r21792: Fix crash bug triggered by Excel reported by Jerry.
[samba.git] / source / smbd / trans2.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB transaction2 handling
4    Copyright (C) Jeremy Allison                 1994-2007
5    Copyright (C) Stefan (metze) Metzmacher      2003
6    Copyright (C) Volker Lendecke                2005
7    Copyright (C) Steve French                   2005
8    Copyright (C) James Peach                    2007
9
10    Extensively modified by Andrew Tridgell, 1995
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 2 of the License, or
15    (at your option) any later version.
16    
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21    
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 */
26
27 #include "includes.h"
28
29 extern int max_send;
30 extern enum protocol_types Protocol;
31 extern int smb_read_error;
32 extern uint32 global_client_caps;
33 extern struct current_user current_user;
34
35 #define get_file_size(sbuf) ((sbuf).st_size)
36 #define DIR_ENTRY_SAFETY_MARGIN 4096
37
38 static char *store_file_unix_basic(connection_struct *conn,
39                                 char *pdata,
40                                 files_struct *fsp,
41                                 const SMB_STRUCT_STAT *psbuf);
42
43 static char *store_file_unix_basic_info2(connection_struct *conn,
44                                 char *pdata,
45                                 files_struct *fsp,
46                                 const SMB_STRUCT_STAT *psbuf);
47
48 /********************************************************************
49  Roundup a value to the nearest allocation roundup size boundary.
50  Only do this for Windows clients.
51 ********************************************************************/
52
53 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
54 {
55         SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
56
57         /* Only roundup for Windows clients. */
58         enum remote_arch_types ra_type = get_remote_arch();
59         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
60                 val = SMB_ROUNDUP(val,rval);
61         }
62         return val;
63 }
64
65 /********************************************************************
66  Given a stat buffer return the allocated size on disk, taking into
67  account sparse files.
68 ********************************************************************/
69
70 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
71 {
72         SMB_BIG_UINT ret;
73
74         if(S_ISDIR(sbuf->st_mode)) {
75                 return 0;
76         }
77
78 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
79         ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
80 #else
81         ret = (SMB_BIG_UINT)get_file_size(*sbuf);
82 #endif
83
84         if (fsp && fsp->initial_allocation_size)
85                 ret = MAX(ret,fsp->initial_allocation_size);
86
87         return smb_roundup(conn, ret);
88 }
89
90 /****************************************************************************
91  Utility functions for dealing with extended attributes.
92 ****************************************************************************/
93
94 static const char *prohibited_ea_names[] = {
95         SAMBA_POSIX_INHERITANCE_EA_NAME,
96         SAMBA_XATTR_DOS_ATTRIB,
97         NULL
98 };
99
100 /****************************************************************************
101  Refuse to allow clients to overwrite our private xattrs.
102 ****************************************************************************/
103
104 static BOOL samba_private_attr_name(const char *unix_ea_name)
105 {
106         int i;
107
108         for (i = 0; prohibited_ea_names[i]; i++) {
109                 if (strequal( prohibited_ea_names[i], unix_ea_name))
110                         return True;
111         }
112         return False;
113 }
114
115 /****************************************************************************
116  Get one EA value. Fill in a struct ea_struct.
117 ****************************************************************************/
118
119 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
120                                 const char *fname, char *ea_name, struct ea_struct *pea)
121 {
122         /* Get the value of this xattr. Max size is 64k. */
123         size_t attr_size = 256;
124         char *val = NULL;
125         ssize_t sizeret;
126
127  again:
128
129         val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
130         if (!val) {
131                 return False;
132         }
133
134         if (fsp && fsp->fh->fd != -1) {
135                 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
136         } else {
137                 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
138         }
139
140         if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
141                 attr_size = 65536;
142                 goto again;
143         }
144
145         if (sizeret == -1) {
146                 return False;
147         }
148
149         DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
150         dump_data(10, val, sizeret);
151
152         pea->flags = 0;
153         if (strnequal(ea_name, "user.", 5)) {
154                 pea->name = &ea_name[5];
155         } else {
156                 pea->name = ea_name;
157         }
158         pea->value.data = (unsigned char *)val;
159         pea->value.length = (size_t)sizeret;
160         return True;
161 }
162
163 /****************************************************************************
164  Return a linked list of the total EA's. Plus the total size
165 ****************************************************************************/
166
167 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
168                                         const char *fname, size_t *pea_total_len)
169 {
170         /* Get a list of all xattrs. Max namesize is 64k. */
171         size_t ea_namelist_size = 1024;
172         char *ea_namelist;
173         char *p;
174         ssize_t sizeret;
175         int i;
176         struct ea_list *ea_list_head = NULL;
177
178         *pea_total_len = 0;
179
180         if (!lp_ea_support(SNUM(conn))) {
181                 return NULL;
182         }
183
184         for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
185              ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
186
187                 if (!ea_namelist) {
188                         return NULL;
189                 }
190
191                 if (fsp && fsp->fh->fd != -1) {
192                         sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
193                 } else {
194                         sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
195                 }
196
197                 if (sizeret == -1 && errno == ERANGE) {
198                         ea_namelist_size *= 2;
199                 } else {
200                         break;
201                 }
202         }
203
204         if (sizeret == -1)
205                 return NULL;
206
207         DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
208
209         if (sizeret) {
210                 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
211                         struct ea_list *listp;
212
213                         if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
214                                 continue;
215                 
216                         listp = TALLOC_P(mem_ctx, struct ea_list);
217                         if (!listp)
218                                 return NULL;
219
220                         if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
221                                 return NULL;
222                         }
223
224                         {
225                                 fstring dos_ea_name;
226                                 push_ascii_fstring(dos_ea_name, listp->ea.name);
227                                 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
228                                 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
229                                         (unsigned int)*pea_total_len, dos_ea_name,
230                                         (unsigned int)listp->ea.value.length ));
231                         }
232                         DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
233                 }
234                 /* Add on 4 for total length. */
235                 if (*pea_total_len) {
236                         *pea_total_len += 4;
237                 }
238         }
239
240         DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
241         return ea_list_head;
242 }
243
244 /****************************************************************************
245  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
246  that was filled.
247 ****************************************************************************/
248
249 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
250         connection_struct *conn, struct ea_list *ea_list)
251 {
252         unsigned int ret_data_size = 4;
253         char *p = pdata;
254
255         SMB_ASSERT(total_data_size >= 4);
256
257         if (!lp_ea_support(SNUM(conn))) {
258                 SIVAL(pdata,4,0);
259                 return 4;
260         }
261
262         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
263                 size_t dos_namelen;
264                 fstring dos_ea_name;
265                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
266                 dos_namelen = strlen(dos_ea_name);
267                 if (dos_namelen > 255 || dos_namelen == 0) {
268                         break;
269                 }
270                 if (ea_list->ea.value.length > 65535) {
271                         break;
272                 }
273                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
274                         break;
275                 }
276
277                 /* We know we have room. */
278                 SCVAL(p,0,ea_list->ea.flags);
279                 SCVAL(p,1,dos_namelen);
280                 SSVAL(p,2,ea_list->ea.value.length);
281                 fstrcpy(p+4, dos_ea_name);
282                 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
283
284                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
285                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
286         }
287
288         ret_data_size = PTR_DIFF(p, pdata);
289         DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
290         SIVAL(pdata,0,ret_data_size);
291         return ret_data_size;
292 }
293
294 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
295 {
296         size_t total_ea_len = 0;
297         TALLOC_CTX *mem_ctx = NULL;
298
299         if (!lp_ea_support(SNUM(conn))) {
300                 return 0;
301         }
302         mem_ctx = talloc_init("estimate_ea_size");
303         (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
304         talloc_destroy(mem_ctx);
305         return total_ea_len;
306 }
307
308 /****************************************************************************
309  Ensure the EA name is case insensitive by matching any existing EA name.
310 ****************************************************************************/
311
312 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
313 {
314         size_t total_ea_len;
315         TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
316         struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
317
318         for (; ea_list; ea_list = ea_list->next) {
319                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
320                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
321                                 &unix_ea_name[5], ea_list->ea.name));
322                         safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
323                         break;
324                 }
325         }
326         talloc_destroy(mem_ctx);
327 }
328
329 /****************************************************************************
330  Set or delete an extended attribute.
331 ****************************************************************************/
332
333 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
334 {
335         if (!lp_ea_support(SNUM(conn))) {
336                 return NT_STATUS_EAS_NOT_SUPPORTED;
337         }
338
339         for (;ea_list; ea_list = ea_list->next) {
340                 int ret;
341                 fstring unix_ea_name;
342
343                 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
344                 fstrcat(unix_ea_name, ea_list->ea.name);
345
346                 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
347
348                 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
349
350                 if (samba_private_attr_name(unix_ea_name)) {
351                         DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
352                         return NT_STATUS_ACCESS_DENIED;
353                 }
354
355                 if (ea_list->ea.value.length == 0) {
356                         /* Remove the attribute. */
357                         if (fsp && (fsp->fh->fd != -1)) {
358                                 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
359                                         unix_ea_name, fsp->fsp_name));
360                                 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
361                         } else {
362                                 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
363                                         unix_ea_name, fname));
364                                 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
365                         }
366 #ifdef ENOATTR
367                         /* Removing a non existent attribute always succeeds. */
368                         if (ret == -1 && errno == ENOATTR) {
369                                 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
370                                                 unix_ea_name));
371                                 ret = 0;
372                         }
373 #endif
374                 } else {
375                         if (fsp && (fsp->fh->fd != -1)) {
376                                 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
377                                         unix_ea_name, fsp->fsp_name));
378                                 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
379                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
380                         } else {
381                                 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
382                                         unix_ea_name, fname));
383                                 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
384                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
385                         }
386                 }
387
388                 if (ret == -1) {
389 #ifdef ENOTSUP
390                         if (errno == ENOTSUP) {
391                                 return NT_STATUS_EAS_NOT_SUPPORTED;
392                         }
393 #endif
394                         return map_nt_error_from_unix(errno);
395                 }
396
397         }
398         return NT_STATUS_OK;
399 }
400 /****************************************************************************
401  Read a list of EA names from an incoming data buffer. Create an ea_list with them.
402 ****************************************************************************/
403
404 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
405 {
406         struct ea_list *ea_list_head = NULL;
407         size_t offset = 0;
408
409         while (offset + 2 < data_size) {
410                 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
411                 unsigned int namelen = CVAL(pdata,offset);
412
413                 offset++; /* Go past the namelen byte. */
414
415                 /* integer wrap paranioa. */
416                 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
417                                 (offset > data_size) || (namelen > data_size) ||
418                                 (offset + namelen >= data_size)) {
419                         break;
420                 }
421                 /* Ensure the name is null terminated. */
422                 if (pdata[offset + namelen] != '\0') {
423                         return NULL;
424                 }
425                 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
426                 if (!eal->ea.name) {
427                         return NULL;
428                 }
429
430                 offset += (namelen + 1); /* Go past the name + terminating zero. */
431                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
432                 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
433         }
434
435         return ea_list_head;
436 }
437
438 /****************************************************************************
439  Read one EA list entry from the buffer.
440 ****************************************************************************/
441
442 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
443 {
444         struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
445         uint16 val_len;
446         unsigned int namelen;
447
448         if (!eal) {
449                 return NULL;
450         }
451
452         if (data_size < 6) {
453                 return NULL;
454         }
455
456         eal->ea.flags = CVAL(pdata,0);
457         namelen = CVAL(pdata,1);
458         val_len = SVAL(pdata,2);
459
460         if (4 + namelen + 1 + val_len > data_size) {
461                 return NULL;
462         }
463
464         /* Ensure the name is null terminated. */
465         if (pdata[namelen + 4] != '\0') {
466                 return NULL;
467         }
468         pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
469         if (!eal->ea.name) {
470                 return NULL;
471         }
472
473         eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
474         if (!eal->ea.value.data) {
475                 return NULL;
476         }
477
478         memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
479
480         /* Ensure we're null terminated just in case we print the value. */
481         eal->ea.value.data[val_len] = '\0';
482         /* But don't count the null. */
483         eal->ea.value.length--;
484
485         if (pbytes_used) {
486                 *pbytes_used = 4 + namelen + 1 + val_len;
487         }
488
489         DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
490         dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
491
492         return eal;
493 }
494
495 /****************************************************************************
496  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
497 ****************************************************************************/
498
499 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
500 {
501         struct ea_list *ea_list_head = NULL;
502         size_t offset = 0;
503         size_t bytes_used = 0;
504
505         while (offset < data_size) {
506                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
507
508                 if (!eal) {
509                         return NULL;
510                 }
511
512                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
513                 offset += bytes_used;
514         }
515
516         return ea_list_head;
517 }
518
519 /****************************************************************************
520  Count the total EA size needed.
521 ****************************************************************************/
522
523 static size_t ea_list_size(struct ea_list *ealist)
524 {
525         fstring dos_ea_name;
526         struct ea_list *listp;
527         size_t ret = 0;
528
529         for (listp = ealist; listp; listp = listp->next) {
530                 push_ascii_fstring(dos_ea_name, listp->ea.name);
531                 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
532         }
533         /* Add on 4 for total length. */
534         if (ret) {
535                 ret += 4;
536         }
537
538         return ret;
539 }
540
541 /****************************************************************************
542  Return a union of EA's from a file list and a list of names.
543  The TALLOC context for the two lists *MUST* be identical as we steal
544  memory from one list to add to another. JRA.
545 ****************************************************************************/
546
547 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
548 {
549         struct ea_list *nlistp, *flistp;
550
551         for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
552                 for (flistp = file_list; flistp; flistp = flistp->next) {
553                         if (strequal(nlistp->ea.name, flistp->ea.name)) {
554                                 break;
555                         }
556                 }
557
558                 if (flistp) {
559                         /* Copy the data from this entry. */
560                         nlistp->ea.flags = flistp->ea.flags;
561                         nlistp->ea.value = flistp->ea.value;
562                 } else {
563                         /* Null entry. */
564                         nlistp->ea.flags = 0;
565                         ZERO_STRUCT(nlistp->ea.value);
566                 }
567         }
568
569         *total_ea_len = ea_list_size(name_list);
570         return name_list;
571 }
572
573 /****************************************************************************
574   Send the required number of replies back.
575   We assume all fields other than the data fields are
576   set correctly for the type of call.
577   HACK ! Always assumes smb_setup field is zero.
578 ****************************************************************************/
579
580 int send_trans2_replies(char *outbuf,
581                         int bufsize,
582                         const char *params, 
583                         int paramsize,
584                         const char *pdata,
585                         int datasize,
586                         int max_data_bytes)
587 {
588         /* As we are using a protocol > LANMAN1 then the max_send
589          variable must have been set in the sessetupX call.
590          This takes precedence over the max_xmit field in the
591          global struct. These different max_xmit variables should
592          be merged as this is now too confusing */
593
594         int data_to_send = datasize;
595         int params_to_send = paramsize;
596         int useable_space;
597         const char *pp = params;
598         const char *pd = pdata;
599         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
600         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
601         int data_alignment_offset = 0;
602
603         /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
604         
605         set_message(outbuf,10,0,True);
606
607         /* Modify the data_to_send and datasize and set the error if
608            we're trying to send more than max_data_bytes. We still send
609            the part of the packet(s) that fit. Strange, but needed
610            for OS/2. */
611
612         if (max_data_bytes > 0 && datasize > max_data_bytes) {
613                 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
614                         max_data_bytes, datasize ));
615                 datasize = data_to_send = max_data_bytes;
616                 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
617         }
618
619         /* If there genuinely are no parameters or data to send just send the empty packet */
620
621         if(params_to_send == 0 && data_to_send == 0) {
622                 show_msg(outbuf);
623                 if (!send_smb(smbd_server_fd(),outbuf))
624                         exit_server_cleanly("send_trans2_replies: send_smb failed.");
625                 return 0;
626         }
627
628         /* When sending params and data ensure that both are nicely aligned */
629         /* Only do this alignment when there is also data to send - else
630                 can cause NT redirector problems. */
631
632         if (((params_to_send % 4) != 0) && (data_to_send != 0))
633                 data_alignment_offset = 4 - (params_to_send % 4);
634
635         /* Space is bufsize minus Netbios over TCP header minus SMB header */
636         /* The alignment_offset is to align the param bytes on an even byte
637                 boundary. NT 4.0 Beta needs this to work correctly. */
638
639         useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
640
641         /* useable_space can never be more than max_send minus the alignment offset. */
642
643         useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
644
645         while (params_to_send || data_to_send) {
646                 /* Calculate whether we will totally or partially fill this packet */
647
648                 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
649
650                 /* We can never send more than useable_space */
651                 /*
652                  * Note that 'useable_space' does not include the alignment offsets,
653                  * but we must include the alignment offsets in the calculation of
654                  * the length of the data we send over the wire, as the alignment offsets
655                  * are sent here. Fix from Marc_Jacobsen@hp.com.
656                  */
657
658                 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
659
660                 set_message(outbuf, 10, total_sent_thistime, True);
661
662                 /* Set total params and data to be sent */
663                 SSVAL(outbuf,smb_tprcnt,paramsize);
664                 SSVAL(outbuf,smb_tdrcnt,datasize);
665
666                 /* Calculate how many parameters and data we can fit into
667                  * this packet. Parameters get precedence
668                  */
669
670                 params_sent_thistime = MIN(params_to_send,useable_space);
671                 data_sent_thistime = useable_space - params_sent_thistime;
672                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
673
674                 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
675
676                 /* smb_proff is the offset from the start of the SMB header to the
677                         parameter bytes, however the first 4 bytes of outbuf are
678                         the Netbios over TCP header. Thus use smb_base() to subtract
679                         them from the calculation */
680
681                 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
682
683                 if(params_sent_thistime == 0)
684                         SSVAL(outbuf,smb_prdisp,0);
685                 else
686                         /* Absolute displacement of param bytes sent in this packet */
687                         SSVAL(outbuf,smb_prdisp,pp - params);
688
689                 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
690                 if(data_sent_thistime == 0) {
691                         SSVAL(outbuf,smb_droff,0);
692                         SSVAL(outbuf,smb_drdisp, 0);
693                 } else {
694                         /* The offset of the data bytes is the offset of the
695                                 parameter bytes plus the number of parameters being sent this time */
696                         SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
697                                 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
698                         SSVAL(outbuf,smb_drdisp, pd - pdata);
699                 }
700
701                 /* Copy the param bytes into the packet */
702
703                 if(params_sent_thistime)
704                         memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
705
706                 /* Copy in the data bytes */
707                 if(data_sent_thistime)
708                         memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
709                                 data_alignment_offset,pd,data_sent_thistime);
710
711                 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
712                         params_sent_thistime, data_sent_thistime, useable_space));
713                 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
714                         params_to_send, data_to_send, paramsize, datasize));
715
716                 /* Send the packet */
717                 show_msg(outbuf);
718                 if (!send_smb(smbd_server_fd(),outbuf))
719                         exit_server_cleanly("send_trans2_replies: send_smb failed.");
720
721                 pp += params_sent_thistime;
722                 pd += data_sent_thistime;
723
724                 params_to_send -= params_sent_thistime;
725                 data_to_send -= data_sent_thistime;
726
727                 /* Sanity check */
728                 if(params_to_send < 0 || data_to_send < 0) {
729                         DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
730                                 params_to_send, data_to_send));
731                         return -1;
732                 }
733         }
734
735         return 0;
736 }
737
738 /****************************************************************************
739  Reply to a TRANSACT2_OPEN.
740 ****************************************************************************/
741
742 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
743                                 char **pparams, int total_params, char **ppdata, int total_data,
744                                 unsigned int max_data_bytes)
745 {
746         char *params = *pparams;
747         char *pdata = *ppdata;
748         int deny_mode;
749         int32 open_attr;
750         BOOL oplock_request;
751 #if 0
752         BOOL return_additional_info;
753         int16 open_sattr;
754         time_t open_time;
755 #endif
756         int open_ofun;
757         uint32 open_size;
758         char *pname;
759         pstring fname;
760         SMB_OFF_T size=0;
761         int fattr=0,mtime=0;
762         SMB_INO_T inode = 0;
763         SMB_STRUCT_STAT sbuf;
764         int smb_action = 0;
765         files_struct *fsp;
766         struct ea_list *ea_list = NULL;
767         uint16 flags = 0;
768         NTSTATUS status;
769         uint32 access_mask;
770         uint32 share_mode;
771         uint32 create_disposition;
772         uint32 create_options = 0;
773
774         /*
775          * Ensure we have enough parameters to perform the operation.
776          */
777
778         if (total_params < 29) {
779                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
780         }
781
782         flags = SVAL(params, 0);
783         deny_mode = SVAL(params, 2);
784         open_attr = SVAL(params,6);
785         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
786         if (oplock_request) {
787                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
788         }
789
790 #if 0
791         return_additional_info = BITSETW(params,0);
792         open_sattr = SVAL(params, 4);
793         open_time = make_unix_date3(params+8);
794 #endif
795         open_ofun = SVAL(params,12);
796         open_size = IVAL(params,14);
797         pname = &params[28];
798
799         if (IS_IPC(conn)) {
800                 return(ERROR_DOS(ERRSRV,ERRaccess));
801         }
802
803         srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
804         if (!NT_STATUS_IS_OK(status)) {
805                 return ERROR_NT(status);
806         }
807
808         DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
809                 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
810                 (unsigned int)open_ofun, open_size));
811
812         /* XXXX we need to handle passed times, sattr and flags */
813
814         status = unix_convert(conn, fname, False, NULL, &sbuf);
815         if (!NT_STATUS_IS_OK(status)) {
816                 return ERROR_NT(status);
817         }
818     
819         status = check_name(conn, fname);
820         if (!NT_STATUS_IS_OK(status)) {
821                 return ERROR_NT(status);
822         }
823
824         if (open_ofun == 0) {
825                 return ERROR_NT(NT_STATUS_OBJECT_NAME_COLLISION);
826         }
827
828         if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
829                                 &access_mask,
830                                 &share_mode,
831                                 &create_disposition,
832                                 &create_options)) {
833                 return ERROR_DOS(ERRDOS, ERRbadaccess);
834         }
835
836         /* Any data in this call is an EA list. */
837         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
838                 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
839         }
840
841         if (total_data != 4) {
842                 if (total_data < 10) {
843                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
844                 }
845
846                 if (IVAL(pdata,0) > total_data) {
847                         DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
848                                 IVAL(pdata,0), (unsigned int)total_data));
849                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
850                 }
851
852                 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
853                                        total_data - 4);
854                 if (!ea_list) {
855                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
856                 }
857         } else if (IVAL(pdata,0) != 4) {
858                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
859         }
860
861         status = open_file_ntcreate(conn,fname,&sbuf,
862                 access_mask,
863                 share_mode,
864                 create_disposition,
865                 create_options,
866                 open_attr,
867                 oplock_request,
868                 &smb_action, &fsp);
869       
870         if (!NT_STATUS_IS_OK(status)) {
871                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
872                         /* We have re-scheduled this call. */
873                         return -1;
874                 }
875                 return ERROR_NT(status);
876         }
877
878         size = get_file_size(sbuf);
879         fattr = dos_mode(conn,fname,&sbuf);
880         mtime = sbuf.st_mtime;
881         inode = sbuf.st_ino;
882         if (fattr & aDIR) {
883                 close_file(fsp,ERROR_CLOSE);
884                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
885         }
886
887         /* Save the requested allocation size. */
888         /* Allocate space for the file if a size hint is supplied */
889         if ((smb_action == FILE_WAS_CREATED) || (smb_action == FILE_WAS_OVERWRITTEN)) {
890                 SMB_BIG_UINT allocation_size = (SMB_BIG_UINT)open_size;
891                 if (allocation_size && (allocation_size > (SMB_BIG_UINT)size)) {
892                         fsp->initial_allocation_size = smb_roundup(fsp->conn, allocation_size);
893                         if (fsp->is_directory) {
894                                 close_file(fsp,ERROR_CLOSE);
895                                 /* Can't set allocation size on a directory. */
896                                 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
897                         }
898                         if (vfs_allocate_file_space(fsp, fsp->initial_allocation_size) == -1) {
899                                 close_file(fsp,ERROR_CLOSE);
900                                 return ERROR_NT(NT_STATUS_DISK_FULL);
901                         }
902
903                         /* Adjust size here to return the right size in the reply.
904                            Windows does it this way. */
905                         size = fsp->initial_allocation_size;
906                 } else {
907                         fsp->initial_allocation_size = smb_roundup(fsp->conn,(SMB_BIG_UINT)size);
908                 }
909         }
910
911         if (ea_list && smb_action == FILE_WAS_CREATED) {
912                 status = set_ea(conn, fsp, fname, ea_list);
913                 if (!NT_STATUS_IS_OK(status)) {
914                         close_file(fsp,ERROR_CLOSE);
915                         return ERROR_NT(status);
916                 }
917         }
918
919         /* Realloc the size of parameters and data we will return */
920         *pparams = (char *)SMB_REALLOC(*pparams, 30);
921         if(*pparams == NULL ) {
922                 return ERROR_NT(NT_STATUS_NO_MEMORY);
923         }
924         params = *pparams;
925
926         SSVAL(params,0,fsp->fnum);
927         SSVAL(params,2,fattr);
928         srv_put_dos_date2(params,4, mtime);
929         SIVAL(params,8, (uint32)size);
930         SSVAL(params,12,deny_mode);
931         SSVAL(params,14,0); /* open_type - file or directory. */
932         SSVAL(params,16,0); /* open_state - only valid for IPC device. */
933
934         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
935                 smb_action |= EXTENDED_OPLOCK_GRANTED;
936         }
937
938         SSVAL(params,18,smb_action);
939
940         /*
941          * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
942          */
943         SIVAL(params,20,inode);
944         SSVAL(params,24,0); /* Padding. */
945         if (flags & 8) {
946                 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
947                 SIVAL(params, 26, ea_size);
948         } else {
949                 SIVAL(params, 26, 0);
950         }
951
952         /* Send the required number of replies */
953         send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
954
955         return -1;
956 }
957
958 /*********************************************************
959  Routine to check if a given string matches exactly.
960  as a special case a mask of "." does NOT match. That
961  is required for correct wildcard semantics
962  Case can be significant or not.
963 **********************************************************/
964
965 static BOOL exact_match(connection_struct *conn, char *str, char *mask)
966 {
967         if (mask[0] == '.' && mask[1] == 0)
968                 return False;
969         if (conn->case_sensitive)
970                 return strcmp(str,mask)==0;
971         if (StrCaseCmp(str,mask) != 0) {
972                 return False;
973         }
974         if (dptr_has_wild(conn->dirptr)) {
975                 return False;
976         }
977         return True;
978 }
979
980 /****************************************************************************
981  Return the filetype for UNIX extensions.
982 ****************************************************************************/
983
984 static uint32 unix_filetype(mode_t mode)
985 {
986         if(S_ISREG(mode))
987                 return UNIX_TYPE_FILE;
988         else if(S_ISDIR(mode))
989                 return UNIX_TYPE_DIR;
990 #ifdef S_ISLNK
991         else if(S_ISLNK(mode))
992                 return UNIX_TYPE_SYMLINK;
993 #endif
994 #ifdef S_ISCHR
995         else if(S_ISCHR(mode))
996                 return UNIX_TYPE_CHARDEV;
997 #endif
998 #ifdef S_ISBLK
999         else if(S_ISBLK(mode))
1000                 return UNIX_TYPE_BLKDEV;
1001 #endif
1002 #ifdef S_ISFIFO
1003         else if(S_ISFIFO(mode))
1004                 return UNIX_TYPE_FIFO;
1005 #endif
1006 #ifdef S_ISSOCK
1007         else if(S_ISSOCK(mode))
1008                 return UNIX_TYPE_SOCKET;
1009 #endif
1010
1011         DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1012         return UNIX_TYPE_UNKNOWN;
1013 }
1014
1015 /****************************************************************************
1016  Map wire perms onto standard UNIX permissions. Obey share restrictions.
1017 ****************************************************************************/
1018
1019 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1020
1021 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1022                                 SMB_STRUCT_STAT *psbuf,
1023                                 uint32 perms,
1024                                 enum perm_type ptype,
1025                                 mode_t *ret_perms)
1026 {
1027         mode_t ret = 0;
1028
1029         if (perms == SMB_MODE_NO_CHANGE) {
1030                 if (!VALID_STAT(*psbuf)) {
1031                         return NT_STATUS_INVALID_PARAMETER;
1032                 } else {
1033                         *ret_perms = psbuf->st_mode;
1034                         return NT_STATUS_OK;
1035                 }
1036         }
1037
1038         ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1039         ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1040         ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1041         ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1042         ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1043         ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1044         ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1045         ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1046         ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1047 #ifdef S_ISVTX
1048         ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1049 #endif
1050 #ifdef S_ISGID
1051         ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1052 #endif
1053 #ifdef S_ISUID
1054         ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1055 #endif
1056
1057         switch (ptype) {
1058         case PERM_NEW_FILE:
1059                 /* Apply mode mask */
1060                 ret &= lp_create_mask(SNUM(conn));
1061                 /* Add in force bits */
1062                 ret |= lp_force_create_mode(SNUM(conn));
1063                 break;
1064         case PERM_NEW_DIR:
1065                 ret &= lp_dir_mask(SNUM(conn));
1066                 /* Add in force bits */
1067                 ret |= lp_force_dir_mode(SNUM(conn));
1068                 break;
1069         case PERM_EXISTING_FILE:
1070                 /* Apply mode mask */
1071                 ret &= lp_security_mask(SNUM(conn));
1072                 /* Add in force bits */
1073                 ret |= lp_force_security_mode(SNUM(conn));
1074                 break;
1075         case PERM_EXISTING_DIR:
1076                 /* Apply mode mask */
1077                 ret &= lp_dir_security_mask(SNUM(conn));
1078                 /* Add in force bits */
1079                 ret |= lp_force_dir_security_mode(SNUM(conn));
1080                 break;
1081         }
1082
1083         *ret_perms = ret;
1084         return NT_STATUS_OK;
1085 }
1086
1087 /****************************************************************************
1088  Get a level dependent lanman2 dir entry.
1089 ****************************************************************************/
1090
1091 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1092                                   void *inbuf, char *outbuf,
1093                                  char *path_mask,uint32 dirtype,int info_level,
1094                                  int requires_resume_key,
1095                                  BOOL dont_descend,char **ppdata, 
1096                                  char *base_data, int space_remaining, 
1097                                  BOOL *out_of_space, BOOL *got_exact_match,
1098                                  int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1099 {
1100         const char *dname;
1101         BOOL found = False;
1102         SMB_STRUCT_STAT sbuf;
1103         pstring mask;
1104         pstring pathreal;
1105         pstring fname;
1106         char *p, *q, *pdata = *ppdata;
1107         uint32 reskey=0;
1108         long prev_dirpos=0;
1109         uint32 mode=0;
1110         SMB_OFF_T file_size = 0;
1111         SMB_BIG_UINT allocation_size = 0;
1112         uint32 len;
1113         struct timespec mdate_ts, adate_ts, create_date_ts;
1114         time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1115         char *nameptr;
1116         char *last_entry_ptr;
1117         BOOL was_8_3;
1118         uint32 nt_extmode; /* Used for NT connections instead of mode */
1119         BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1120         BOOL check_mangled_names = lp_manglednames(conn->params);
1121
1122         *fname = 0;
1123         *out_of_space = False;
1124         *got_exact_match = False;
1125
1126         ZERO_STRUCT(mdate_ts);
1127         ZERO_STRUCT(adate_ts);
1128         ZERO_STRUCT(create_date_ts);
1129
1130         if (!conn->dirptr)
1131                 return(False);
1132
1133         p = strrchr_m(path_mask,'/');
1134         if(p != NULL) {
1135                 if(p[1] == '\0')
1136                         pstrcpy(mask,"*.*");
1137                 else
1138                         pstrcpy(mask, p+1);
1139         } else
1140                 pstrcpy(mask, path_mask);
1141
1142
1143         while (!found) {
1144                 BOOL got_match;
1145                 BOOL ms_dfs_link = False;
1146
1147                 /* Needed if we run out of space */
1148                 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1149                 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1150
1151                 /*
1152                  * Due to bugs in NT client redirectors we are not using
1153                  * resume keys any more - set them to zero.
1154                  * Check out the related comments in findfirst/findnext.
1155                  * JRA.
1156                  */
1157
1158                 reskey = 0;
1159
1160                 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1161                         (long)conn->dirptr,curr_dirpos));
1162       
1163                 if (!dname) 
1164                         return(False);
1165
1166                 pstrcpy(fname,dname);      
1167
1168                 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
1169                         got_match = mask_match(fname, mask, conn->case_sensitive);
1170
1171                 if(!got_match && check_mangled_names &&
1172                    !mangle_is_8_3(fname, False, conn->params)) {
1173
1174                         /*
1175                          * It turns out that NT matches wildcards against
1176                          * both long *and* short names. This may explain some
1177                          * of the wildcard wierdness from old DOS clients
1178                          * that some people have been seeing.... JRA.
1179                          */
1180
1181                         pstring newname;
1182                         pstrcpy( newname, fname);
1183                         mangle_map( newname, True, False, conn->params);
1184                         if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
1185                                 got_match = mask_match(newname, mask, conn->case_sensitive);
1186                 }
1187
1188                 if(got_match) {
1189                         BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1190                         if (dont_descend && !isdots)
1191                                 continue;
1192           
1193                         pstrcpy(pathreal,conn->dirpath);
1194                         if(needslash)
1195                                 pstrcat(pathreal,"/");
1196                         pstrcat(pathreal,dname);
1197
1198                         if (INFO_LEVEL_IS_UNIX(info_level)) {
1199                                 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1200                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1201                                                 pathreal,strerror(errno)));
1202                                         continue;
1203                                 }
1204                         } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1205
1206                                 /* Needed to show the msdfs symlinks as 
1207                                  * directories */
1208
1209                                 if(lp_host_msdfs() && 
1210                                    lp_msdfs_root(SNUM(conn)) &&
1211                                    ((ms_dfs_link = is_msdfs_link(NULL,conn, pathreal, NULL, NULL, &sbuf)) == True)) {
1212
1213                                         DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1214                                         sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1215
1216                                 } else {
1217
1218                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1219                                                 pathreal,strerror(errno)));
1220                                         continue;
1221                                 }
1222                         }
1223
1224                         if (ms_dfs_link) {
1225                                 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1226                         } else {
1227                                 mode = dos_mode(conn,pathreal,&sbuf);
1228                         }
1229
1230                         if (!dir_check_ftype(conn,mode,dirtype)) {
1231                                 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1232                                 continue;
1233                         }
1234
1235                         if (!(mode & aDIR))
1236                                 file_size = get_file_size(sbuf);
1237                         allocation_size = get_allocation_size(conn,NULL,&sbuf);
1238
1239                         mdate_ts = get_mtimespec(&sbuf);
1240                         adate_ts = get_atimespec(&sbuf);
1241                         create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1242
1243                         if (lp_dos_filetime_resolution(SNUM(conn))) {
1244                                 dos_filetime_timespec(&create_date_ts);
1245                                 dos_filetime_timespec(&mdate_ts);
1246                                 dos_filetime_timespec(&adate_ts);
1247                         }
1248
1249                         create_date = convert_timespec_to_time_t(create_date_ts);
1250                         mdate = convert_timespec_to_time_t(mdate_ts);
1251                         adate = convert_timespec_to_time_t(adate_ts);
1252                         
1253                         DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1254           
1255                         found = True;
1256
1257                         dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1258                 }
1259         }
1260
1261         mangle_map(fname,False,True,conn->params);
1262
1263         p = pdata;
1264         last_entry_ptr = p;
1265
1266         nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1267
1268         switch (info_level) {
1269                 case SMB_FIND_INFO_STANDARD:
1270                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1271                         if(requires_resume_key) {
1272                                 SIVAL(p,0,reskey);
1273                                 p += 4;
1274                         }
1275                         srv_put_dos_date2(p,0,create_date);
1276                         srv_put_dos_date2(p,4,adate);
1277                         srv_put_dos_date2(p,8,mdate);
1278                         SIVAL(p,12,(uint32)file_size);
1279                         SIVAL(p,16,(uint32)allocation_size);
1280                         SSVAL(p,20,mode);
1281                         p += 23;
1282                         nameptr = p;
1283                         p += align_string(outbuf, p, 0);
1284                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1285                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1286                                 if (len > 2) {
1287                                         SCVAL(nameptr, -1, len - 2);
1288                                 } else {
1289                                         SCVAL(nameptr, -1, 0);
1290                                 }
1291                         } else {
1292                                 if (len > 1) {
1293                                         SCVAL(nameptr, -1, len - 1);
1294                                 } else {
1295                                         SCVAL(nameptr, -1, 0);
1296                                 }
1297                         }
1298                         p += len;
1299                         break;
1300
1301                 case SMB_FIND_EA_SIZE:
1302                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1303                         if(requires_resume_key) {
1304                                 SIVAL(p,0,reskey);
1305                                 p += 4;
1306                         }
1307                         srv_put_dos_date2(p,0,create_date);
1308                         srv_put_dos_date2(p,4,adate);
1309                         srv_put_dos_date2(p,8,mdate);
1310                         SIVAL(p,12,(uint32)file_size);
1311                         SIVAL(p,16,(uint32)allocation_size);
1312                         SSVAL(p,20,mode);
1313                         {
1314                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1315                                 SIVAL(p,22,ea_size); /* Extended attributes */
1316                         }
1317                         p += 27;
1318                         nameptr = p - 1;
1319                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1320                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1321                                 if (len > 2) {
1322                                         len -= 2;
1323                                 } else {
1324                                         len = 0;
1325                                 }
1326                         } else {
1327                                 if (len > 1) {
1328                                         len -= 1;
1329                                 } else {
1330                                         len = 0;
1331                                 }
1332                         }
1333                         SCVAL(nameptr,0,len);
1334                         p += len;
1335                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1336                         break;
1337
1338                 case SMB_FIND_EA_LIST:
1339                 {
1340                         struct ea_list *file_list = NULL;
1341                         size_t ea_len = 0;
1342
1343                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1344                         if (!name_list) {
1345                                 return False;
1346                         }
1347                         if(requires_resume_key) {
1348                                 SIVAL(p,0,reskey);
1349                                 p += 4;
1350                         }
1351                         srv_put_dos_date2(p,0,create_date);
1352                         srv_put_dos_date2(p,4,adate);
1353                         srv_put_dos_date2(p,8,mdate);
1354                         SIVAL(p,12,(uint32)file_size);
1355                         SIVAL(p,16,(uint32)allocation_size);
1356                         SSVAL(p,20,mode);
1357                         p += 22; /* p now points to the EA area. */
1358
1359                         file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1360                         name_list = ea_list_union(name_list, file_list, &ea_len);
1361
1362                         /* We need to determine if this entry will fit in the space available. */
1363                         /* Max string size is 255 bytes. */
1364                         if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1365                                 /* Move the dirptr back to prev_dirpos */
1366                                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1367                                 *out_of_space = True;
1368                                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1369                                 return False; /* Not finished - just out of space */
1370                         }
1371
1372                         /* Push the ea_data followed by the name. */
1373                         p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1374                         nameptr = p;
1375                         len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1376                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1377                                 if (len > 2) {
1378                                         len -= 2;
1379                                 } else {
1380                                         len = 0;
1381                                 }
1382                         } else {
1383                                 if (len > 1) {
1384                                         len -= 1;
1385                                 } else {
1386                                         len = 0;
1387                                 }
1388                         }
1389                         SCVAL(nameptr,0,len);
1390                         p += len + 1;
1391                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1392                         break;
1393                 }
1394
1395                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1396                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1397                         was_8_3 = mangle_is_8_3(fname, True, conn->params);
1398                         p += 4;
1399                         SIVAL(p,0,reskey); p += 4;
1400                         put_long_date_timespec(p,create_date_ts); p += 8;
1401                         put_long_date_timespec(p,adate_ts); p += 8;
1402                         put_long_date_timespec(p,mdate_ts); p += 8;
1403                         put_long_date_timespec(p,mdate_ts); p += 8;
1404                         SOFF_T(p,0,file_size); p += 8;
1405                         SOFF_T(p,0,allocation_size); p += 8;
1406                         SIVAL(p,0,nt_extmode); p += 4;
1407                         q = p; p += 4; /* q is placeholder for name length. */
1408                         {
1409                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1410                                 SIVAL(p,0,ea_size); /* Extended attributes */
1411                                 p += 4;
1412                         }
1413                         /* Clear the short name buffer. This is
1414                          * IMPORTANT as not doing so will trigger
1415                          * a Win2k client bug. JRA.
1416                          */
1417                         if (!was_8_3 && check_mangled_names) {
1418                                 pstring mangled_name;
1419                                 pstrcpy(mangled_name, fname);
1420                                 mangle_map(mangled_name,True,True,
1421                                            conn->params);
1422                                 mangled_name[12] = 0;
1423                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1424                                 if (len < 24) {
1425                                         memset(p + 2 + len,'\0',24 - len);
1426                                 }
1427                                 SSVAL(p, 0, len);
1428                         } else {
1429                                 memset(p,'\0',26);
1430                         }
1431                         p += 2 + 24;
1432                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1433                         SIVAL(q,0,len);
1434                         p += len;
1435                         SIVAL(p,0,0); /* Ensure any padding is null. */
1436                         len = PTR_DIFF(p, pdata);
1437                         len = (len + 3) & ~3;
1438                         SIVAL(pdata,0,len);
1439                         p = pdata + len;
1440                         break;
1441
1442                 case SMB_FIND_FILE_DIRECTORY_INFO:
1443                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1444                         p += 4;
1445                         SIVAL(p,0,reskey); p += 4;
1446                         put_long_date_timespec(p,create_date_ts); p += 8;
1447                         put_long_date_timespec(p,adate_ts); p += 8;
1448                         put_long_date_timespec(p,mdate_ts); p += 8;
1449                         put_long_date_timespec(p,mdate_ts); p += 8;
1450                         SOFF_T(p,0,file_size); p += 8;
1451                         SOFF_T(p,0,allocation_size); p += 8;
1452                         SIVAL(p,0,nt_extmode); p += 4;
1453                         len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1454                         SIVAL(p,0,len);
1455                         p += 4 + len;
1456                         SIVAL(p,0,0); /* Ensure any padding is null. */
1457                         len = PTR_DIFF(p, pdata);
1458                         len = (len + 3) & ~3;
1459                         SIVAL(pdata,0,len);
1460                         p = pdata + len;
1461                         break;
1462       
1463                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1464                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1465                         p += 4;
1466                         SIVAL(p,0,reskey); p += 4;
1467                         put_long_date_timespec(p,create_date_ts); p += 8;
1468                         put_long_date_timespec(p,adate_ts); p += 8;
1469                         put_long_date_timespec(p,mdate_ts); p += 8;
1470                         put_long_date_timespec(p,mdate_ts); p += 8;
1471                         SOFF_T(p,0,file_size); p += 8;
1472                         SOFF_T(p,0,allocation_size); p += 8;
1473                         SIVAL(p,0,nt_extmode); p += 4;
1474                         q = p; p += 4; /* q is placeholder for name length. */
1475                         {
1476                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1477                                 SIVAL(p,0,ea_size); /* Extended attributes */
1478                                 p +=4;
1479                         }
1480                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1481                         SIVAL(q, 0, len);
1482                         p += len;
1483
1484                         SIVAL(p,0,0); /* Ensure any padding is null. */
1485                         len = PTR_DIFF(p, pdata);
1486                         len = (len + 3) & ~3;
1487                         SIVAL(pdata,0,len);
1488                         p = pdata + len;
1489                         break;
1490
1491                 case SMB_FIND_FILE_NAMES_INFO:
1492                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1493                         p += 4;
1494                         SIVAL(p,0,reskey); p += 4;
1495                         p += 4;
1496                         /* this must *not* be null terminated or w2k gets in a loop trying to set an
1497                            acl on a dir (tridge) */
1498                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1499                         SIVAL(p, -4, len);
1500                         p += len;
1501                         SIVAL(p,0,0); /* Ensure any padding is null. */
1502                         len = PTR_DIFF(p, pdata);
1503                         len = (len + 3) & ~3;
1504                         SIVAL(pdata,0,len);
1505                         p = pdata + len;
1506                         break;
1507
1508                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1509                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1510                         p += 4;
1511                         SIVAL(p,0,reskey); p += 4;
1512                         put_long_date_timespec(p,create_date_ts); p += 8;
1513                         put_long_date_timespec(p,adate_ts); p += 8;
1514                         put_long_date_timespec(p,mdate_ts); p += 8;
1515                         put_long_date_timespec(p,mdate_ts); p += 8;
1516                         SOFF_T(p,0,file_size); p += 8;
1517                         SOFF_T(p,0,allocation_size); p += 8;
1518                         SIVAL(p,0,nt_extmode); p += 4;
1519                         q = p; p += 4; /* q is placeholder for name length. */
1520                         {
1521                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1522                                 SIVAL(p,0,ea_size); /* Extended attributes */
1523                                 p +=4;
1524                         }
1525                         SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1526                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1527                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1528                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1529                         SIVAL(q, 0, len);
1530                         p += len; 
1531                         SIVAL(p,0,0); /* Ensure any padding is null. */
1532                         len = PTR_DIFF(p, pdata);
1533                         len = (len + 3) & ~3;
1534                         SIVAL(pdata,0,len);
1535                         p = pdata + len;
1536                         break;
1537
1538                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1539                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1540                         was_8_3 = mangle_is_8_3(fname, True, conn->params);
1541                         p += 4;
1542                         SIVAL(p,0,reskey); p += 4;
1543                         put_long_date_timespec(p,create_date_ts); p += 8;
1544                         put_long_date_timespec(p,adate_ts); p += 8;
1545                         put_long_date_timespec(p,mdate_ts); p += 8;
1546                         put_long_date_timespec(p,mdate_ts); p += 8;
1547                         SOFF_T(p,0,file_size); p += 8;
1548                         SOFF_T(p,0,allocation_size); p += 8;
1549                         SIVAL(p,0,nt_extmode); p += 4;
1550                         q = p; p += 4; /* q is placeholder for name length */
1551                         {
1552                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1553                                 SIVAL(p,0,ea_size); /* Extended attributes */
1554                                 p +=4;
1555                         }
1556                         /* Clear the short name buffer. This is
1557                          * IMPORTANT as not doing so will trigger
1558                          * a Win2k client bug. JRA.
1559                          */
1560                         if (!was_8_3 && check_mangled_names) {
1561                                 pstring mangled_name;
1562                                 pstrcpy(mangled_name, fname);
1563                                 mangle_map(mangled_name,True,True,
1564                                            conn->params);
1565                                 mangled_name[12] = 0;
1566                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1567                                 SSVAL(p, 0, len);
1568                                 if (len < 24) {
1569                                         memset(p + 2 + len,'\0',24 - len);
1570                                 }
1571                                 SSVAL(p, 0, len);
1572                         } else {
1573                                 memset(p,'\0',26);
1574                         }
1575                         p += 26;
1576                         SSVAL(p,0,0); p += 2; /* Reserved ? */
1577                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1578                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1579                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1580                         SIVAL(q,0,len);
1581                         p += len;
1582                         SIVAL(p,0,0); /* Ensure any padding is null. */
1583                         len = PTR_DIFF(p, pdata);
1584                         len = (len + 3) & ~3;
1585                         SIVAL(pdata,0,len);
1586                         p = pdata + len;
1587                         break;
1588
1589                 /* CIFS UNIX Extension. */
1590
1591                 case SMB_FIND_FILE_UNIX:
1592                 case SMB_FIND_FILE_UNIX_INFO2:
1593                         p+= 4;
1594                         SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
1595
1596                         /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1597
1598                         if (info_level == SMB_FIND_FILE_UNIX) {
1599                                 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1600                                 p = store_file_unix_basic(conn, p,
1601                                                         NULL, &sbuf);
1602                         } else {
1603                                 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1604                                 p = store_file_unix_basic_info2(conn, p,
1605                                                         NULL, &sbuf);
1606                         }
1607
1608                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1609                         p += len;
1610                         SIVAL(p,0,0); /* Ensure any padding is null. */
1611
1612                         len = PTR_DIFF(p, pdata);
1613                         len = (len + 3) & ~3;
1614                         SIVAL(pdata,0,len);     /* Offset from this structure to the beginning of the next one */
1615                         p = pdata + len;
1616                         /* End of SMB_QUERY_FILE_UNIX_BASIC */
1617
1618                         break;
1619
1620                 default:      
1621                         return(False);
1622         }
1623
1624
1625         if (PTR_DIFF(p,pdata) > space_remaining) {
1626                 /* Move the dirptr back to prev_dirpos */
1627                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1628                 *out_of_space = True;
1629                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1630                 return False; /* Not finished - just out of space */
1631         }
1632
1633         /* Setup the last entry pointer, as an offset from base_data */
1634         *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1635         /* Advance the data pointer to the next slot */
1636         *ppdata = p;
1637
1638         return(found);
1639 }
1640
1641 /****************************************************************************
1642  Reply to a TRANS2_FINDFIRST.
1643 ****************************************************************************/
1644
1645 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
1646                                 char **pparams, int total_params, char **ppdata, int total_data,
1647                                 unsigned int max_data_bytes)
1648 {
1649         /* We must be careful here that we don't return more than the
1650                 allowed number of data bytes. If this means returning fewer than
1651                 maxentries then so be it. We assume that the redirector has
1652                 enough room for the fixed number of parameter bytes it has
1653                 requested. */
1654         char *params = *pparams;
1655         char *pdata = *ppdata;
1656         uint32 dirtype;
1657         int maxentries;
1658         uint16 findfirst_flags;
1659         BOOL close_after_first;
1660         BOOL close_if_end;
1661         BOOL requires_resume_key;
1662         int info_level;
1663         pstring directory;
1664         pstring mask;
1665         char *p;
1666         int last_entry_off=0;
1667         int dptr_num = -1;
1668         int numentries = 0;
1669         int i;
1670         BOOL finished = False;
1671         BOOL dont_descend = False;
1672         BOOL out_of_space = False;
1673         int space_remaining;
1674         BOOL mask_contains_wcard = False;
1675         SMB_STRUCT_STAT sbuf;
1676         TALLOC_CTX *ea_ctx = NULL;
1677         struct ea_list *ea_list = NULL;
1678         NTSTATUS ntstatus = NT_STATUS_OK;
1679
1680         if (total_params < 13) {
1681                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1682         }
1683
1684         dirtype = SVAL(params,0);
1685         maxentries = SVAL(params,2);
1686         findfirst_flags = SVAL(params,4);
1687         close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1688         close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1689         requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1690         info_level = SVAL(params,6);
1691
1692         *directory = *mask = 0;
1693
1694         DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1695 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1696                 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1697                 info_level, max_data_bytes));
1698
1699         if (!maxentries) {
1700                 /* W2K3 seems to treat zero as 1. */
1701                 maxentries = 1;
1702         }
1703  
1704         switch (info_level) {
1705                 case SMB_FIND_INFO_STANDARD:
1706                 case SMB_FIND_EA_SIZE:
1707                 case SMB_FIND_EA_LIST:
1708                 case SMB_FIND_FILE_DIRECTORY_INFO:
1709                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1710                 case SMB_FIND_FILE_NAMES_INFO:
1711                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1712                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1713                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1714                         break;
1715                 case SMB_FIND_FILE_UNIX:
1716                 case SMB_FIND_FILE_UNIX_INFO2:
1717                         if (!lp_unix_extensions()) {
1718                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1719                         }
1720                         break;
1721                 default:
1722                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1723         }
1724
1725         srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1726         if (!NT_STATUS_IS_OK(ntstatus)) {
1727                 return ERROR_NT(ntstatus);
1728         }
1729
1730         if (!resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, directory)) {
1731                 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
1732         }
1733
1734         ntstatus = unix_convert(conn, directory, True, NULL, &sbuf);
1735         if (!NT_STATUS_IS_OK(ntstatus)) {
1736                 return ERROR_NT(ntstatus);
1737         }
1738         ntstatus = check_name(conn, directory);
1739         if (!NT_STATUS_IS_OK(ntstatus)) {
1740                 return ERROR_NT(ntstatus);
1741         }
1742
1743         p = strrchr_m(directory,'/');
1744         if(p == NULL) {
1745                 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1746                 if((directory[0] == '.') && (directory[1] == '\0')) {
1747                         pstrcpy(mask,"*");
1748                         mask_contains_wcard = True;
1749                 } else {
1750                         pstrcpy(mask,directory);
1751                 }
1752                 pstrcpy(directory,"./");
1753         } else {
1754                 pstrcpy(mask,p+1);
1755                 *p = 0;
1756         }
1757
1758         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1759
1760         if (info_level == SMB_FIND_EA_LIST) {
1761                 uint32 ea_size;
1762
1763                 if (total_data < 4) {
1764                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1765                 }
1766
1767                 ea_size = IVAL(pdata,0);
1768                 if (ea_size != total_data) {
1769                         DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1770 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1771                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1772                 }
1773
1774                 if (!lp_ea_support(SNUM(conn))) {
1775                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
1776                 }
1777                                                                                                                                                         
1778                 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1779                         return ERROR_NT(NT_STATUS_NO_MEMORY);
1780                 }
1781
1782                 /* Pull out the list of names. */
1783                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1784                 if (!ea_list) {
1785                         talloc_destroy(ea_ctx);
1786                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1787                 }
1788         }
1789
1790         *ppdata = (char *)SMB_REALLOC(
1791                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1792         if(*ppdata == NULL ) {
1793                 talloc_destroy(ea_ctx);
1794                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1795         }
1796         pdata = *ppdata;
1797
1798         /* Realloc the params space */
1799         *pparams = (char *)SMB_REALLOC(*pparams, 10);
1800         if (*pparams == NULL) {
1801                 talloc_destroy(ea_ctx);
1802                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1803         }
1804         params = *pparams;
1805
1806         /* Save the wildcard match and attribs we are using on this directory - 
1807                 needed as lanman2 assumes these are being saved between calls */
1808
1809         ntstatus = dptr_create(conn,
1810                                 directory,
1811                                 False,
1812                                 True,
1813                                 SVAL(inbuf,smb_pid),
1814                                 mask,
1815                                 mask_contains_wcard,
1816                                 dirtype,
1817                                 &conn->dirptr);
1818
1819         if (!NT_STATUS_IS_OK(ntstatus)) {
1820                 talloc_destroy(ea_ctx);
1821                 return ERROR_NT(ntstatus);
1822         }
1823
1824         dptr_num = dptr_dnum(conn->dirptr);
1825         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
1826
1827         /* We don't need to check for VOL here as this is returned by 
1828                 a different TRANS2 call. */
1829   
1830         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1831         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1832                 dont_descend = True;
1833     
1834         p = pdata;
1835         space_remaining = max_data_bytes;
1836         out_of_space = False;
1837
1838         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1839                 BOOL got_exact_match = False;
1840
1841                 /* this is a heuristic to avoid seeking the dirptr except when 
1842                         absolutely necessary. It allows for a filename of about 40 chars */
1843                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1844                         out_of_space = True;
1845                         finished = False;
1846                 } else {
1847                         finished = !get_lanman2_dir_entry(conn,
1848                                         inbuf, outbuf,
1849                                         mask,dirtype,info_level,
1850                                         requires_resume_key,dont_descend,
1851                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1852                                         &last_entry_off, ea_list, ea_ctx);
1853                 }
1854
1855                 if (finished && out_of_space)
1856                         finished = False;
1857
1858                 if (!finished && !out_of_space)
1859                         numentries++;
1860
1861                 /*
1862                  * As an optimisation if we know we aren't looking
1863                  * for a wildcard name (ie. the name matches the wildcard exactly)
1864                  * then we can finish on any (first) match.
1865                  * This speeds up large directory searches. JRA.
1866                  */
1867
1868                 if(got_exact_match)
1869                         finished = True;
1870
1871                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1872         }
1873   
1874         talloc_destroy(ea_ctx);
1875
1876         /* Check if we can close the dirptr */
1877         if(close_after_first || (finished && close_if_end)) {
1878                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1879                 dptr_close(&dptr_num);
1880         }
1881
1882         /* 
1883          * If there are no matching entries we must return ERRDOS/ERRbadfile - 
1884          * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1885          * the protocol level is less than NT1. Tested with smbclient. JRA.
1886          * This should fix the OS/2 client bug #2335.
1887          */
1888
1889         if(numentries == 0) {
1890                 dptr_close(&dptr_num);
1891                 if (Protocol < PROTOCOL_NT1) {
1892                         return ERROR_DOS(ERRDOS,ERRnofiles);
1893                 } else {
1894                         return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1895                 }
1896         }
1897
1898         /* At this point pdata points to numentries directory entries. */
1899
1900         /* Set up the return parameter block */
1901         SSVAL(params,0,dptr_num);
1902         SSVAL(params,2,numentries);
1903         SSVAL(params,4,finished);
1904         SSVAL(params,6,0); /* Never an EA error */
1905         SSVAL(params,8,last_entry_off);
1906
1907         send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
1908
1909         if ((! *directory) && dptr_path(dptr_num))
1910                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1911
1912         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1913                 smb_fn_name(CVAL(inbuf,smb_com)), 
1914                 mask, directory, dirtype, numentries ) );
1915
1916         /* 
1917          * Force a name mangle here to ensure that the
1918          * mask as an 8.3 name is top of the mangled cache.
1919          * The reasons for this are subtle. Don't remove
1920          * this code unless you know what you are doing
1921          * (see PR#13758). JRA.
1922          */
1923
1924         if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1925                 mangle_map(mask, True, True, conn->params);
1926
1927         return(-1);
1928 }
1929
1930 /****************************************************************************
1931  Reply to a TRANS2_FINDNEXT.
1932 ****************************************************************************/
1933
1934 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1935                                         char **pparams, int total_params, char **ppdata, int total_data,
1936                                         unsigned int max_data_bytes)
1937 {
1938         /* We must be careful here that we don't return more than the
1939                 allowed number of data bytes. If this means returning fewer than
1940                 maxentries then so be it. We assume that the redirector has
1941                 enough room for the fixed number of parameter bytes it has
1942                 requested. */
1943         char *params = *pparams;
1944         char *pdata = *ppdata;
1945         int dptr_num;
1946         int maxentries;
1947         uint16 info_level;
1948         uint32 resume_key;
1949         uint16 findnext_flags;
1950         BOOL close_after_request;
1951         BOOL close_if_end;
1952         BOOL requires_resume_key;
1953         BOOL continue_bit;
1954         BOOL mask_contains_wcard = False;
1955         pstring resume_name;
1956         pstring mask;
1957         pstring directory;
1958         char *p;
1959         uint16 dirtype;
1960         int numentries = 0;
1961         int i, last_entry_off=0;
1962         BOOL finished = False;
1963         BOOL dont_descend = False;
1964         BOOL out_of_space = False;
1965         int space_remaining;
1966         TALLOC_CTX *ea_ctx = NULL;
1967         struct ea_list *ea_list = NULL;
1968         NTSTATUS ntstatus = NT_STATUS_OK;
1969
1970         if (total_params < 13) {
1971                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1972         }
1973
1974         dptr_num = SVAL(params,0);
1975         maxentries = SVAL(params,2);
1976         info_level = SVAL(params,4);
1977         resume_key = IVAL(params,6);
1978         findnext_flags = SVAL(params,10);
1979         close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1980         close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1981         requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1982         continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1983
1984         *mask = *directory = *resume_name = 0;
1985
1986         srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1987         if (!NT_STATUS_IS_OK(ntstatus)) {
1988                 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1989                    complain (it thinks we're asking for the directory above the shared
1990                    path or an invalid name). Catch this as the resume name is only compared, never used in
1991                    a file access. JRA. */
1992                 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1993                         pstrcpy(resume_name, "..");
1994                 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1995                         pstrcpy(resume_name, ".");
1996                 } else {
1997                         return ERROR_NT(ntstatus);
1998                 }
1999         }
2000
2001         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2002 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2003 resume_key = %d resume name = %s continue=%d level = %d\n",
2004                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
2005                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2006
2007         if (!maxentries) {
2008                 /* W2K3 seems to treat zero as 1. */
2009                 maxentries = 1;
2010         }
2011
2012         switch (info_level) {
2013                 case SMB_FIND_INFO_STANDARD:
2014                 case SMB_FIND_EA_SIZE:
2015                 case SMB_FIND_EA_LIST:
2016                 case SMB_FIND_FILE_DIRECTORY_INFO:
2017                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2018                 case SMB_FIND_FILE_NAMES_INFO:
2019                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2020                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2021                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2022                         break;
2023                 case SMB_FIND_FILE_UNIX:
2024                 case SMB_FIND_FILE_UNIX_INFO2:
2025                         if (!lp_unix_extensions()) {
2026                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2027                         }
2028                         break;
2029                 default:
2030                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2031         }
2032
2033         if (info_level == SMB_FIND_EA_LIST) {
2034                 uint32 ea_size;
2035
2036                 if (total_data < 4) {
2037                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2038                 }
2039
2040                 ea_size = IVAL(pdata,0);
2041                 if (ea_size != total_data) {
2042                         DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2043 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2044                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2045                 }
2046                                                                                                                                                      
2047                 if (!lp_ea_support(SNUM(conn))) {
2048                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
2049                 }
2050                                                                                                                                                      
2051                 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2052                         return ERROR_NT(NT_STATUS_NO_MEMORY);
2053                 }
2054
2055                 /* Pull out the list of names. */
2056                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2057                 if (!ea_list) {
2058                         talloc_destroy(ea_ctx);
2059                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2060                 }
2061         }
2062
2063         *ppdata = (char *)SMB_REALLOC(
2064                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2065         if(*ppdata == NULL) {
2066                 talloc_destroy(ea_ctx);
2067                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2068         }
2069
2070         pdata = *ppdata;
2071
2072         /* Realloc the params space */
2073         *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2074         if(*pparams == NULL ) {
2075                 talloc_destroy(ea_ctx);
2076                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2077         }
2078
2079         params = *pparams;
2080
2081         /* Check that the dptr is valid */
2082         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2083                 talloc_destroy(ea_ctx);
2084                 return ERROR_DOS(ERRDOS,ERRnofiles);
2085         }
2086
2087         string_set(&conn->dirpath,dptr_path(dptr_num));
2088
2089         /* Get the wildcard mask from the dptr */
2090         if((p = dptr_wcard(dptr_num))== NULL) {
2091                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2092                 talloc_destroy(ea_ctx);
2093                 return ERROR_DOS(ERRDOS,ERRnofiles);
2094         }
2095
2096         pstrcpy(mask, p);
2097         pstrcpy(directory,conn->dirpath);
2098
2099         /* Get the attr mask from the dptr */
2100         dirtype = dptr_attr(dptr_num);
2101
2102         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2103                 dptr_num, mask, dirtype, 
2104                 (long)conn->dirptr,
2105                 dptr_TellDir(conn->dirptr)));
2106
2107         /* We don't need to check for VOL here as this is returned by 
2108                 a different TRANS2 call. */
2109
2110         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2111         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2112                 dont_descend = True;
2113     
2114         p = pdata;
2115         space_remaining = max_data_bytes;
2116         out_of_space = False;
2117
2118         /* 
2119          * Seek to the correct position. We no longer use the resume key but
2120          * depend on the last file name instead.
2121          */
2122
2123         if(*resume_name && !continue_bit) {
2124                 SMB_STRUCT_STAT st;
2125
2126                 long current_pos = 0;
2127                 /*
2128                  * Remember, mangle_map is called by
2129                  * get_lanman2_dir_entry(), so the resume name
2130                  * could be mangled. Ensure we check the unmangled name.
2131                  */
2132
2133                 if (mangle_is_mangled(resume_name, conn->params)) {
2134                         mangle_check_cache(resume_name, sizeof(resume_name)-1,
2135                                            conn->params);
2136                 }
2137
2138                 /*
2139                  * Fix for NT redirector problem triggered by resume key indexes
2140                  * changing between directory scans. We now return a resume key of 0
2141                  * and instead look for the filename to continue from (also given
2142                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2143                  * findfirst/findnext (as is usual) then the directory pointer
2144                  * should already be at the correct place.
2145                  */
2146
2147                 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2148         } /* end if resume_name && !continue_bit */
2149
2150         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2151                 BOOL got_exact_match = False;
2152
2153                 /* this is a heuristic to avoid seeking the dirptr except when 
2154                         absolutely necessary. It allows for a filename of about 40 chars */
2155                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2156                         out_of_space = True;
2157                         finished = False;
2158                 } else {
2159                         finished = !get_lanman2_dir_entry(conn,
2160                                                 inbuf, outbuf,
2161                                                 mask,dirtype,info_level,
2162                                                 requires_resume_key,dont_descend,
2163                                                 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2164                                                 &last_entry_off, ea_list, ea_ctx);
2165                 }
2166
2167                 if (finished && out_of_space)
2168                         finished = False;
2169
2170                 if (!finished && !out_of_space)
2171                         numentries++;
2172
2173                 /*
2174                  * As an optimisation if we know we aren't looking
2175                  * for a wildcard name (ie. the name matches the wildcard exactly)
2176                  * then we can finish on any (first) match.
2177                  * This speeds up large directory searches. JRA.
2178                  */
2179
2180                 if(got_exact_match)
2181                         finished = True;
2182
2183                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2184         }
2185   
2186         talloc_destroy(ea_ctx);
2187
2188         /* Check if we can close the dirptr */
2189         if(close_after_request || (finished && close_if_end)) {
2190                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2191                 dptr_close(&dptr_num); /* This frees up the saved mask */
2192         }
2193
2194         /* Set up the return parameter block */
2195         SSVAL(params,0,numentries);
2196         SSVAL(params,2,finished);
2197         SSVAL(params,4,0); /* Never an EA error */
2198         SSVAL(params,6,last_entry_off);
2199
2200         send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2201
2202         if ((! *directory) && dptr_path(dptr_num))
2203                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2204
2205         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2206                 smb_fn_name(CVAL(inbuf,smb_com)), 
2207                 mask, directory, dirtype, numentries ) );
2208
2209         return(-1);
2210 }
2211
2212 /****************************************************************************
2213  Reply to a TRANS2_QFSINFO (query filesystem info).
2214 ****************************************************************************/
2215
2216 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2217                                         char **pparams, int total_params, char **ppdata, int total_data,
2218                                         unsigned int max_data_bytes)
2219 {
2220         char *pdata;
2221         char *params = *pparams;
2222         uint16 info_level;
2223         int data_len, len;
2224         SMB_STRUCT_STAT st;
2225         char *vname = volume_label(SNUM(conn));
2226         int snum = SNUM(conn);
2227         char *fstype = lp_fstype(SNUM(conn));
2228         int quota_flag = 0;
2229
2230         if (total_params < 2) {
2231                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2232         }
2233
2234         info_level = SVAL(params,0);
2235
2236         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2237
2238         if(SMB_VFS_STAT(conn,".",&st)!=0) {
2239                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2240                 return ERROR_DOS(ERRSRV,ERRinvdevice);
2241         }
2242
2243         *ppdata = (char *)SMB_REALLOC(
2244                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2245         if (*ppdata == NULL ) {
2246                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2247         }
2248
2249         pdata = *ppdata;
2250         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2251
2252         switch (info_level) {
2253                 case SMB_INFO_ALLOCATION:
2254                 {
2255                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2256                         data_len = 18;
2257                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2258                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2259                         }
2260
2261                         block_size = lp_block_size(snum);
2262                         if (bsize < block_size) {
2263                                 SMB_BIG_UINT factor = block_size/bsize;
2264                                 bsize = block_size;
2265                                 dsize /= factor;
2266                                 dfree /= factor;
2267                         }
2268                         if (bsize > block_size) {
2269                                 SMB_BIG_UINT factor = bsize/block_size;
2270                                 bsize = block_size;
2271                                 dsize *= factor;
2272                                 dfree *= factor;
2273                         }
2274                         bytes_per_sector = 512;
2275                         sectors_per_unit = bsize/bytes_per_sector;
2276
2277                         DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2278 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2279                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2280
2281                         SIVAL(pdata,l1_idFileSystem,st.st_dev);
2282                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2283                         SIVAL(pdata,l1_cUnit,dsize);
2284                         SIVAL(pdata,l1_cUnitAvail,dfree);
2285                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
2286                         break;
2287                 }
2288
2289                 case SMB_INFO_VOLUME:
2290                         /* Return volume name */
2291                         /* 
2292                          * Add volume serial number - hash of a combination of
2293                          * the called hostname and the service name.
2294                          */
2295                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2296                         /*
2297                          * Win2k3 and previous mess this up by sending a name length
2298                          * one byte short. I believe only older clients (OS/2 Win9x) use
2299                          * this call so try fixing this by adding a terminating null to
2300                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2301                          */
2302                         len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2303                         SCVAL(pdata,l2_vol_cch,len);
2304                         data_len = l2_vol_szVolLabel + len;
2305                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2306                                 (unsigned)st.st_ctime, len, vname));
2307                         break;
2308
2309                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2310                 case SMB_FS_ATTRIBUTE_INFORMATION:
2311
2312
2313 #if defined(HAVE_SYS_QUOTAS)
2314                         quota_flag = FILE_VOLUME_QUOTAS;
2315 #endif
2316
2317                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2318                                 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2319                                 quota_flag); /* FS ATTRIBUTES */
2320
2321                         SIVAL(pdata,4,255); /* Max filename component length */
2322                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2323                                 and will think we can't do long filenames */
2324                         len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2325                         SIVAL(pdata,8,len);
2326                         data_len = 12 + len;
2327                         break;
2328
2329                 case SMB_QUERY_FS_LABEL_INFO:
2330                 case SMB_FS_LABEL_INFORMATION:
2331                         len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2332                         data_len = 4 + len;
2333                         SIVAL(pdata,0,len);
2334                         break;
2335
2336                 case SMB_QUERY_FS_VOLUME_INFO:      
2337                 case SMB_FS_VOLUME_INFORMATION:
2338
2339                         /* 
2340                          * Add volume serial number - hash of a combination of
2341                          * the called hostname and the service name.
2342                          */
2343                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
2344                                 (str_checksum(get_local_machine_name())<<16));
2345
2346                         len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2347                         SIVAL(pdata,12,len);
2348                         data_len = 18+len;
2349                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
2350                                 (int)strlen(vname),vname, lp_servicename(snum)));
2351                         break;
2352
2353                 case SMB_QUERY_FS_SIZE_INFO:
2354                 case SMB_FS_SIZE_INFORMATION:
2355                 {
2356                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2357                         data_len = 24;
2358                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2359                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2360                         }
2361                         block_size = lp_block_size(snum);
2362                         if (bsize < block_size) {
2363                                 SMB_BIG_UINT factor = block_size/bsize;
2364                                 bsize = block_size;
2365                                 dsize /= factor;
2366                                 dfree /= factor;
2367                         }
2368                         if (bsize > block_size) {
2369                                 SMB_BIG_UINT factor = bsize/block_size;
2370                                 bsize = block_size;
2371                                 dsize *= factor;
2372                                 dfree *= factor;
2373                         }
2374                         bytes_per_sector = 512;
2375                         sectors_per_unit = bsize/bytes_per_sector;
2376                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2377 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2378                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2379                         SBIG_UINT(pdata,0,dsize);
2380                         SBIG_UINT(pdata,8,dfree);
2381                         SIVAL(pdata,16,sectors_per_unit);
2382                         SIVAL(pdata,20,bytes_per_sector);
2383                         break;
2384                 }
2385
2386                 case SMB_FS_FULL_SIZE_INFORMATION:
2387                 {
2388                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2389                         data_len = 32;
2390                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2391                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2392                         }
2393                         block_size = lp_block_size(snum);
2394                         if (bsize < block_size) {
2395                                 SMB_BIG_UINT factor = block_size/bsize;
2396                                 bsize = block_size;
2397                                 dsize /= factor;
2398                                 dfree /= factor;
2399                         }
2400                         if (bsize > block_size) {
2401                                 SMB_BIG_UINT factor = bsize/block_size;
2402                                 bsize = block_size;
2403                                 dsize *= factor;
2404                                 dfree *= factor;
2405                         }
2406                         bytes_per_sector = 512;
2407                         sectors_per_unit = bsize/bytes_per_sector;
2408                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2409 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2410                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2411                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2412                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2413                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2414                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2415                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2416                         break;
2417                 }
2418
2419                 case SMB_QUERY_FS_DEVICE_INFO:
2420                 case SMB_FS_DEVICE_INFORMATION:
2421                         data_len = 8;
2422                         SIVAL(pdata,0,0); /* dev type */
2423                         SIVAL(pdata,4,0); /* characteristics */
2424                         break;
2425
2426 #ifdef HAVE_SYS_QUOTAS
2427                 case SMB_FS_QUOTA_INFORMATION:
2428                 /* 
2429                  * what we have to send --metze:
2430                  *
2431                  * Unknown1:            24 NULL bytes
2432                  * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2433                  * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
2434                  * Quota Flags:         2 byte :
2435                  * Unknown3:            6 NULL bytes
2436                  *
2437                  * 48 bytes total
2438                  * 
2439                  * details for Quota Flags:
2440                  * 
2441                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2442                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2443                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2444                  * 0x0001 Enable Quotas: enable quota for this fs
2445                  *
2446                  */
2447                 {
2448                         /* we need to fake up a fsp here,
2449                          * because its not send in this call
2450                          */
2451                         files_struct fsp;
2452                         SMB_NTQUOTA_STRUCT quotas;
2453                         
2454                         ZERO_STRUCT(fsp);
2455                         ZERO_STRUCT(quotas);
2456                         
2457                         fsp.conn = conn;
2458                         fsp.fnum = -1;
2459                         
2460                         /* access check */
2461                         if (current_user.ut.uid != 0) {
2462                                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2463                                         lp_servicename(SNUM(conn)),conn->user));
2464                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2465                         }
2466                         
2467                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2468                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2469                                 return ERROR_DOS(ERRSRV,ERRerror);
2470                         }
2471
2472                         data_len = 48;
2473
2474                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
2475                 
2476                         /* Unknown1 24 NULL bytes*/
2477                         SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2478                         SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2479                         SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2480                 
2481                         /* Default Soft Quota 8 bytes */
2482                         SBIG_UINT(pdata,24,quotas.softlim);
2483
2484                         /* Default Hard Quota 8 bytes */
2485                         SBIG_UINT(pdata,32,quotas.hardlim);
2486         
2487                         /* Quota flag 2 bytes */
2488                         SSVAL(pdata,40,quotas.qflags);
2489                 
2490                         /* Unknown3 6 NULL bytes */
2491                         SSVAL(pdata,42,0);
2492                         SIVAL(pdata,44,0);
2493                         
2494                         break;
2495                 }
2496 #endif /* HAVE_SYS_QUOTAS */
2497                 case SMB_FS_OBJECTID_INFORMATION:
2498                         data_len = 64;
2499                         break;
2500
2501                 /*
2502                  * Query the version and capabilities of the CIFS UNIX extensions
2503                  * in use.
2504                  */
2505
2506                 case SMB_QUERY_CIFS_UNIX_INFO:
2507                         if (!lp_unix_extensions()) {
2508                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2509                         }
2510                         data_len = 12;
2511                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2512                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2513                         /* We have POSIX ACLs, pathname and locking capability. */
2514                         SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2515                                         CIFS_UNIX_POSIX_ACLS_CAP|
2516                                         CIFS_UNIX_POSIX_PATHNAMES_CAP|
2517                                         CIFS_UNIX_FCNTL_LOCKS_CAP|
2518                                         CIFS_UNIX_EXTATTR_CAP|
2519                                         CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
2520                         break;
2521
2522                 case SMB_QUERY_POSIX_FS_INFO:
2523                 {
2524                         int rc;
2525                         vfs_statvfs_struct svfs;
2526
2527                         if (!lp_unix_extensions()) {
2528                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2529                         }
2530
2531                         rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2532
2533                         if (!rc) {
2534                                 data_len = 56;
2535                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
2536                                 SIVAL(pdata,4,svfs.BlockSize);
2537                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2538                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2539                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2540                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2541                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2542                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2543                                 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2544 #ifdef EOPNOTSUPP
2545                         } else if (rc == EOPNOTSUPP) {
2546                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2547 #endif /* EOPNOTSUPP */
2548                         } else {
2549                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2550                                 return ERROR_DOS(ERRSRV,ERRerror);
2551                         }
2552                         break;
2553                 }
2554
2555                 case SMB_QUERY_POSIX_WHOAMI:
2556                 {
2557                         uint32_t flags = 0;
2558                         uint32_t sid_bytes;
2559                         int i;
2560
2561                         if (!lp_unix_extensions()) {
2562                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2563                         }
2564
2565                         if (max_data_bytes < 40) {
2566                                 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2567                         }
2568
2569                         /* We ARE guest if global_sid_Builtin_Guests is
2570                          * in our list of SIDs.
2571                          */
2572                         if (nt_token_check_sid(&global_sid_Builtin_Guests,
2573                                     current_user.nt_user_token)) {
2574                                 flags |= SMB_WHOAMI_GUEST;
2575                         }
2576
2577                         /* We are NOT guest if global_sid_Authenticated_Users
2578                          * is in our list of SIDs.
2579                          */
2580                         if (nt_token_check_sid(&global_sid_Authenticated_Users,
2581                                     current_user.nt_user_token)) {
2582                                 flags &= ~SMB_WHOAMI_GUEST;
2583                         }
2584
2585                         /* NOTE: 8 bytes for UID/GID, irrespective of native
2586                          * platform size. This matches
2587                          * SMB_QUERY_FILE_UNIX_BASIC and friends.
2588                          */
2589                         data_len = 4 /* flags */
2590                             + 4 /* flag mask */
2591                             + 8 /* uid */
2592                             + 8 /* gid */
2593                             + 4 /* ngroups */
2594                             + 4 /* num_sids */
2595                             + 4 /* SID bytes */
2596                             + 4 /* pad/reserved */
2597                             + (current_user.ut.ngroups * 8)
2598                                 /* groups list */
2599                             + (current_user.nt_user_token->num_sids *
2600                                     SID_MAX_SIZE)
2601                                 /* SID list */;
2602
2603                         SIVAL(pdata, 0, flags);
2604                         SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2605                         SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2606                         SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2607
2608
2609                         if (data_len >= max_data_bytes) {
2610                                 /* Potential overflow, skip the GIDs and SIDs. */
2611
2612                                 SIVAL(pdata, 24, 0); /* num_groups */
2613                                 SIVAL(pdata, 28, 0); /* num_sids */
2614                                 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2615                                 SIVAL(pdata, 36, 0); /* reserved */
2616
2617                                 data_len = 40;
2618                                 break;
2619                         }
2620
2621                         SIVAL(pdata, 24, current_user.ut.ngroups);
2622                         SIVAL(pdata, 28,
2623                                 current_user.nt_user_token->num_sids);
2624
2625                         /* We walk the SID list twice, but this call is fairly
2626                          * infrequent, and I don't expect that it's performance
2627                          * sensitive -- jpeach
2628                          */
2629                         for (i = 0, sid_bytes = 0;
2630                             i < current_user.nt_user_token->num_sids; ++i) {
2631                                 sid_bytes +=
2632                                     sid_size(&current_user.nt_user_token->user_sids[i]);
2633                         }
2634
2635                         /* SID list byte count */
2636                         SIVAL(pdata, 32, sid_bytes);
2637
2638                         /* 4 bytes pad/reserved - must be zero */
2639                         SIVAL(pdata, 36, 0);
2640                         data_len = 40;
2641
2642                         /* GID list */
2643                         for (i = 0; i < current_user.ut.ngroups; ++i) {
2644                                 SBIG_UINT(pdata, data_len,
2645                                         (SMB_BIG_UINT)current_user.ut.groups[i]);
2646                                 data_len += 8;
2647                         }
2648
2649                         /* SID list */
2650                         for (i = 0;
2651                             i < current_user.nt_user_token->num_sids; ++i) {
2652                                 int sid_len =
2653                                     sid_size(&current_user.nt_user_token->user_sids[i]);
2654
2655                                 sid_linearize(pdata + data_len, sid_len,
2656                                     &current_user.nt_user_token->user_sids[i]);
2657                                 data_len += sid_len;
2658                         }
2659
2660                         break;
2661                 }
2662
2663                 case SMB_MAC_QUERY_FS_INFO:
2664                         /*
2665                          * Thursby MAC extension... ONLY on NTFS filesystems
2666                          * once we do streams then we don't need this
2667                          */
2668                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2669                                 data_len = 88;
2670                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2671                                 break;
2672                         }
2673                         /* drop through */
2674                 default:
2675                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2676         }
2677
2678
2679         send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2680
2681         DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2682
2683         return -1;
2684 }
2685
2686 /****************************************************************************
2687  Reply to a TRANS2_SETFSINFO (set filesystem info).
2688 ****************************************************************************/
2689
2690 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2691                                         char **pparams, int total_params, char **ppdata, int total_data,
2692                                         unsigned int max_data_bytes)
2693 {
2694         char *pdata = *ppdata;
2695         char *params = *pparams;
2696         uint16 info_level;
2697         int outsize;
2698
2699         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2700
2701         /*  */
2702         if (total_params < 4) {
2703                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2704                         total_params));
2705                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2706         }
2707
2708         info_level = SVAL(params,2);
2709
2710         switch(info_level) {
2711                 case SMB_SET_CIFS_UNIX_INFO:
2712                         {
2713                                 uint16 client_unix_major;
2714                                 uint16 client_unix_minor;
2715                                 uint32 client_unix_cap_low;
2716                                 uint32 client_unix_cap_high;
2717
2718                                 if (!lp_unix_extensions()) {
2719                                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2720                                 }
2721
2722                                 /* There should be 12 bytes of capabilities set. */
2723                                 if (total_data < 8) {
2724                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2725                                 }
2726                                 client_unix_major = SVAL(pdata,0);
2727                                 client_unix_minor = SVAL(pdata,2);
2728                                 client_unix_cap_low = IVAL(pdata,4);
2729                                 client_unix_cap_high = IVAL(pdata,8);
2730                                 /* Just print these values for now. */
2731                                 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2732 cap_low = 0x%x, cap_high = 0x%x\n",
2733                                         (unsigned int)client_unix_major,
2734                                         (unsigned int)client_unix_minor,
2735                                         (unsigned int)client_unix_cap_low,
2736                                         (unsigned int)client_unix_cap_high ));
2737
2738                                 /* Here is where we must switch to posix pathname processing... */
2739                                 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2740                                         lp_set_posix_pathnames();
2741                                         mangle_change_to_posix();
2742                                 }
2743
2744                                 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2745                                     !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2746                                         /* Client that knows how to do posix locks,
2747                                          * but not posix open/mkdir operations. Set a
2748                                          * default type for read/write checks. */
2749
2750                                         lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2751
2752                                 }
2753                                 break;
2754                         }
2755                 case SMB_FS_QUOTA_INFORMATION:
2756                         {
2757                                 files_struct *fsp = NULL;
2758                                 SMB_NTQUOTA_STRUCT quotas;
2759         
2760                                 ZERO_STRUCT(quotas);
2761
2762                                 /* access check */
2763                                 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2764                                         DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2765                                                 lp_servicename(SNUM(conn)),conn->user));
2766                                         return ERROR_DOS(ERRSRV,ERRaccess);
2767                                 }
2768
2769                                 /* note: normaly there're 48 bytes,
2770                                  * but we didn't use the last 6 bytes for now 
2771                                  * --metze 
2772                                  */
2773                                 fsp = file_fsp(params,0);
2774                                 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2775                                         DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2776                                         return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2777                                 }
2778
2779                                 if (total_data < 42) {
2780                                         DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2781                                                 total_data));
2782                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2783                                 }
2784                         
2785                                 /* unknown_1 24 NULL bytes in pdata*/
2786                 
2787                                 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2788                                 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2789 #ifdef LARGE_SMB_OFF_T
2790                                 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2791 #else /* LARGE_SMB_OFF_T */
2792                                 if ((IVAL(pdata,28) != 0)&&
2793                                         ((quotas.softlim != 0xFFFFFFFF)||
2794                                         (IVAL(pdata,28)!=0xFFFFFFFF))) {
2795                                         /* more than 32 bits? */
2796                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2797                                 }
2798 #endif /* LARGE_SMB_OFF_T */
2799                 
2800                                 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2801                                 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2802 #ifdef LARGE_SMB_OFF_T
2803                                 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2804 #else /* LARGE_SMB_OFF_T */
2805                                 if ((IVAL(pdata,36) != 0)&&
2806                                         ((quotas.hardlim != 0xFFFFFFFF)||
2807                                         (IVAL(pdata,36)!=0xFFFFFFFF))) {
2808                                         /* more than 32 bits? */
2809                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2810                                 }
2811 #endif /* LARGE_SMB_OFF_T */
2812                 
2813                                 /* quota_flags 2 bytes **/
2814                                 quotas.qflags = SVAL(pdata,40);
2815                 
2816                                 /* unknown_2 6 NULL bytes follow*/
2817                 
2818                                 /* now set the quotas */
2819                                 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2820                                         DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2821                                         return ERROR_DOS(ERRSRV,ERRerror);
2822                                 }
2823                         
2824                                 break;
2825                         }
2826                 default:
2827                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2828                                 info_level));
2829                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2830                         break;
2831         }
2832
2833         /* 
2834          * sending this reply works fine, 
2835          * but I'm not sure it's the same 
2836          * like windows do...
2837          * --metze
2838          */ 
2839         outsize = set_message(outbuf,10,0,True);
2840
2841         return outsize;
2842 }
2843
2844 #if defined(HAVE_POSIX_ACLS)
2845 /****************************************************************************
2846  Utility function to count the number of entries in a POSIX acl.
2847 ****************************************************************************/
2848
2849 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2850 {
2851         unsigned int ace_count = 0;
2852         int entry_id = SMB_ACL_FIRST_ENTRY;
2853         SMB_ACL_ENTRY_T entry;
2854
2855         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2856                 /* get_next... */
2857                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2858                         entry_id = SMB_ACL_NEXT_ENTRY;
2859                 }
2860                 ace_count++;
2861         }
2862         return ace_count;
2863 }
2864
2865 /****************************************************************************
2866  Utility function to marshall a POSIX acl into wire format.
2867 ****************************************************************************/
2868
2869 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2870 {
2871         int entry_id = SMB_ACL_FIRST_ENTRY;
2872         SMB_ACL_ENTRY_T entry;
2873
2874         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2875                 SMB_ACL_TAG_T tagtype;
2876                 SMB_ACL_PERMSET_T permset;
2877                 unsigned char perms = 0;
2878                 unsigned int own_grp;
2879
2880                 /* get_next... */
2881                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2882                         entry_id = SMB_ACL_NEXT_ENTRY;
2883                 }
2884
2885                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2886                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2887                         return False;
2888                 }
2889
2890                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2891                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2892                         return False;
2893                 }
2894
2895                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2896                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2897                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2898
2899                 SCVAL(pdata,1,perms);
2900
2901                 switch (tagtype) {
2902                         case SMB_ACL_USER_OBJ:
2903                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2904                                 own_grp = (unsigned int)pst->st_uid;
2905                                 SIVAL(pdata,2,own_grp);
2906                                 SIVAL(pdata,6,0);
2907                                 break;
2908                         case SMB_ACL_USER:
2909                                 {
2910                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2911                                         if (!puid) {
2912                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2913                                         }
2914                                         own_grp = (unsigned int)*puid;
2915                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2916                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2917                                         SIVAL(pdata,2,own_grp);
2918                                         SIVAL(pdata,6,0);
2919                                         break;
2920                                 }
2921                         case SMB_ACL_GROUP_OBJ:
2922                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2923                                 own_grp = (unsigned int)pst->st_gid;
2924                                 SIVAL(pdata,2,own_grp);
2925                                 SIVAL(pdata,6,0);
2926                                 break;
2927                         case SMB_ACL_GROUP:
2928                                 {
2929                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2930                                         if (!pgid) {
2931                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2932                                         }
2933                                         own_grp = (unsigned int)*pgid;
2934                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2935                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2936                                         SIVAL(pdata,2,own_grp);
2937                                         SIVAL(pdata,6,0);
2938                                         break;
2939                                 }
2940                         case SMB_ACL_MASK:
2941                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2942                                 SIVAL(pdata,2,0xFFFFFFFF);
2943                                 SIVAL(pdata,6,0xFFFFFFFF);
2944                                 break;
2945                         case SMB_ACL_OTHER:
2946                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2947                                 SIVAL(pdata,2,0xFFFFFFFF);
2948                                 SIVAL(pdata,6,0xFFFFFFFF);
2949                                 break;
2950                         default:
2951                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2952                                 return False;
2953                 }
2954                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2955         }
2956
2957         return True;
2958 }
2959 #endif
2960
2961 /****************************************************************************
2962  Store the FILE_UNIX_BASIC info.
2963 ****************************************************************************/
2964
2965 static char *store_file_unix_basic(connection_struct *conn,
2966                                 char *pdata,
2967                                 files_struct *fsp,
2968                                 const SMB_STRUCT_STAT *psbuf)
2969 {
2970         DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
2971         DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
2972
2973         SOFF_T(pdata,0,get_file_size(*psbuf));             /* File size 64 Bit */
2974         pdata += 8;
2975
2976         SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2977         pdata += 8;
2978
2979         put_long_date_timespec(pdata,get_ctimespec(psbuf));       /* Change Time 64 Bit */
2980         put_long_date_timespec(pdata+8,get_atimespec(psbuf));     /* Last access time 64 Bit */
2981         put_long_date_timespec(pdata+16,get_mtimespec(psbuf));    /* Last modification time 64 Bit */
2982         pdata += 24;
2983
2984         SIVAL(pdata,0,psbuf->st_uid);               /* user id for the owner */
2985         SIVAL(pdata,4,0);
2986         pdata += 8;
2987
2988         SIVAL(pdata,0,psbuf->st_gid);               /* group id of owner */
2989         SIVAL(pdata,4,0);
2990         pdata += 8;
2991
2992         SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
2993         pdata += 4;
2994
2995         SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev));   /* Major device number if type is device */
2996         SIVAL(pdata,4,0);
2997         pdata += 8;
2998
2999         SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev));   /* Minor device number if type is device */
3000         SIVAL(pdata,4,0);
3001         pdata += 8;
3002
3003         SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino);   /* inode number */
3004         pdata += 8;
3005                                 
3006         SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode));     /* Standard UNIX file permissions */
3007         SIVAL(pdata,4,0);
3008         pdata += 8;
3009
3010         SIVAL(pdata,0,psbuf->st_nlink);             /* number of hard links */
3011         SIVAL(pdata,4,0);
3012         pdata += 8;
3013
3014         return pdata;
3015 }
3016
3017 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3018  * the chflags(2) (or equivalent) flags.
3019  *
3020  * XXX: this really should be behind the VFS interface. To do this, we would
3021  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3022  * Each VFS module could then implement it's own mapping as appropriate for the
3023  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3024  */
3025 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3026         info2_flags_map[] =
3027 {
3028 #ifdef UF_NODUMP
3029     { UF_NODUMP, EXT_DO_NOT_BACKUP },
3030 #endif
3031
3032 #ifdef UF_IMMUTABLE
3033     { UF_IMMUTABLE, EXT_IMMUTABLE },
3034 #endif
3035
3036 #ifdef UF_APPEND
3037     { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3038 #endif
3039
3040 #ifdef UF_HIDDEN
3041     { UF_HIDDEN, EXT_HIDDEN },
3042 #endif
3043
3044     /* Do not remove. We need to guarantee that this array has at least one
3045      * entry to build on HP-UX.
3046      */
3047     { 0, 0 }
3048
3049 };
3050
3051 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3052                                 uint32 *smb_fflags, uint32 *smb_fmask)
3053 {
3054 #ifdef HAVE_STAT_ST_FLAGS
3055         int i;
3056
3057         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3058             *smb_fmask |= info2_flags_map[i].smb_fflag;
3059             if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3060                     *smb_fflags |= info2_flags_map[i].smb_fflag;
3061             }
3062         }
3063 #endif /* HAVE_STAT_ST_FLAGS */
3064 }
3065
3066 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3067                                 const uint32 smb_fflags,
3068                                 const uint32 smb_fmask,
3069                                 int *stat_fflags)
3070 {
3071 #ifdef HAVE_STAT_ST_FLAGS
3072         uint32 max_fmask = 0;
3073         int i;
3074
3075         *stat_fflags = psbuf->st_flags;
3076
3077         /* For each flags requested in smb_fmask, check the state of the
3078          * corresponding flag in smb_fflags and set or clear the matching
3079          * stat flag.
3080          */
3081
3082         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3083             max_fmask |= info2_flags_map[i].smb_fflag;
3084             if (smb_fmask & info2_flags_map[i].smb_fflag) {
3085                     if (smb_fflags & info2_flags_map[i].smb_fflag) {
3086                             *stat_fflags |= info2_flags_map[i].stat_fflag;
3087                     } else {
3088                             *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3089                     }
3090             }
3091         }
3092
3093         /* If smb_fmask is asking to set any bits that are not supported by
3094          * our flag mappings, we should fail.
3095          */
3096         if ((smb_fmask & max_fmask) != smb_fmask) {
3097                 return False;
3098         }
3099
3100         return True;
3101 #else
3102         return False;
3103 #endif /* HAVE_STAT_ST_FLAGS */
3104 }
3105
3106
3107 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3108  * of file flags and birth (create) time.
3109  */
3110 static char *store_file_unix_basic_info2(connection_struct *conn,
3111                                 char *pdata,
3112                                 files_struct *fsp,
3113                                 const SMB_STRUCT_STAT *psbuf)
3114 {
3115         uint32 file_flags = 0;
3116         uint32 flags_mask = 0;
3117
3118         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3119
3120         /* Create (birth) time 64 bit */
3121         put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3122         pdata += 8;
3123
3124         map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3125         SIVAL(pdata, 0, file_flags); /* flags */
3126         SIVAL(pdata, 4, flags_mask); /* mask */
3127         pdata += 8;
3128
3129         return pdata;
3130 }
3131
3132 /****************************************************************************
3133  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3134  file name or file id).
3135 ****************************************************************************/
3136
3137 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3138                                         unsigned int tran_call,
3139                                         char **pparams, int total_params, char **ppdata, int total_data,
3140                                         unsigned int max_data_bytes)
3141 {
3142         char *params = *pparams;
3143         char *pdata = *ppdata;
3144         uint16 info_level;
3145         int mode=0;
3146         int nlink;
3147         SMB_OFF_T file_size=0;
3148         SMB_BIG_UINT allocation_size=0;
3149         unsigned int data_size = 0;
3150         unsigned int param_size = 2;
3151         SMB_STRUCT_STAT sbuf;
3152         pstring fname, dos_fname;
3153         char *fullpathname;
3154         char *base_name;
3155         char *p;
3156         SMB_OFF_T pos = 0;
3157         BOOL delete_pending = False;
3158         int len;
3159         time_t create_time, mtime, atime;
3160         struct timespec create_time_ts, mtime_ts, atime_ts;
3161         files_struct *fsp = NULL;
3162         TALLOC_CTX *data_ctx = NULL;
3163         struct ea_list *ea_list = NULL;
3164         uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3165         char *lock_data = NULL;
3166
3167         if (!params)
3168                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3169
3170         ZERO_STRUCT(sbuf);
3171
3172         if (tran_call == TRANSACT2_QFILEINFO) {
3173                 if (total_params < 4) {
3174                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3175                 }
3176
3177                 fsp = file_fsp(params,0);
3178                 info_level = SVAL(params,2);
3179
3180                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3181
3182                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3183                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3184                 }
3185
3186                 if(fsp && (fsp->fake_file_handle)) {
3187                         /*
3188                          * This is actually for the QUOTA_FAKE_FILE --metze
3189                          */
3190                                                 
3191                         pstrcpy(fname, fsp->fsp_name);
3192                         /* We know this name is ok, it's already passed the checks. */
3193                         
3194                 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3195                         /*
3196                          * This is actually a QFILEINFO on a directory
3197                          * handle (returned from an NT SMB). NT5.0 seems
3198                          * to do this call. JRA.
3199                          */
3200                         /* We know this name is ok, it's already passed the checks. */
3201                         pstrcpy(fname, fsp->fsp_name);
3202                   
3203                         if (INFO_LEVEL_IS_UNIX(info_level)) {
3204                                 /* Always do lstat for UNIX calls. */
3205                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3206                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3207                                         return UNIXERROR(ERRDOS,ERRbadpath);
3208                                 }
3209                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3210                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3211                                 return UNIXERROR(ERRDOS,ERRbadpath);
3212                         }
3213
3214                         delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3215                 } else {
3216                         /*
3217                          * Original code - this is an open file.
3218                          */
3219                         CHECK_FSP(fsp,conn);
3220
3221                         pstrcpy(fname, fsp->fsp_name);
3222                         if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3223                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3224                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3225                         }
3226                         pos = fsp->fh->position_information;
3227                         delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3228                         access_mask = fsp->access_mask;
3229                 }
3230         } else {
3231                 NTSTATUS status = NT_STATUS_OK;
3232
3233                 /* qpathinfo */
3234                 if (total_params < 7) {
3235                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3236                 }
3237
3238                 info_level = SVAL(params,0);
3239
3240                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3241
3242                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3243                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3244                 }
3245
3246                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3247                 if (!NT_STATUS_IS_OK(status)) {
3248                         return ERROR_NT(status);
3249                 }
3250
3251                 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
3252                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3253                 }
3254
3255                 status = unix_convert(conn, fname, False, NULL, &sbuf);
3256                 if (!NT_STATUS_IS_OK(status)) {
3257                         return ERROR_NT(status);
3258                 }
3259                 status = check_name(conn, fname);
3260                 if (!NT_STATUS_IS_OK(status)) {
3261                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3262                         return ERROR_NT(status);
3263                 }
3264
3265                 if (INFO_LEVEL_IS_UNIX(info_level)) {
3266                         /* Always do lstat for UNIX calls. */
3267                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3268                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3269                                 return UNIXERROR(ERRDOS,ERRbadpath);
3270                         }
3271                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3272                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3273                         return UNIXERROR(ERRDOS,ERRbadpath);
3274                 }
3275
3276                 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3277                 if (delete_pending) {
3278                         return ERROR_NT(NT_STATUS_DELETE_PENDING);
3279                 }
3280         }
3281
3282         nlink = sbuf.st_nlink;
3283
3284         if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3285                 /* NTFS does not seem to count ".." */
3286                 nlink -= 1;
3287         }
3288
3289         if ((nlink > 0) && delete_pending) {
3290                 nlink -= 1;
3291         }
3292
3293         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3294                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3295         }
3296
3297         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3298                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3299
3300         p = strrchr_m(fname,'/'); 
3301         if (!p)
3302                 base_name = fname;
3303         else
3304                 base_name = p+1;
3305
3306         mode = dos_mode(conn,fname,&sbuf);
3307         if (!mode)
3308                 mode = FILE_ATTRIBUTE_NORMAL;
3309
3310         fullpathname = fname;
3311         if (!(mode & aDIR))
3312                 file_size = get_file_size(sbuf);
3313
3314         /* Pull out any data sent here before we realloc. */
3315         switch (info_level) {
3316                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3317                 {
3318                         /* Pull any EA list from the data portion. */
3319                         uint32 ea_size;
3320
3321                         if (total_data < 4) {
3322                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3323                         }
3324                         ea_size = IVAL(pdata,0);
3325
3326                         if (total_data > 0 && ea_size != total_data) {
3327                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3328 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3329                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3330                         }
3331
3332                         if (!lp_ea_support(SNUM(conn))) {
3333                                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3334                         }
3335
3336                         if ((data_ctx = talloc_init("ea_list")) == NULL) {
3337                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3338                         }
3339
3340                         /* Pull out the list of names. */
3341                         ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3342                         if (!ea_list) {
3343                                 talloc_destroy(data_ctx);
3344                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3345                         }
3346                         break;
3347                 }
3348
3349                 case SMB_QUERY_POSIX_LOCK:
3350                 {
3351                         if (fsp == NULL || fsp->fh->fd == -1) {
3352                                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3353                         }
3354
3355                         if (total_data != POSIX_LOCK_DATA_SIZE) {
3356                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3357                         }
3358
3359                         if ((data_ctx = talloc_init("lock_request")) == NULL) {
3360                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3361                         }
3362
3363                         /* Copy the lock range data. */
3364                         lock_data = (char *)talloc_memdup(
3365                                 data_ctx, pdata, total_data);
3366                         if (!lock_data) {
3367                                 talloc_destroy(data_ctx);
3368                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3369                         }
3370                 }
3371                 default:
3372                         break;
3373         }
3374
3375         *pparams = (char *)SMB_REALLOC(*pparams,2);
3376         if (*pparams == NULL) {
3377                 talloc_destroy(data_ctx);
3378                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3379         }
3380         params = *pparams;
3381         SSVAL(params,0,0);
3382         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3383         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3384         if (*ppdata == NULL ) {
3385                 talloc_destroy(data_ctx);
3386                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3387         }
3388         pdata = *ppdata;
3389
3390         create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3391         mtime_ts = get_mtimespec(&sbuf);
3392         atime_ts = get_atimespec(&sbuf);
3393
3394         allocation_size = get_allocation_size(conn,fsp,&sbuf);
3395
3396         if (fsp) {
3397                 if (!null_timespec(fsp->pending_modtime)) {
3398                         /* the pending modtime overrides the current modtime */
3399                         mtime_ts = fsp->pending_modtime;
3400                 }
3401         } else {
3402                 /* Do we have this path open ? */
3403                 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3404                 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3405                         /* the pending modtime overrides the current modtime */
3406                         mtime_ts = fsp1->pending_modtime;
3407                 }
3408                 if (fsp1 && fsp1->initial_allocation_size) {
3409                         allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3410                 }
3411         }
3412
3413         if (lp_dos_filetime_resolution(SNUM(conn))) {
3414                 dos_filetime_timespec(&create_time_ts);
3415                 dos_filetime_timespec(&mtime_ts);
3416                 dos_filetime_timespec(&atime_ts);
3417         }
3418
3419         create_time = convert_timespec_to_time_t(create_time_ts);
3420         mtime = convert_timespec_to_time_t(mtime_ts);
3421         atime = convert_timespec_to_time_t(atime_ts);
3422
3423         /* NT expects the name to be in an exact form of the *full*
3424            filename. See the trans2 torture test */
3425         if (strequal(base_name,".")) {
3426                 pstrcpy(dos_fname, "\\");
3427         } else {
3428                 pstr_sprintf(dos_fname, "\\%s", fname);
3429                 string_replace(dos_fname, '/', '\\');
3430         }
3431
3432         switch (info_level) {
3433                 case SMB_INFO_STANDARD:
3434                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3435                         data_size = 22;
3436                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3437                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3438                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3439                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
3440                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3441                         SSVAL(pdata,l1_attrFile,mode);
3442                         break;
3443
3444                 case SMB_INFO_QUERY_EA_SIZE:
3445                 {
3446                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3447                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3448                         data_size = 26;
3449                         srv_put_dos_date2(pdata,0,create_time);
3450                         srv_put_dos_date2(pdata,4,atime);
3451                         srv_put_dos_date2(pdata,8,mtime); /* write time */
3452                         SIVAL(pdata,12,(uint32)file_size);
3453                         SIVAL(pdata,16,(uint32)allocation_size);
3454                         SSVAL(pdata,20,mode);
3455                         SIVAL(pdata,22,ea_size);
3456                         break;
3457                 }
3458
3459                 case SMB_INFO_IS_NAME_VALID:
3460                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3461                         if (tran_call == TRANSACT2_QFILEINFO) {
3462                                 /* os/2 needs this ? really ?*/      
3463                                 return ERROR_DOS(ERRDOS,ERRbadfunc); 
3464                         }
3465                         data_size = 0;
3466                         param_size = 0;
3467                         break;
3468                         
3469                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3470                 {
3471                         size_t total_ea_len = 0;
3472                         struct ea_list *ea_file_list = NULL;
3473
3474                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3475
3476                         ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3477                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3478
3479                         if (!ea_list || (total_ea_len > data_size)) {
3480                                 talloc_destroy(data_ctx);
3481                                 data_size = 4;
3482                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3483                                 break;
3484                         }
3485
3486                         data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3487                         talloc_destroy(data_ctx);
3488                         break;
3489                 }
3490
3491                 case SMB_INFO_QUERY_ALL_EAS:
3492                 {
3493                         /* We have data_size bytes to put EA's into. */
3494                         size_t total_ea_len = 0;
3495
3496                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3497
3498                         data_ctx = talloc_init("ea_ctx");
3499                         if (!data_ctx) {
3500                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3501                         }
3502
3503                         ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3504                         if (!ea_list || (total_ea_len > data_size)) {
3505                                 talloc_destroy(data_ctx);
3506                                 data_size = 4;
3507                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3508                                 break;
3509                         }
3510
3511                         data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3512                         talloc_destroy(data_ctx);
3513                         break;
3514                 }
3515
3516                 case SMB_FILE_BASIC_INFORMATION:
3517                 case SMB_QUERY_FILE_BASIC_INFO:
3518
3519                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3520                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3521                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3522                         } else {
3523                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3524                                 data_size = 40;
3525                                 SIVAL(pdata,36,0);
3526                         }
3527                         put_long_date_timespec(pdata,create_time_ts);
3528                         put_long_date_timespec(pdata+8,atime_ts);
3529                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3530                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3531                         SIVAL(pdata,32,mode);
3532
3533                         DEBUG(5,("SMB_QFBI - "));
3534                         DEBUG(5,("create: %s ", ctime(&create_time)));
3535                         DEBUG(5,("access: %s ", ctime(&atime)));
3536                         DEBUG(5,("write: %s ", ctime(&mtime)));
3537                         DEBUG(5,("change: %s ", ctime(&mtime)));
3538                         DEBUG(5,("mode: %x\n", mode));
3539                         break;
3540
3541                 case SMB_FILE_STANDARD_INFORMATION:
3542                 case SMB_QUERY_FILE_STANDARD_INFO:
3543
3544                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3545                         data_size = 24;
3546                         SOFF_T(pdata,0,allocation_size);
3547                         SOFF_T(pdata,8,file_size);
3548                         SIVAL(pdata,16,nlink);
3549                         SCVAL(pdata,20,delete_pending?1:0);
3550                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3551                         SSVAL(pdata,22,0); /* Padding. */
3552                         break;
3553
3554                 case SMB_FILE_EA_INFORMATION:
3555                 case SMB_QUERY_FILE_EA_INFO:
3556                 {
3557                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3558                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3559                         data_size = 4;
3560                         SIVAL(pdata,0,ea_size);
3561                         break;
3562                 }
3563
3564                 /* Get the 8.3 name - used if NT SMB was negotiated. */
3565                 case SMB_QUERY_FILE_ALT_NAME_INFO:
3566                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3567                 {
3568                         pstring short_name;
3569
3570                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3571                         pstrcpy(short_name,base_name);
3572                         /* Mangle if not already 8.3 */
3573                         if(!mangle_is_8_3(short_name, True, conn->params)) {
3574                                 mangle_map(short_name,True,True,conn->params);
3575                         }
3576                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3577                         data_size = 4 + len;
3578                         SIVAL(pdata,0,len);
3579                         break;
3580                 }
3581
3582                 case SMB_QUERY_FILE_NAME_INFO:
3583                         /*
3584                           this must be *exactly* right for ACLs on mapped drives to work
3585                          */
3586                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3587                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3588                         data_size = 4 + len;
3589                         SIVAL(pdata,0,len);
3590                         break;
3591
3592                 case SMB_FILE_ALLOCATION_INFORMATION:
3593                 case SMB_QUERY_FILE_ALLOCATION_INFO:
3594                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3595                         data_size = 8;
3596                         SOFF_T(pdata,0,allocation_size);
3597                         break;
3598
3599                 case SMB_FILE_END_OF_FILE_INFORMATION:
3600                 case SMB_QUERY_FILE_END_OF_FILEINFO:
3601                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3602                         data_size = 8;
3603                         SOFF_T(pdata,0,file_size);
3604                         break;
3605
3606                 case SMB_QUERY_FILE_ALL_INFO:
3607                 case SMB_FILE_ALL_INFORMATION:
3608                 {
3609                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3610                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3611                         put_long_date_timespec(pdata,create_time_ts);
3612                         put_long_date_timespec(pdata+8,atime_ts);
3613                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3614                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3615                         SIVAL(pdata,32,mode);
3616                         SIVAL(pdata,36,0); /* padding. */
3617                         pdata += 40;
3618                         SOFF_T(pdata,0,allocation_size);
3619                         SOFF_T(pdata,8,file_size);
3620                         SIVAL(pdata,16,nlink);
3621                         SCVAL(pdata,20,delete_pending);
3622                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3623                         SSVAL(pdata,22,0);
3624                         pdata += 24;
3625                         SIVAL(pdata,0,ea_size);
3626                         pdata += 4; /* EA info */
3627                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3628                         SIVAL(pdata,0,len);
3629                         pdata += 4 + len;
3630                         data_size = PTR_DIFF(pdata,(*ppdata));
3631                         break;
3632                 }
3633                 case SMB_FILE_INTERNAL_INFORMATION:
3634                         /* This should be an index number - looks like
3635                            dev/ino to me :-) 
3636
3637                            I think this causes us to fail the IFSKIT
3638                            BasicFileInformationTest. -tpot */
3639
3640                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3641                         SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3642                         SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3643                         data_size = 8;
3644                         break;
3645
3646                 case SMB_FILE_ACCESS_INFORMATION:
3647                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3648                         SIVAL(pdata,0,access_mask);
3649                         data_size = 4;
3650                         break;
3651
3652                 case SMB_FILE_NAME_INFORMATION:
3653                         /* Pathname with leading '\'. */
3654                         {
3655                                 size_t byte_len;
3656                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3657                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3658                                 SIVAL(pdata,0,byte_len);
3659                                 data_size = 4 + byte_len;
3660                                 break;
3661                         }
3662
3663                 case SMB_FILE_DISPOSITION_INFORMATION:
3664                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3665                         data_size = 1;
3666                         SCVAL(pdata,0,delete_pending);
3667                         break;
3668
3669                 case SMB_FILE_POSITION_INFORMATION:
3670                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3671                         data_size = 8;
3672                         SOFF_T(pdata,0,pos);
3673                         break;
3674
3675                 case SMB_FILE_MODE_INFORMATION:
3676                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3677                         SIVAL(pdata,0,mode);
3678                         data_size = 4;
3679                         break;
3680
3681                 case SMB_FILE_ALIGNMENT_INFORMATION:
3682                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3683                         SIVAL(pdata,0,0); /* No alignment needed. */
3684                         data_size = 4;
3685                         break;
3686
3687 #if 0
3688                 /*
3689                  * NT4 server just returns "invalid query" to this - if we try to answer
3690                  * it then NTws gets a BSOD! (tridge).
3691                  * W2K seems to want this. JRA.
3692                  */
3693                 case SMB_QUERY_FILE_STREAM_INFO:
3694 #endif
3695                 case SMB_FILE_STREAM_INFORMATION:
3696                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3697                         if (mode & aDIR) {
3698                                 data_size = 0;
3699                         } else {
3700                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3701                                 SIVAL(pdata,0,0); /* ??? */
3702                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3703                                 SOFF_T(pdata,8,file_size);
3704                                 SIVAL(pdata,16,allocation_size);
3705                                 SIVAL(pdata,20,0); /* ??? */
3706                                 data_size = 24 + byte_len;
3707                         }
3708                         break;
3709
3710                 case SMB_QUERY_COMPRESSION_INFO:
3711                 case SMB_FILE_COMPRESSION_INFORMATION:
3712                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3713                         SOFF_T(pdata,0,file_size);
3714                         SIVAL(pdata,8,0); /* ??? */
3715                         SIVAL(pdata,12,0); /* ??? */
3716                         data_size = 16;
3717                         break;
3718
3719                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3720                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3721                         put_long_date_timespec(pdata,create_time_ts);
3722                         put_long_date_timespec(pdata+8,atime_ts);
3723                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3724                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3725                         SIVAL(pdata,32,allocation_size);
3726                         SOFF_T(pdata,40,file_size);
3727                         SIVAL(pdata,48,mode);
3728                         SIVAL(pdata,52,0); /* ??? */
3729                         data_size = 56;
3730                         break;
3731
3732                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3733                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3734                         SIVAL(pdata,0,mode);
3735                         SIVAL(pdata,4,0);
3736                         data_size = 8;
3737                         break;
3738
3739                 /*
3740                  * CIFS UNIX Extensions.
3741                  */
3742
3743                 case SMB_QUERY_FILE_UNIX_BASIC:
3744
3745                         pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3746                         data_size = PTR_DIFF(pdata,(*ppdata));
3747
3748                         {
3749                                 int i;
3750                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3751
3752                                 for (i=0; i<100; i++)
3753                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3754                                 DEBUG(4,("\n"));
3755                         }
3756
3757                         break;
3758
3759                 case SMB_QUERY_FILE_UNIX_INFO2:
3760
3761                         pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3762                         data_size = PTR_DIFF(pdata,(*ppdata));
3763
3764                         {
3765                                 int i;
3766                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3767
3768                                 for (i=0; i<100; i++)
3769                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3770                                 DEBUG(4,("\n"));
3771                         }
3772
3773                         break;
3774
3775                 case SMB_QUERY_FILE_UNIX_LINK:
3776                         {
3777                                 pstring buffer;
3778
3779                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3780 #ifdef S_ISLNK
3781                                 if(!S_ISLNK(sbuf.st_mode))
3782                                         return(UNIXERROR(ERRSRV,ERRbadlink));
3783 #else
3784                                 return(UNIXERROR(ERRDOS,ERRbadlink));
3785 #endif
3786                                 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
3787                                 if (len == -1)
3788                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3789                                 buffer[len] = 0;
3790                                 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3791                                 pdata += len;
3792                                 data_size = PTR_DIFF(pdata,(*ppdata));
3793
3794                                 break;
3795                         }
3796
3797 #if defined(HAVE_POSIX_ACLS)
3798                 case SMB_QUERY_POSIX_ACL:
3799                         {
3800                                 SMB_ACL_T file_acl = NULL;
3801                                 SMB_ACL_T def_acl = NULL;
3802                                 uint16 num_file_acls = 0;
3803                                 uint16 num_def_acls = 0;
3804
3805                                 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3806                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3807                                 } else {
3808                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3809                                 }
3810
3811                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3812                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3813                                                 fname ));
3814                                         return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3815                                 }
3816
3817                                 if (S_ISDIR(sbuf.st_mode)) {
3818                                         if (fsp && fsp->is_directory) {
3819                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3820                                         } else {
3821                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3822                                         }
3823                                         def_acl = free_empty_sys_acl(conn, def_acl);
3824                                 }
3825
3826                                 num_file_acls = count_acl_entries(conn, file_acl);
3827                                 num_def_acls = count_acl_entries(conn, def_acl);
3828
3829                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3830                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3831                                                 data_size,
3832                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3833                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
3834                                         if (file_acl) {
3835                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3836                                         }
3837                                         if (def_acl) {
3838                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3839                                         }
3840                                         return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3841                                 }
3842
3843                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3844                                 SSVAL(pdata,2,num_file_acls);
3845                                 SSVAL(pdata,4,num_def_acls);
3846                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3847                                         if (file_acl) {
3848                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3849                                         }
3850                                         if (def_acl) {
3851                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3852                                         }
3853                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3854                                 }
3855                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3856                                         if (file_acl) {
3857                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3858                                         }
3859                                         if (def_acl) {
3860                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3861                                         }
3862                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3863                                 }
3864
3865                                 if (file_acl) {
3866                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3867                                 }
3868                                 if (def_acl) {
3869                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3870                                 }
3871                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3872                                 break;
3873                         }
3874 #endif
3875
3876
3877                 case SMB_QUERY_POSIX_LOCK:
3878                 {
3879                         NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3880                         SMB_BIG_UINT count;
3881                         SMB_BIG_UINT offset;
3882                         uint32 lock_pid;
3883                         enum brl_type lock_type;
3884
3885                         if (total_data != POSIX_LOCK_DATA_SIZE) {
3886                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3887                         }
3888
3889                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3890                                 case POSIX_LOCK_TYPE_READ:
3891                                         lock_type = READ_LOCK;
3892                                         break;
3893                                 case POSIX_LOCK_TYPE_WRITE:
3894                                         lock_type = WRITE_LOCK;
3895                                         break;
3896                                 case POSIX_LOCK_TYPE_UNLOCK:
3897                                 default:
3898                                         /* There's no point in asking for an unlock... */
3899                                         talloc_destroy(data_ctx);
3900                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3901                         }
3902
3903                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3904 #if defined(HAVE_LONGLONG)
3905                         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3906                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3907                         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3908                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3909 #else /* HAVE_LONGLONG */
3910                         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3911                         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3912 #endif /* HAVE_LONGLONG */
3913
3914                         status = query_lock(fsp,
3915                                         &lock_pid,
3916                                         &count,
3917                                         &offset,
3918                                         &lock_type,
3919                                         POSIX_LOCK);
3920
3921                         if (ERROR_WAS_LOCK_DENIED(status)) {
3922                                 /* Here we need to report who has it locked... */
3923                                 data_size = POSIX_LOCK_DATA_SIZE;
3924
3925                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3926                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3927                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3928 #if defined(HAVE_LONGLONG)
3929                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3930                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3931                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3932                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3933 #else /* HAVE_LONGLONG */
3934                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3935                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3936 #endif /* HAVE_LONGLONG */
3937
3938                         } else if (NT_STATUS_IS_OK(status)) {
3939                                 /* For success we just return a copy of what we sent
3940                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3941                                 data_size = POSIX_LOCK_DATA_SIZE;
3942                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3943                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3944                         } else {
3945                                 return ERROR_NT(status);
3946                         }
3947                         break;
3948                 }
3949
3950                 default:
3951                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3952         }
3953
3954         send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3955
3956         return(-1);
3957 }
3958
3959 /****************************************************************************
3960  Set a hard link (called by UNIX extensions and by NT rename with HARD link
3961  code.
3962 ****************************************************************************/
3963
3964 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
3965 {
3966         SMB_STRUCT_STAT sbuf1, sbuf2;
3967         pstring last_component_oldname;
3968         pstring last_component_newname;
3969         NTSTATUS status = NT_STATUS_OK;
3970
3971         ZERO_STRUCT(sbuf1);
3972         ZERO_STRUCT(sbuf2);
3973
3974         status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
3975         if (!NT_STATUS_IS_OK(status)) {
3976                 return status;
3977         }
3978
3979         status = check_name(conn, oldname);
3980         if (!NT_STATUS_IS_OK(status)) {
3981                 return status;
3982         }
3983
3984         /* source must already exist. */
3985         if (!VALID_STAT(sbuf1)) {
3986                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3987         }
3988
3989         status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
3990         if (!NT_STATUS_IS_OK(status)) {
3991                 return status;
3992         }
3993
3994         status = check_name(conn, newname);
3995         if (!NT_STATUS_IS_OK(status)) {
3996                 return status;
3997         }
3998
3999         /* Disallow if newname already exists. */
4000         if (VALID_STAT(sbuf2)) {
4001                 return NT_STATUS_OBJECT_NAME_COLLISION;
4002         }
4003
4004         /* No links from a directory. */
4005         if (S_ISDIR(sbuf1.st_mode)) {
4006                 return NT_STATUS_FILE_IS_A_DIRECTORY;
4007         }
4008
4009         /* Ensure this is within the share. */
4010         status = reduce_name(conn, oldname);
4011         if (!NT_STATUS_IS_OK(status)) {
4012                 return status;
4013         }
4014
4015         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4016
4017         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4018                 status = map_nt_error_from_unix(errno);
4019                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4020                                 nt_errstr(status), newname, oldname));
4021         }
4022
4023         return status;
4024 }
4025
4026 /****************************************************************************
4027  Deal with setting the time from any of the setfilepathinfo functions.
4028 ****************************************************************************/
4029
4030 static NTSTATUS smb_set_file_time(connection_struct *conn,
4031                                 files_struct *fsp,
4032                                 const char *fname,
4033                                 const SMB_STRUCT_STAT *psbuf,
4034                                 struct timespec ts[2])
4035 {
4036         uint32 action =
4037                 FILE_NOTIFY_CHANGE_LAST_ACCESS
4038                 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4039
4040         
4041         if (!VALID_STAT(*psbuf)) {
4042                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4043         }
4044
4045         /* get some defaults (no modifications) if any info is zero or -1. */
4046         if (null_timespec(ts[0])) {
4047                 ts[0] = get_atimespec(psbuf);
4048                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4049         }
4050
4051         if (null_timespec(ts[1])) {
4052                 ts[1] = get_mtimespec(psbuf);
4053                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4054         }
4055
4056         DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4057         DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4058
4059         /*
4060          * Try and set the times of this file if
4061          * they are different from the current values.
4062          */
4063
4064         {
4065                 struct timespec mts = get_mtimespec(psbuf);
4066                 struct timespec ats = get_atimespec(psbuf);
4067                 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4068                         return NT_STATUS_OK;
4069                 }
4070         }
4071
4072         if(fsp != NULL) {
4073                 /*
4074                  * This was a setfileinfo on an open file.
4075                  * NT does this a lot. We also need to 
4076                  * set the time here, as it can be read by 
4077                  * FindFirst/FindNext and with the patch for bug #2045
4078                  * in smbd/fileio.c it ensures that this timestamp is
4079                  * kept sticky even after a write. We save the request
4080                  * away and will set it on file close and after a write. JRA.
4081                  */
4082
4083                 if (!null_timespec(ts[1])) {
4084                         DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4085                                 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4086                         fsp_set_pending_modtime(fsp, ts[1]);
4087                 }
4088
4089         }
4090         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4091
4092         if(file_ntimes(conn, fname, ts)!=0) {
4093                 return map_nt_error_from_unix(errno);
4094         }
4095         if (action != 0) {
4096                 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4097         }
4098         return NT_STATUS_OK;
4099 }
4100
4101 /****************************************************************************
4102  Deal with setting the dosmode from any of the setfilepathinfo functions.
4103 ****************************************************************************/
4104
4105 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4106                                 const char *fname,
4107                                 SMB_STRUCT_STAT *psbuf,
4108                                 uint32 dosmode)
4109 {
4110         if (!VALID_STAT(*psbuf)) {
4111                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4112         }
4113
4114         if (dosmode) {
4115                 if (S_ISDIR(psbuf->st_mode)) {
4116                         dosmode |= aDIR;
4117                 } else {
4118                         dosmode &= ~aDIR;
4119                 }
4120         }
4121
4122         DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4123
4124         /* check the mode isn't different, before changing it */
4125         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4126
4127                 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4128                                         fname, (unsigned int)dosmode ));
4129
4130                 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4131                         DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4132                                                 fname, strerror(errno)));
4133                         return map_nt_error_from_unix(errno);
4134                 }
4135         }
4136         return NT_STATUS_OK;
4137 }
4138
4139 /****************************************************************************
4140  Deal with setting the size from any of the setfilepathinfo functions.
4141 ****************************************************************************/
4142
4143 static NTSTATUS smb_set_file_size(connection_struct *conn,
4144                                 files_struct *fsp,
4145                                 const char *fname,
4146                                 SMB_STRUCT_STAT *psbuf,
4147                                 SMB_OFF_T size)
4148 {
4149         NTSTATUS status = NT_STATUS_OK;
4150         files_struct *new_fsp = NULL;
4151
4152         if (!VALID_STAT(*psbuf)) {
4153                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4154         }
4155
4156         DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4157
4158         if (size == get_file_size(*psbuf)) {
4159                 return NT_STATUS_OK;
4160         }
4161
4162         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4163                 fname, (double)size ));
4164
4165         if (fsp && fsp->fh->fd != -1) {
4166                 /* Handle based call. */
4167                 if (vfs_set_filelen(fsp, size) == -1) {
4168                         return map_nt_error_from_unix(errno);
4169                 }
4170                 return NT_STATUS_OK;
4171         }
4172
4173         status = open_file_ntcreate(conn, fname, psbuf,
4174                                 FILE_WRITE_DATA,
4175                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4176                                 FILE_OPEN,
4177                                 0,
4178                                 FILE_ATTRIBUTE_NORMAL,
4179                                 FORCE_OPLOCK_BREAK_TO_NONE,
4180                                 NULL, &new_fsp);
4181         
4182         if (!NT_STATUS_IS_OK(status)) {
4183                 /* NB. We check for open_was_deferred in the caller. */
4184                 return status;
4185         }
4186
4187         if (vfs_set_filelen(new_fsp, size) == -1) {
4188                 status = map_nt_error_from_unix(errno);
4189                 close_file(new_fsp,NORMAL_CLOSE);
4190                 return status;
4191         }
4192
4193         close_file(new_fsp,NORMAL_CLOSE);
4194         return NT_STATUS_OK;
4195 }
4196
4197 /****************************************************************************
4198  Deal with SMB_INFO_SET_EA.
4199 ****************************************************************************/
4200
4201 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4202                                 const char *pdata,
4203                                 int total_data,
4204                                 files_struct *fsp,
4205                                 const char *fname)
4206 {
4207         struct ea_list *ea_list = NULL;
4208         TALLOC_CTX *ctx = NULL;
4209         NTSTATUS status = NT_STATUS_OK;
4210
4211         if (total_data < 10) {
4212
4213                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4214                    length. They seem to have no effect. Bug #3212. JRA */
4215
4216                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4217                         /* We're done. We only get EA info in this call. */
4218                         return NT_STATUS_OK;
4219                 }
4220
4221                 return NT_STATUS_INVALID_PARAMETER;
4222         }
4223
4224         if (IVAL(pdata,0) > total_data) {
4225                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4226                         IVAL(pdata,0), (unsigned int)total_data));
4227                 return NT_STATUS_INVALID_PARAMETER;
4228         }
4229
4230         ctx = talloc_init("SMB_INFO_SET_EA");
4231         if (!ctx) {
4232                 return NT_STATUS_NO_MEMORY;
4233         }
4234         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4235         if (!ea_list) {
4236                 talloc_destroy(ctx);
4237                 return NT_STATUS_INVALID_PARAMETER;
4238         }
4239         status = set_ea(conn, fsp, fname, ea_list);
4240         talloc_destroy(ctx);
4241
4242         return status;
4243 }
4244
4245 /****************************************************************************
4246  Deal with SMB_SET_FILE_DISPOSITION_INFO.
4247 ****************************************************************************/
4248
4249 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4250                                 const char *pdata,
4251                                 int total_data,
4252                                 files_struct *fsp,
4253                                 const char *fname,
4254                                 SMB_STRUCT_STAT *psbuf)
4255 {
4256         NTSTATUS status = NT_STATUS_OK;
4257         BOOL delete_on_close;
4258         uint32 dosmode = 0;
4259
4260         if (total_data < 1) {
4261                 return NT_STATUS_INVALID_PARAMETER;
4262         }
4263
4264         if (fsp == NULL) {
4265                 return NT_STATUS_INVALID_HANDLE;
4266         }
4267
4268         delete_on_close = (CVAL(pdata,0) ? True : False);
4269         dosmode = dos_mode(conn, fname, psbuf);
4270
4271         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4272                 "delete_on_close = %u\n",
4273                 fsp->fsp_name,
4274                 (unsigned int)dosmode,
4275                 (unsigned int)delete_on_close ));
4276
4277         status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4278  
4279         if (!NT_STATUS_IS_OK(status)) {
4280                 return status;
4281         }
4282
4283         /* The set is across all open files on this dev/inode pair. */
4284         if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4285                 return NT_STATUS_ACCESS_DENIED;
4286         }
4287         return NT_STATUS_OK;
4288 }
4289
4290 /****************************************************************************
4291  Deal with SMB_FILE_POSITION_INFORMATION.
4292 ****************************************************************************/
4293
4294 static NTSTATUS smb_file_position_information(connection_struct *conn,
4295                                 const char *pdata,
4296                                 int total_data,
4297                                 files_struct *fsp)
4298 {
4299         SMB_BIG_UINT position_information;
4300
4301         if (total_data < 8) {
4302                 return NT_STATUS_INVALID_PARAMETER;
4303         }
4304
4305         if (fsp == NULL) {
4306                 /* Ignore on pathname based set. */
4307                 return NT_STATUS_OK;
4308         }
4309
4310         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4311 #ifdef LARGE_SMB_OFF_T
4312         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4313 #else /* LARGE_SMB_OFF_T */
4314         if (IVAL(pdata,4) != 0) {
4315                 /* more than 32 bits? */
4316                 return NT_STATUS_INVALID_PARAMETER;
4317         }
4318 #endif /* LARGE_SMB_OFF_T */
4319
4320         DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4321                 fsp->fsp_name, (double)position_information ));
4322         fsp->fh->position_information = position_information;
4323         return NT_STATUS_OK;
4324 }
4325
4326 /****************************************************************************
4327  Deal with SMB_FILE_MODE_INFORMATION.
4328 ****************************************************************************/
4329
4330 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4331                                 const char *pdata,
4332                                 int total_data)
4333 {
4334         uint32 mode;
4335
4336         if (total_data < 4) {
4337                 return NT_STATUS_INVALID_PARAMETER;
4338         }
4339         mode = IVAL(pdata,0);
4340         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4341                 return NT_STATUS_INVALID_PARAMETER;
4342         }
4343         return NT_STATUS_OK;
4344 }
4345
4346 /****************************************************************************
4347  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4348 ****************************************************************************/
4349
4350 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4351                                 char *inbuf,
4352                                 const char *pdata,
4353                                 int total_data,
4354                                 const char *fname)
4355 {
4356         pstring link_target;
4357         const char *newname = fname;
4358         NTSTATUS status = NT_STATUS_OK;
4359
4360         /* Set a symbolic link. */
4361         /* Don't allow this if follow links is false. */
4362
4363         if (total_data == 0) {
4364                 return NT_STATUS_INVALID_PARAMETER;
4365         }
4366
4367         if (!lp_symlinks(SNUM(conn))) {
4368                 return NT_STATUS_ACCESS_DENIED;
4369         }
4370
4371         srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4372
4373         /* !widelinks forces the target path to be within the share. */
4374         /* This means we can interpret the target as a pathname. */
4375         if (!lp_widelinks(SNUM(conn))) {
4376                 pstring rel_name;
4377                 char *last_dirp = NULL;
4378
4379                 unix_format(link_target);
4380                 if (*link_target == '/') {
4381                         /* No absolute paths allowed. */
4382                         return NT_STATUS_ACCESS_DENIED;
4383                 }
4384                 pstrcpy(rel_name, newname);
4385                 last_dirp = strrchr_m(rel_name, '/');
4386                 if (last_dirp) {
4387                         last_dirp[1] = '\0';
4388                 } else {
4389                         pstrcpy(rel_name, "./");
4390                 }
4391                 pstrcat(rel_name, link_target);
4392
4393                 status = check_name(conn, rel_name);
4394                 if (!NT_STATUS_IS_OK(status)) {
4395                         return status;
4396                 }
4397         }
4398
4399         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4400                         newname, link_target ));
4401
4402         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4403                 return map_nt_error_from_unix(errno);
4404         }
4405
4406         return NT_STATUS_OK;
4407 }
4408
4409 /****************************************************************************
4410  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4411 ****************************************************************************/
4412
4413 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4414                                 char *inbuf,
4415                                 char *outbuf,
4416                                 const char *pdata,
4417                                 int total_data,
4418                                 pstring fname)
4419 {
4420         pstring oldname;
4421         NTSTATUS status = NT_STATUS_OK;
4422
4423         /* Set a hard link. */
4424         if (total_data == 0) {
4425                 return NT_STATUS_INVALID_PARAMETER;
4426         }
4427
4428         srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4429         if (!NT_STATUS_IS_OK(status)) {
4430                 return status;
4431         }
4432
4433         if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname)) {
4434                 return NT_STATUS_PATH_NOT_COVERED;
4435         }
4436
4437         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4438                 fname, oldname));
4439
4440         return hardlink_internals(conn, oldname, fname);
4441 }
4442
4443 /****************************************************************************
4444  Deal with SMB_FILE_RENAME_INFORMATION.
4445 ****************************************************************************/
4446
4447 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4448                                 char *inbuf,
4449                                 char *outbuf,
4450                                 const char *pdata,
4451                                 int total_data,
4452                                 files_struct *fsp,
4453                                 pstring fname)
4454 {
4455         BOOL overwrite;
4456         /* uint32 root_fid; */  /* Not used */
4457         uint32 len;
4458         pstring newname;
4459         pstring base_name;
4460         BOOL dest_has_wcard = False;
4461         NTSTATUS status = NT_STATUS_OK;
4462         char *p;
4463
4464         if (total_data < 13) {
4465                 return NT_STATUS_INVALID_PARAMETER;
4466         }
4467
4468         overwrite = (CVAL(pdata,0) ? True : False);
4469         /* root_fid = IVAL(pdata,4); */
4470         len = IVAL(pdata,8);
4471
4472         if (len > (total_data - 12) || (len == 0)) {
4473                 return NT_STATUS_INVALID_PARAMETER;
4474         }
4475
4476         srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4477         if (!NT_STATUS_IS_OK(status)) {
4478                 return status;
4479         }
4480
4481         if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname)) {
4482                 return NT_STATUS_PATH_NOT_COVERED;
4483         }
4484
4485         /* Check the new name has no '/' characters. */
4486         if (strchr_m(newname, '/')) {
4487                 return NT_STATUS_NOT_SUPPORTED;
4488         }
4489
4490         /* Create the base directory. */
4491         pstrcpy(base_name, fname);
4492         p = strrchr_m(base_name, '/');
4493         if (p) {
4494                 *p = '\0';
4495         }
4496         /* Append the new name. */
4497         pstrcat(base_name, "/");
4498         pstrcat(base_name, newname);
4499
4500         if (fsp) {
4501                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4502                         fsp->fnum, fsp->fsp_name, base_name ));
4503                 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4504         } else {
4505                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4506                         fname, newname ));
4507                 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4508         }
4509
4510         return status;
4511 }
4512
4513 /****************************************************************************
4514  Deal with SMB_SET_POSIX_ACL.
4515 ****************************************************************************/
4516
4517 #if defined(HAVE_POSIX_ACLS)
4518 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4519                                 const char *pdata,
4520                                 int total_data,
4521                                 files_struct *fsp,
4522                                 const char *fname,
4523                                 SMB_STRUCT_STAT *psbuf)
4524 {
4525         uint16 posix_acl_version;
4526         uint16 num_file_acls;
4527         uint16 num_def_acls;
4528         BOOL valid_file_acls = True;
4529         BOOL valid_def_acls = True;
4530
4531         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4532                 return NT_STATUS_INVALID_PARAMETER;
4533         }
4534         posix_acl_version = SVAL(pdata,0);
4535         num_file_acls = SVAL(pdata,2);
4536         num_def_acls = SVAL(pdata,4);
4537
4538         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4539                 valid_file_acls = False;
4540                 num_file_acls = 0;
4541         }
4542
4543         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4544                 valid_def_acls = False;
4545                 num_def_acls = 0;
4546         }
4547
4548         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4549                 return NT_STATUS_INVALID_PARAMETER;
4550         }
4551
4552         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4553                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4554                 return NT_STATUS_INVALID_PARAMETER;
4555         }
4556
4557         DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4558                 fname ? fname : fsp->fsp_name,
4559                 (unsigned int)num_file_acls,
4560                 (unsigned int)num_def_acls));
4561
4562         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4563                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4564                 return map_nt_error_from_unix(errno);
4565         }
4566
4567         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4568                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
4569                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4570                 return map_nt_error_from_unix(errno);
4571         }
4572         return NT_STATUS_OK;
4573 }
4574 #endif
4575
4576 /****************************************************************************
4577  Deal with SMB_SET_POSIX_LOCK.
4578 ****************************************************************************/
4579
4580 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4581                                 char *inbuf,
4582                                 int length,
4583                                 const char *pdata,
4584                                 int total_data,
4585                                 files_struct *fsp)
4586 {
4587         SMB_BIG_UINT count;
4588         SMB_BIG_UINT offset;
4589         uint32 lock_pid;
4590         BOOL blocking_lock = False;
4591         enum brl_type lock_type;
4592         NTSTATUS status = NT_STATUS_OK;
4593
4594         if (fsp == NULL || fsp->fh->fd == -1) {
4595                 return NT_STATUS_INVALID_HANDLE;
4596         }
4597
4598         if (total_data != POSIX_LOCK_DATA_SIZE) {
4599                 return NT_STATUS_INVALID_PARAMETER;
4600         }
4601
4602         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4603                 case POSIX_LOCK_TYPE_READ:
4604                         lock_type = READ_LOCK;
4605                         break;
4606                 case POSIX_LOCK_TYPE_WRITE:
4607                         /* Return the right POSIX-mappable error code for files opened read-only. */
4608                         if (!fsp->can_write) {
4609                                 return NT_STATUS_INVALID_HANDLE;
4610                         }
4611                         lock_type = WRITE_LOCK;
4612                         break;
4613                 case POSIX_LOCK_TYPE_UNLOCK:
4614                         lock_type = UNLOCK_LOCK;
4615                         break;
4616                 default:
4617                         return NT_STATUS_INVALID_PARAMETER;
4618         }
4619
4620         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4621                 blocking_lock = False;
4622         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4623                 blocking_lock = True;
4624         } else {
4625                 return NT_STATUS_INVALID_PARAMETER;
4626         }
4627
4628         if (!lp_blocking_locks(SNUM(conn))) { 
4629                 blocking_lock = False;
4630         }
4631
4632         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4633 #if defined(HAVE_LONGLONG)
4634         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4635                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4636         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4637                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4638 #else /* HAVE_LONGLONG */
4639         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4640         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4641 #endif /* HAVE_LONGLONG */
4642
4643         DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4644                         "lock_pid = %u, count = %.0f, offset = %.0f\n",
4645                 fsp->fsp_name,
4646                 (unsigned int)lock_type,
4647                 (unsigned int)lock_pid,
4648                 (double)count,
4649                 (double)offset ));
4650
4651         if (lock_type == UNLOCK_LOCK) {
4652                 status = do_unlock(fsp,
4653                                 lock_pid,
4654                                 count,
4655                                 offset,
4656                                 POSIX_LOCK);
4657         } else {
4658                 struct byte_range_lock *br_lck = do_lock(fsp,
4659                                                         lock_pid,
4660                                                         count,
4661                                                         offset,
4662                                                         lock_type,
4663                                                         POSIX_LOCK,
4664                                                         blocking_lock,
4665                                                         &status);
4666
4667                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4668                         /*
4669                          * A blocking lock was requested. Package up
4670                          * this smb into a queued request and push it
4671                          * onto the blocking lock queue.
4672                          */
4673                         if(push_blocking_lock_request(br_lck,
4674                                                 inbuf, length,
4675                                                 fsp,
4676                                                 -1, /* infinite timeout. */
4677                                                 0,
4678                                                 lock_pid,
4679                                                 lock_type,
4680                                                 POSIX_LOCK,
4681                                                 offset,
4682                                                 count)) {
4683                                 TALLOC_FREE(br_lck);
4684                                 return status;
4685                         }
4686                 }
4687                 TALLOC_FREE(br_lck);
4688         }
4689
4690         return status;
4691 }
4692
4693 /****************************************************************************
4694  Deal with SMB_INFO_STANDARD.
4695 ****************************************************************************/
4696
4697 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4698                                         const char *pdata,
4699                                         int total_data,
4700                                         files_struct *fsp,
4701                                         const char *fname,
4702                                         const SMB_STRUCT_STAT *psbuf)
4703 {
4704         struct timespec ts[2];
4705
4706         if (total_data < 12) {
4707                 return NT_STATUS_INVALID_PARAMETER;
4708         }
4709
4710         /* access time */
4711         ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4712         /* write time */
4713         ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4714
4715         DEBUG(10,("smb_set_info_standard: file %s\n",
4716                 fname ? fname : fsp->fsp_name ));
4717
4718         return smb_set_file_time(conn,
4719                                 fsp,
4720                                 fname,
4721                                 psbuf,
4722                                 ts);
4723 }
4724
4725 /****************************************************************************
4726  Deal with SMB_SET_FILE_BASIC_INFO.
4727 ****************************************************************************/
4728
4729 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4730                                         const char *pdata,
4731                                         int total_data,
4732                                         files_struct *fsp,
4733                                         const char *fname,
4734                                         SMB_STRUCT_STAT *psbuf)
4735 {
4736         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4737         struct timespec write_time;
4738         struct timespec changed_time;
4739         uint32 dosmode = 0;
4740         struct timespec ts[2];
4741         NTSTATUS status = NT_STATUS_OK;
4742
4743         if (total_data < 36) {
4744                 return NT_STATUS_INVALID_PARAMETER;
4745         }
4746
4747         /* Set the attributes */
4748         dosmode = IVAL(pdata,32);
4749         status = smb_set_file_dosmode(conn,
4750                                         fname,
4751                                         psbuf,
4752                                         dosmode);
4753         if (!NT_STATUS_IS_OK(status)) {
4754                 return status;
4755         }
4756
4757         /* Ignore create time at offset pdata. */
4758
4759         /* access time */
4760         ts[0] = interpret_long_date(pdata+8);
4761
4762         write_time = interpret_long_date(pdata+16);
4763         changed_time = interpret_long_date(pdata+24);
4764
4765         /* mtime */
4766         ts[1] = timespec_min(&write_time, &changed_time);
4767
4768         if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4769                 ts[1] = write_time;
4770         }
4771
4772         /* Prefer a defined time to an undefined one. */
4773         if (null_timespec(ts[1])) {
4774                 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4775         }
4776
4777         DEBUG(10,("smb_set_file_basic_info: file %s\n",
4778                 fname ? fname : fsp->fsp_name ));
4779
4780         return smb_set_file_time(conn,
4781                                 fsp,
4782                                 fname,
4783                                 psbuf,
4784                                 ts);
4785 }
4786
4787 /****************************************************************************
4788  Deal with SMB_SET_FILE_ALLOCATION_INFO.
4789 ****************************************************************************/
4790
4791 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4792                                         const char *pdata,
4793                                         int total_data,
4794                                         files_struct *fsp,
4795                                         const char *fname,
4796                                         SMB_STRUCT_STAT *psbuf)
4797 {
4798         SMB_BIG_UINT allocation_size = 0;
4799         NTSTATUS status = NT_STATUS_OK;
4800         files_struct *new_fsp = NULL;
4801
4802         if (!VALID_STAT(*psbuf)) {
4803                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4804         }
4805
4806         if (total_data < 8) {
4807                 return NT_STATUS_INVALID_PARAMETER;
4808         }
4809
4810         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4811 #ifdef LARGE_SMB_OFF_T
4812         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4813 #else /* LARGE_SMB_OFF_T */
4814         if (IVAL(pdata,4) != 0) {
4815                 /* more than 32 bits? */
4816                 return NT_STATUS_INVALID_PARAMETER;
4817         }
4818 #endif /* LARGE_SMB_OFF_T */
4819
4820         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4821                         fname, (double)allocation_size ));
4822
4823         if (allocation_size) {
4824                 allocation_size = smb_roundup(conn, allocation_size);
4825         }
4826
4827         if(allocation_size == get_file_size(*psbuf)) {
4828                 return NT_STATUS_OK;
4829         }
4830  
4831         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4832                         fname, (double)allocation_size ));
4833  
4834         if (fsp && fsp->fh->fd != -1) {
4835                 /* Open file handle. */
4836                 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4837                         return map_nt_error_from_unix(errno);
4838                 }
4839                 return NT_STATUS_OK;
4840         }
4841
4842         /* Pathname or stat or directory file. */
4843
4844         status = open_file_ntcreate(conn, fname, psbuf,
4845                                 FILE_WRITE_DATA,
4846                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4847                                 FILE_OPEN,
4848                                 0,
4849                                 FILE_ATTRIBUTE_NORMAL,
4850                                 FORCE_OPLOCK_BREAK_TO_NONE,
4851                                 NULL, &new_fsp);
4852  
4853         if (!NT_STATUS_IS_OK(status)) {
4854                 /* NB. We check for open_was_deferred in the caller. */
4855                 return status;
4856         }
4857         if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4858                 status = map_nt_error_from_unix(errno);
4859                 close_file(new_fsp,NORMAL_CLOSE);
4860                 return status;
4861         }
4862
4863         close_file(new_fsp,NORMAL_CLOSE);
4864         return NT_STATUS_OK;
4865 }
4866
4867 /****************************************************************************
4868  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4869 ****************************************************************************/
4870
4871 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4872                                         const char *pdata,
4873                                         int total_data,
4874                                         files_struct *fsp,
4875                                         const char *fname,
4876                                         SMB_STRUCT_STAT *psbuf)
4877 {
4878         SMB_OFF_T size;
4879
4880         if (total_data < 8) {
4881                 return NT_STATUS_INVALID_PARAMETER;
4882         }
4883
4884         size = IVAL(pdata,0);
4885 #ifdef LARGE_SMB_OFF_T
4886         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4887 #else /* LARGE_SMB_OFF_T */
4888         if (IVAL(pdata,4) != 0) {
4889                 /* more than 32 bits? */
4890                 return NT_STATUS_INVALID_PARAMETER;
4891         }
4892 #endif /* LARGE_SMB_OFF_T */
4893         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4894                 "file %s to %.0f\n", fname, (double)size ));
4895
4896         return smb_set_file_size(conn,
4897                                 fsp,
4898                                 fname,
4899                                 psbuf,
4900                                 size);
4901 }
4902
4903 /****************************************************************************
4904  Allow a UNIX info mknod.
4905 ****************************************************************************/
4906
4907 static NTSTATUS smb_unix_mknod(connection_struct *conn,
4908                                         const char *pdata,
4909                                         int total_data,
4910                                         const char *fname,
4911                                         SMB_STRUCT_STAT *psbuf)
4912 {
4913         uint32 file_type = IVAL(pdata,56);
4914 #if defined(HAVE_MAKEDEV)
4915         uint32 dev_major = IVAL(pdata,60);
4916         uint32 dev_minor = IVAL(pdata,68);
4917 #endif
4918         SMB_DEV_T dev = (SMB_DEV_T)0;
4919         uint32 raw_unixmode = IVAL(pdata,84);
4920         NTSTATUS status;
4921         mode_t unixmode;
4922
4923         if (total_data < 100) {
4924                 return NT_STATUS_INVALID_PARAMETER;
4925         }
4926
4927         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
4928         if (!NT_STATUS_IS_OK(status)) {
4929                 return status;
4930         }
4931
4932 #if defined(HAVE_MAKEDEV)
4933         dev = makedev(dev_major, dev_minor);
4934 #endif
4935
4936         switch (file_type) {
4937 #if defined(S_IFIFO)
4938                 case UNIX_TYPE_FIFO:
4939                         unixmode |= S_IFIFO;
4940                         break;
4941 #endif
4942 #if defined(S_IFSOCK)
4943                 case UNIX_TYPE_SOCKET:
4944                         unixmode |= S_IFSOCK;
4945                         break;
4946 #endif
4947 #if defined(S_IFCHR)
4948                 case UNIX_TYPE_CHARDEV:
4949                         unixmode |= S_IFCHR;
4950                         break;
4951 #endif
4952 #if defined(S_IFBLK)
4953                 case UNIX_TYPE_BLKDEV:
4954                         unixmode |= S_IFBLK;
4955                         break;
4956 #endif
4957                 default:
4958                         return NT_STATUS_INVALID_PARAMETER;
4959         }
4960
4961         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4962 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
4963
4964         /* Ok - do the mknod. */
4965         if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
4966                 return map_nt_error_from_unix(errno);
4967         }
4968
4969         /* If any of the other "set" calls fail we
4970          * don't want to end up with a half-constructed mknod.
4971          */
4972
4973         if (lp_inherit_perms(SNUM(conn))) {
4974                 inherit_access_acl(
4975                         conn, parent_dirname(fname),
4976                         fname, unixmode);
4977         }
4978
4979         if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
4980                 status = map_nt_error_from_unix(errno);
4981                 SMB_VFS_UNLINK(conn,fname);
4982                 return status;
4983         }
4984         return NT_STATUS_OK;
4985 }
4986
4987 /****************************************************************************
4988  Deal with SMB_SET_FILE_UNIX_BASIC.
4989 ****************************************************************************/
4990
4991 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
4992                                         const char *pdata,
4993                                         int total_data,
4994                                         files_struct *fsp,
4995                                         const char *fname,
4996                                         SMB_STRUCT_STAT *psbuf)
4997 {
4998         struct timespec ts[2];
4999         uint32 raw_unixmode;
5000         mode_t unixmode;
5001         SMB_OFF_T size = 0;
5002         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5003         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5004         NTSTATUS status = NT_STATUS_OK;
5005         BOOL delete_on_fail = False;
5006         enum perm_type ptype;
5007
5008         if (total_data < 100) {
5009                 return NT_STATUS_INVALID_PARAMETER;
5010         }
5011
5012         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5013            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5014                 size=IVAL(pdata,0); /* first 8 Bytes are size */
5015 #ifdef LARGE_SMB_OFF_T
5016                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5017 #else /* LARGE_SMB_OFF_T */
5018                 if (IVAL(pdata,4) != 0) {
5019                         /* more than 32 bits? */
5020                         return NT_STATUS_INVALID_PARAMETER;
5021                 }
5022 #endif /* LARGE_SMB_OFF_T */
5023         }
5024
5025         ts[0] = interpret_long_date(pdata+24); /* access_time */
5026         ts[1] = interpret_long_date(pdata+32); /* modification_time */
5027         set_owner = (uid_t)IVAL(pdata,40);
5028         set_grp = (gid_t)IVAL(pdata,48);
5029         raw_unixmode = IVAL(pdata,84);
5030
5031         if (VALID_STAT(*psbuf)) {
5032                 if (S_ISDIR(psbuf->st_mode)) {
5033                         ptype = PERM_EXISTING_DIR;
5034                 } else {
5035                         ptype = PERM_EXISTING_FILE;
5036                 }
5037         } else {
5038                 ptype = PERM_NEW_FILE;
5039         }
5040
5041         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5042         if (!NT_STATUS_IS_OK(status)) {
5043                 return status;
5044         }
5045
5046         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5047 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5048                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5049
5050         if (!VALID_STAT(*psbuf)) {
5051                 /*
5052                  * The only valid use of this is to create character and block
5053                  * devices, and named pipes. This is deprecated (IMHO) and 
5054                  * a new info level should be used for mknod. JRA.
5055                  */
5056
5057                 status = smb_unix_mknod(conn,
5058                                         pdata,
5059                                         total_data,
5060                                         fname,
5061                                         psbuf);
5062                 if (!NT_STATUS_IS_OK(status)) {
5063                         return status;
5064                 }
5065
5066                 /* Ensure we don't try and change anything else. */
5067                 raw_unixmode = SMB_MODE_NO_CHANGE;
5068                 size = get_file_size(*psbuf);
5069                 ts[0] = get_atimespec(psbuf);
5070                 ts[1] = get_mtimespec(psbuf);
5071                 /* 
5072                  * We continue here as we might want to change the 
5073                  * owner uid/gid.
5074                  */
5075                 delete_on_fail = True;
5076         }
5077
5078 #if 1
5079         /* Horrible backwards compatibility hack as an old server bug
5080          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5081          * */
5082
5083         if (!size) {
5084                 size = get_file_size(*psbuf);
5085         }
5086 #endif
5087
5088         /*
5089          * Deal with the UNIX specific mode set.
5090          */
5091
5092         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5093                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5094                         (unsigned int)unixmode, fname ));
5095                 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5096                         return map_nt_error_from_unix(errno);
5097                 }
5098         }
5099
5100         /*
5101          * Deal with the UNIX specific uid set.
5102          */
5103
5104         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5105                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5106                         (unsigned int)set_owner, fname ));
5107                 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5108                         status = map_nt_error_from_unix(errno);
5109                         if (delete_on_fail) {
5110                                 SMB_VFS_UNLINK(conn,fname);
5111                         }
5112                         return status;
5113                 }
5114         }
5115
5116         /*
5117          * Deal with the UNIX specific gid set.
5118          */
5119
5120         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5121                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5122                         (unsigned int)set_owner, fname ));
5123                 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5124                         status = map_nt_error_from_unix(errno);
5125                         if (delete_on_fail) {
5126                                 SMB_VFS_UNLINK(conn,fname);
5127                         }
5128                         return status;
5129                 }
5130         }
5131
5132         /* Deal with any size changes. */
5133
5134         status = smb_set_file_size(conn,
5135                                 fsp,
5136                                 fname,
5137                                 psbuf,
5138                                 size);
5139         if (!NT_STATUS_IS_OK(status)) {
5140                 return status;
5141         }
5142
5143         /* Deal with any time changes. */
5144
5145         return smb_set_file_time(conn,
5146                                 fsp,
5147                                 fname,
5148                                 psbuf,
5149                                 ts);
5150 }
5151
5152 /****************************************************************************
5153  Deal with SMB_SET_FILE_UNIX_INFO2.
5154 ****************************************************************************/
5155
5156 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5157                                         const char *pdata,
5158                                         int total_data,
5159                                         files_struct *fsp,
5160                                         const char *fname,
5161                                         SMB_STRUCT_STAT *psbuf)
5162 {
5163         NTSTATUS status;
5164         uint32 smb_fflags;
5165         uint32 smb_fmask;
5166
5167         if (total_data < 116) {
5168                 return NT_STATUS_INVALID_PARAMETER;
5169         }
5170
5171         /* Start by setting all the fields that are common between UNIX_BASIC
5172          * and UNIX_INFO2.
5173          */
5174         status = smb_set_file_unix_basic(conn, pdata, total_data,
5175                                 fsp, fname, psbuf);
5176         if (!NT_STATUS_IS_OK(status)) {
5177                 return status;
5178         }
5179
5180         smb_fflags = IVAL(pdata, 108);
5181         smb_fmask = IVAL(pdata, 112);
5182
5183         /* NB: We should only attempt to alter the file flags if the client
5184          * sends a non-zero mask.
5185          */
5186         if (smb_fmask != 0) {
5187                 int stat_fflags = 0;
5188
5189                 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5190                             &stat_fflags)) {
5191                         /* Client asked to alter a flag we don't understand. */
5192                         return NT_STATUS_INVALID_PARAMETER;
5193                 }
5194
5195                 if (fsp && fsp->fh->fd != -1) {
5196                         /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
5197                         return NT_STATUS_NOT_SUPPORTED;
5198                 } else {
5199                         if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5200                                 return map_nt_error_from_unix(errno);
5201                         }
5202                 }
5203         }
5204
5205         /* XXX: need to add support for changing the create_time here. You
5206          * can do this for paths on Darwin with setattrlist(2). The right way
5207          * to hook this up is probably by extending the VFS utimes interface.
5208          */
5209
5210         return NT_STATUS_OK;
5211 }
5212
5213 /****************************************************************************
5214  Create a directory with POSIX semantics.
5215 ****************************************************************************/
5216
5217 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5218                                 char **ppdata,
5219                                 int total_data,
5220                                 const char *fname,
5221                                 SMB_STRUCT_STAT *psbuf,
5222                                 int *pdata_return_size)
5223 {
5224         NTSTATUS status = NT_STATUS_OK;
5225         uint32 raw_unixmode = 0;
5226         uint32 mod_unixmode = 0;
5227         mode_t unixmode = (mode_t)0;
5228         files_struct *fsp = NULL;
5229         uint16 info_level_return = 0;
5230         int info;
5231         char *pdata = *ppdata;
5232
5233         if (total_data < 18) {
5234                 return NT_STATUS_INVALID_PARAMETER;
5235         }
5236
5237         raw_unixmode = IVAL(pdata,8);
5238         /* Next 4 bytes are not yet defined. */
5239
5240         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5241         if (!NT_STATUS_IS_OK(status)) {
5242                 return status;
5243         }
5244
5245         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5246
5247         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5248                 fname, (unsigned int)unixmode ));
5249
5250         status = open_directory(conn,
5251                                 fname,
5252                                 psbuf,
5253                                 FILE_READ_ATTRIBUTES, /* Just a stat open */
5254                                 FILE_SHARE_NONE, /* Ignored for stat opens */
5255                                 FILE_CREATE,
5256                                 0,
5257                                 mod_unixmode,
5258                                 &info,
5259                                 &fsp);
5260
5261         if (NT_STATUS_IS_OK(status)) {
5262                 close_file(fsp, NORMAL_CLOSE);
5263         }
5264
5265         info_level_return = SVAL(pdata,16);
5266  
5267         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5268                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5269         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5270                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5271         } else {
5272                 *pdata_return_size = 12;
5273         }
5274
5275         /* Realloc the data size */
5276         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5277         if (*ppdata == NULL) {
5278                 *pdata_return_size = 0;
5279                 return NT_STATUS_NO_MEMORY;
5280         }
5281
5282         SSVAL(pdata,0,NO_OPLOCK_RETURN);
5283         SSVAL(pdata,2,0); /* No fnum. */
5284         SIVAL(pdata,4,info); /* Was directory created. */
5285
5286         switch (info_level_return) {
5287         case SMB_QUERY_FILE_UNIX_BASIC:
5288                 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5289                 SSVAL(pdata,10,0); /* Padding. */
5290                 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5291         case SMB_QUERY_FILE_UNIX_INFO2:
5292                 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5293                 SSVAL(pdata,10,0); /* Padding. */
5294                 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5295         default:
5296                 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5297                 SSVAL(pdata,10,0); /* Padding. */
5298         }
5299
5300         return status;
5301 }
5302
5303 /****************************************************************************
5304  Open/Create a file with POSIX semantics.
5305 ****************************************************************************/
5306
5307 static NTSTATUS smb_posix_open(connection_struct *conn,
5308                                 char **ppdata,
5309                                 int total_data,
5310                                 const char *fname,
5311                                 SMB_STRUCT_STAT *psbuf,
5312                                 int *pdata_return_size)
5313 {
5314         BOOL extended_oplock_granted = False;
5315         char *pdata = *ppdata;
5316         uint32 flags = 0;
5317         uint32 wire_open_mode = 0;
5318         uint32 raw_unixmode = 0;
5319         uint32 mod_unixmode = 0;
5320         uint32 create_disp = 0;
5321         uint32 access_mask = 0;
5322         uint32 create_options = 0;
5323         NTSTATUS status = NT_STATUS_OK;
5324         mode_t unixmode = (mode_t)0;
5325         files_struct *fsp = NULL;
5326         int oplock_request = 0;
5327         int info = 0;
5328         uint16 info_level_return = 0;
5329
5330         if (total_data < 18) {
5331                 return NT_STATUS_INVALID_PARAMETER;
5332         }
5333
5334         flags = IVAL(pdata,0);
5335         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5336         if (oplock_request) {
5337                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5338         }
5339
5340         wire_open_mode = IVAL(pdata,4);
5341
5342         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5343                 return smb_posix_mkdir(conn,
5344                                         ppdata,
5345                                         total_data,
5346                                         fname,
5347                                         psbuf,
5348                                         pdata_return_size);
5349         }
5350
5351         switch (wire_open_mode & SMB_ACCMODE) {
5352                 case SMB_O_RDONLY:
5353                         access_mask = FILE_READ_DATA;
5354                         break;
5355                 case SMB_O_WRONLY:
5356                         access_mask = FILE_WRITE_DATA;
5357                         break;
5358                 case SMB_O_RDWR:
5359                         access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5360                         break;
5361                 default:
5362                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5363                                 (unsigned int)wire_open_mode ));
5364                         return NT_STATUS_INVALID_PARAMETER;
5365         }
5366
5367         wire_open_mode &= ~SMB_ACCMODE;
5368
5369         if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5370                 create_disp = FILE_CREATE;
5371         } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5372                 create_disp = FILE_OVERWRITE_IF;
5373         } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5374                 create_disp = FILE_OPEN_IF;
5375         } else {
5376                 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5377                         (unsigned int)wire_open_mode ));
5378                 return NT_STATUS_INVALID_PARAMETER;
5379         }
5380
5381         raw_unixmode = IVAL(pdata,8);
5382         /* Next 4 bytes are not yet defined. */
5383
5384         status = unix_perms_from_wire(conn,
5385                                 psbuf,
5386                                 raw_unixmode,
5387                                 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5388                                 &unixmode);
5389
5390         if (!NT_STATUS_IS_OK(status)) {
5391                 return status;
5392         }
5393
5394         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5395
5396         if (wire_open_mode & SMB_O_SYNC) {
5397                 create_options |= FILE_WRITE_THROUGH;
5398         }
5399         if (wire_open_mode & SMB_O_APPEND) {
5400                 access_mask |= FILE_APPEND_DATA;
5401         }
5402         if (wire_open_mode & SMB_O_DIRECT) {
5403                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5404         }
5405
5406         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5407                 fname,
5408                 (unsigned int)wire_open_mode,
5409                 (unsigned int)unixmode ));
5410
5411         status = open_file_ntcreate(conn,
5412                                 fname,
5413                                 psbuf,
5414                                 access_mask,
5415                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5416                                 create_disp,
5417                                 0,              /* no create options yet. */
5418                                 mod_unixmode,
5419                                 oplock_request,
5420                                 &info,
5421                                 &fsp);
5422
5423         if (!NT_STATUS_IS_OK(status)) {
5424                 return status;
5425         }
5426
5427         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5428                 extended_oplock_granted = True;
5429         }
5430
5431         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5432                 extended_oplock_granted = True;
5433         }
5434
5435         info_level_return = SVAL(pdata,16);
5436  
5437         /* Allocate the correct return size. */
5438
5439         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5440                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5441         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5442                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5443         } else {
5444                 *pdata_return_size = 12;
5445         }
5446
5447         /* Realloc the data size */
5448         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5449         if (*ppdata == NULL) {
5450                 close_file(fsp,ERROR_CLOSE);
5451                 *pdata_return_size = 0;
5452                 return NT_STATUS_NO_MEMORY;
5453         }
5454
5455         if (extended_oplock_granted) {
5456                 if (flags & REQUEST_BATCH_OPLOCK) {
5457                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5458                 } else {
5459                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5460                 }
5461         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5462                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5463         } else {
5464                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5465         }
5466
5467         SSVAL(pdata,2,fsp->fnum);
5468         SIVAL(pdata,4,info); /* Was file created etc. */
5469
5470         switch (info_level_return) {
5471         case SMB_QUERY_FILE_UNIX_BASIC:
5472                 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5473                 SSVAL(pdata,10,0); /* padding. */
5474                 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5475         case SMB_QUERY_FILE_UNIX_INFO2:
5476                 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5477                 SSVAL(pdata,10,0); /* padding. */
5478                 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5479         default:
5480                 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5481                 SSVAL(pdata,10,0); /* padding. */
5482         }
5483         return NT_STATUS_OK;
5484 }
5485
5486 /****************************************************************************
5487  Delete a file with POSIX semantics.
5488 ****************************************************************************/
5489
5490 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5491                                 const char *pdata,
5492                                 int total_data,
5493                                 const char *fname,
5494                                 SMB_STRUCT_STAT *psbuf)
5495 {
5496         NTSTATUS status = NT_STATUS_OK;
5497         files_struct *fsp = NULL;
5498         uint16 flags = 0;
5499         int info = 0;
5500
5501         if (total_data < 2) {
5502                 return NT_STATUS_INVALID_PARAMETER;
5503         }
5504
5505         flags = SVAL(pdata,0);
5506
5507         if (!VALID_STAT(*psbuf)) {
5508                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5509         }
5510
5511         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5512                         !VALID_STAT_OF_DIR(*psbuf)) {
5513                 return NT_STATUS_NOT_A_DIRECTORY;
5514         }
5515
5516         DEBUG(10,("smb_posix_unlink: %s %s\n",
5517                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5518                 fname));
5519
5520         if (VALID_STAT_OF_DIR(*psbuf)) {
5521                 status = open_directory(conn,
5522                                         fname,
5523                                         psbuf,
5524                                         DELETE_ACCESS,
5525                                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5526                                         FILE_OPEN,
5527                                         FILE_DELETE_ON_CLOSE,
5528                                         FILE_FLAG_POSIX_SEMANTICS|0777,
5529                                         &info,                          
5530                                         &fsp);
5531         } else {
5532                 char del = 1;
5533
5534                 status = open_file_ntcreate(conn,
5535                                 fname,
5536                                 psbuf,
5537                                 DELETE_ACCESS,
5538                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5539                                 FILE_OPEN,
5540                                 0,
5541                                 FILE_FLAG_POSIX_SEMANTICS|0777,
5542                                 0, /* No oplock, but break existing ones. */
5543                                 &info,
5544                                 &fsp);
5545                 /* 
5546                  * For file opens we must set the delete on close
5547                  * after the open.
5548                  */
5549
5550                 if (!NT_STATUS_IS_OK(status)) {
5551                         return status;
5552                 }
5553
5554                 status = smb_set_file_disposition_info(conn,
5555                                                         &del,
5556                                                         1,
5557                                                         fsp,
5558                                                         fname,
5559                                                         psbuf);
5560         }
5561
5562         if (!NT_STATUS_IS_OK(status)) {
5563                 return status;
5564         }
5565         return close_file(fsp, NORMAL_CLOSE);
5566 }
5567
5568 /****************************************************************************
5569  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5570 ****************************************************************************/
5571
5572 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5573                                         unsigned int tran_call,
5574                                         char **pparams, int total_params, char **ppdata, int total_data,
5575                                         unsigned int max_data_bytes)
5576 {
5577         char *params = *pparams;
5578         char *pdata = *ppdata;
5579         uint16 info_level;
5580         SMB_STRUCT_STAT sbuf;
5581         pstring fname;
5582         files_struct *fsp = NULL;
5583         NTSTATUS status = NT_STATUS_OK;
5584         int data_return_size = 0;
5585
5586         if (!params) {
5587                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5588         }
5589
5590         ZERO_STRUCT(sbuf);
5591
5592         if (tran_call == TRANSACT2_SETFILEINFO) {
5593                 if (total_params < 4) {
5594                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5595                 }
5596
5597                 fsp = file_fsp(params,0);
5598                 info_level = SVAL(params,2);    
5599
5600                 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5601                         /*
5602                          * This is actually a SETFILEINFO on a directory
5603                          * handle (returned from an NT SMB). NT5.0 seems
5604                          * to do this call. JRA.
5605                          */
5606                         pstrcpy(fname, fsp->fsp_name);
5607                         if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5608                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5609                                 return UNIXERROR(ERRDOS,ERRbadpath);
5610                         }
5611                 } else if (fsp && fsp->print_file) {
5612                         /*
5613                          * Doing a DELETE_ON_CLOSE should cancel a print job.
5614                          */
5615                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5616                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5617
5618                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5619         
5620                                 SSVAL(params,0,0);
5621                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5622                                 return(-1);
5623                         } else
5624                                 return (UNIXERROR(ERRDOS,ERRbadpath));
5625             } else {
5626                         /*
5627                          * Original code - this is an open file.
5628                          */
5629                         CHECK_FSP(fsp,conn);
5630
5631                         pstrcpy(fname, fsp->fsp_name);
5632
5633                         if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5634                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5635                                 return(UNIXERROR(ERRDOS,ERRbadfid));
5636                         }
5637                 }
5638         } else {
5639                 /* set path info */
5640                 if (total_params < 7) {
5641                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5642                 }
5643
5644                 info_level = SVAL(params,0);    
5645                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5646                 if (!NT_STATUS_IS_OK(status)) {
5647                         return ERROR_NT(status);
5648                 }
5649
5650                 if (!resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname)) {
5651                         ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5652                 }
5653
5654                 status = unix_convert(conn, fname, False, NULL, &sbuf);
5655                 if (!NT_STATUS_IS_OK(status)) {
5656                         return ERROR_NT(status);
5657                 }
5658
5659                 status = check_name(conn, fname);
5660                 if (!NT_STATUS_IS_OK(status)) {
5661                         return ERROR_NT(status);
5662                 }
5663
5664                 /*
5665                  * For CIFS UNIX extensions the target name may not exist.
5666                  */
5667
5668                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
5669                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
5670                         return UNIXERROR(ERRDOS,ERRbadpath);
5671                 }    
5672         }
5673
5674         if (!CAN_WRITE(conn)) {
5675                 return ERROR_DOS(ERRSRV,ERRaccess);
5676         }
5677
5678         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5679                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5680         }
5681
5682         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5683                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5684
5685         /* Realloc the parameter size */
5686         *pparams = (char *)SMB_REALLOC(*pparams,2);
5687         if (*pparams == NULL) {
5688                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5689         }
5690         params = *pparams;
5691
5692         SSVAL(params,0,0);
5693
5694         if (fsp && !null_timespec(fsp->pending_modtime)) {
5695                 /* the pending modtime overrides the current modtime */
5696                 set_mtimespec(&sbuf, fsp->pending_modtime);
5697         }
5698
5699         switch (info_level) {
5700
5701                 case SMB_INFO_STANDARD:
5702                 {
5703                         status = smb_set_info_standard(conn,
5704                                         pdata,
5705                                         total_data,
5706                                         fsp,
5707                                         fname,
5708                                         &sbuf);
5709                         break;
5710                 }
5711
5712                 case SMB_INFO_SET_EA:
5713                 {
5714                         status = smb_info_set_ea(conn,
5715                                                 pdata,
5716                                                 total_data,
5717                                                 fsp,
5718                                                 fname);
5719                         break;
5720                 }
5721
5722                 case SMB_SET_FILE_BASIC_INFO:
5723                 case SMB_FILE_BASIC_INFORMATION:
5724                 {
5725                         status = smb_set_file_basic_info(conn,
5726                                                         pdata,
5727                                                         total_data,
5728                                                         fsp,
5729                                                         fname,
5730                                                         &sbuf);
5731                         break;
5732                 }
5733
5734                 case SMB_FILE_ALLOCATION_INFORMATION:
5735                 case SMB_SET_FILE_ALLOCATION_INFO:
5736                 {
5737                         status = smb_set_file_allocation_info(conn,
5738                                                                 pdata,
5739                                                                 total_data,
5740                                                                 fsp,
5741                                                                 fname,
5742                                                                 &sbuf);
5743                         break;
5744                 }
5745
5746                 case SMB_FILE_END_OF_FILE_INFORMATION:
5747                 case SMB_SET_FILE_END_OF_FILE_INFO:
5748                 {
5749                         status = smb_set_file_end_of_file_info(conn,
5750                                                                 pdata,
5751                                                                 total_data,
5752                                                                 fsp,
5753                                                                 fname,
5754                                                                 &sbuf);
5755                         break;
5756                 }
5757
5758                 case SMB_FILE_DISPOSITION_INFORMATION:
5759                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5760                 {
5761 #if 0
5762                         /* JRA - We used to just ignore this on a path ? 
5763                          * Shouldn't this be invalid level on a pathname
5764                          * based call ?
5765                          */
5766                         if (tran_call != TRANSACT2_SETFILEINFO) {
5767                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5768                         }
5769 #endif
5770                         status = smb_set_file_disposition_info(conn,
5771                                                 pdata,
5772                                                 total_data,
5773                                                 fsp,
5774                                                 fname,
5775                                                 &sbuf);
5776                         break;
5777                 }
5778
5779                 case SMB_FILE_POSITION_INFORMATION:
5780                 {
5781                         status = smb_file_position_information(conn,
5782                                                 pdata,
5783                                                 total_data,
5784                                                 fsp);
5785                         break;
5786                 }
5787
5788                 /* From tridge Samba4 : 
5789                  * MODE_INFORMATION in setfileinfo (I have no
5790                  * idea what "mode information" on a file is - it takes a value of 0,
5791                  * 2, 4 or 6. What could it be?).
5792                  */
5793
5794                 case SMB_FILE_MODE_INFORMATION:
5795                 {
5796                         status = smb_file_mode_information(conn,
5797                                                 pdata,
5798                                                 total_data);
5799                         break;
5800                 }
5801
5802                 /*
5803                  * CIFS UNIX extensions.
5804                  */
5805
5806                 case SMB_SET_FILE_UNIX_BASIC:
5807                 {
5808                         status = smb_set_file_unix_basic(conn,
5809                                                         pdata,
5810                                                         total_data,
5811                                                         fsp,
5812                                                         fname,
5813                                                         &sbuf);
5814                         break;
5815                 }
5816
5817                 case SMB_SET_FILE_UNIX_INFO2:
5818                 {
5819                         status = smb_set_file_unix_info2(conn,
5820                                                         pdata,
5821                                                         total_data,
5822                                                         fsp,
5823                                                         fname,
5824                                                         &sbuf);
5825                         break;
5826                 }
5827
5828                 case SMB_SET_FILE_UNIX_LINK:
5829                 {
5830                         if (tran_call != TRANSACT2_SETPATHINFO) {
5831                                 /* We must have a pathname for this. */
5832                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5833                         }
5834                         status = smb_set_file_unix_link(conn,
5835                                                 inbuf,
5836                                                 pdata,
5837                                                 total_data,
5838                                                 fname);
5839                         break;
5840                 }
5841
5842                 case SMB_SET_FILE_UNIX_HLINK:
5843                 {
5844                         if (tran_call != TRANSACT2_SETPATHINFO) {
5845                                 /* We must have a pathname for this. */
5846                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5847                         }
5848                         status = smb_set_file_unix_hlink(conn,
5849                                                 inbuf,
5850                                                 outbuf,
5851                                                 pdata,
5852                                                 total_data,
5853                                                 fname);
5854                         break;
5855                 }
5856
5857                 case SMB_FILE_RENAME_INFORMATION:
5858                 {
5859                         status = smb_file_rename_information(conn,
5860                                                         inbuf,
5861                                                         outbuf,
5862                                                         pdata,
5863                                                         total_data,
5864                                                         fsp,
5865                                                         fname);
5866                         break;
5867                 }
5868
5869 #if defined(HAVE_POSIX_ACLS)
5870                 case SMB_SET_POSIX_ACL:
5871                 {
5872                         status = smb_set_posix_acl(conn,
5873                                                 pdata,
5874                                                 total_data,
5875                                                 fsp,
5876                                                 fname,
5877                                                 &sbuf);
5878                         break;
5879                 }
5880 #endif
5881
5882                 case SMB_SET_POSIX_LOCK:
5883                 {
5884                         if (tran_call != TRANSACT2_SETFILEINFO) {
5885                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5886                         }
5887                         status = smb_set_posix_lock(conn,
5888                                                 inbuf,
5889                                                 length,
5890                                                 pdata,
5891                                                 total_data,
5892                                                 fsp);
5893                         break;
5894                 }
5895
5896                 case SMB_POSIX_PATH_OPEN:
5897                 {
5898                         if (tran_call != TRANSACT2_SETPATHINFO) {
5899                                 /* We must have a pathname for this. */
5900                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5901                         }
5902
5903                         status = smb_posix_open(conn,
5904                                                 ppdata,
5905                                                 total_data,
5906                                                 fname,
5907                                                 &sbuf,
5908                                                 &data_return_size);
5909                         break;
5910                 }
5911
5912                 case SMB_POSIX_PATH_UNLINK:
5913                 {
5914                         if (tran_call != TRANSACT2_SETPATHINFO) {
5915                                 /* We must have a pathname for this. */
5916                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5917                         }
5918
5919                         status = smb_posix_unlink(conn,
5920                                                 pdata,
5921                                                 total_data,
5922                                                 fname,
5923                                                 &sbuf);
5924                         break;
5925                 }
5926
5927                 default:
5928                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5929         }
5930
5931         
5932         if (!NT_STATUS_IS_OK(status)) {
5933                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
5934                         /* We have re-scheduled this call. */
5935                         return -1;
5936                 }
5937                 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
5938                         /* We have re-scheduled this call. */
5939                         return -1;
5940                 }
5941                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5942                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5943                 }
5944                 return ERROR_NT(status);
5945         }
5946
5947         SSVAL(params,0,0);
5948         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
5949   
5950         return -1;
5951 }
5952
5953 /****************************************************************************
5954  Reply to a TRANS2_MKDIR (make directory with extended attributes).
5955 ****************************************************************************/
5956
5957 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5958                                         char **pparams, int total_params, char **ppdata, int total_data,
5959                                         unsigned int max_data_bytes)
5960 {
5961         char *params = *pparams;
5962         char *pdata = *ppdata;
5963         pstring directory;
5964         SMB_STRUCT_STAT sbuf;
5965         NTSTATUS status = NT_STATUS_OK;
5966         struct ea_list *ea_list = NULL;
5967
5968         if (!CAN_WRITE(conn))
5969                 return ERROR_DOS(ERRSRV,ERRaccess);
5970
5971         if (total_params < 5) {
5972                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5973         }
5974
5975         srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
5976         if (!NT_STATUS_IS_OK(status)) {
5977                 return ERROR_NT(status);
5978         }
5979
5980         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
5981
5982         status = unix_convert(conn, directory, False, NULL, &sbuf);
5983         if (!NT_STATUS_IS_OK(status)) {
5984                 return ERROR_NT(status);
5985         }
5986
5987         status = check_name(conn, directory);
5988         if (!NT_STATUS_IS_OK(status)) {
5989                 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
5990                 return ERROR_NT(status);
5991         }
5992
5993         /* Any data in this call is an EA list. */
5994         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
5995                 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
5996         }
5997
5998         /*
5999          * OS/2 workplace shell seems to send SET_EA requests of "null"
6000          * length (4 bytes containing IVAL 4).
6001          * They seem to have no effect. Bug #3212. JRA.
6002          */
6003
6004         if (total_data != 4) {
6005                 if (total_data < 10) {
6006                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6007                 }
6008
6009                 if (IVAL(pdata,0) > total_data) {
6010                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6011                                 IVAL(pdata,0), (unsigned int)total_data));
6012                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6013                 }
6014
6015                 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6016                                        total_data - 4);
6017                 if (!ea_list) {
6018                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6019                 }
6020         } else if (IVAL(pdata,0) != 4) {
6021                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6022         }
6023
6024         status = create_directory(conn, directory);
6025
6026         if (!NT_STATUS_IS_OK(status)) {
6027                 return ERROR_NT(status);
6028         }
6029   
6030         /* Try and set any given EA. */
6031         if (ea_list) {
6032                 status = set_ea(conn, NULL, directory, ea_list);
6033                 if (!NT_STATUS_IS_OK(status)) {
6034                         return ERROR_NT(status);
6035                 }
6036         }
6037
6038         /* Realloc the parameter and data sizes */
6039         *pparams = (char *)SMB_REALLOC(*pparams,2);
6040         if(*pparams == NULL) {
6041                 return ERROR_NT(NT_STATUS_NO_MEMORY);
6042         }
6043         params = *pparams;
6044
6045         SSVAL(params,0,0);
6046
6047         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6048   
6049         return(-1);
6050 }
6051
6052 /****************************************************************************
6053  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6054  We don't actually do this - we just send a null response.
6055 ****************************************************************************/
6056
6057 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6058                                         char **pparams, int total_params, char **ppdata, int total_data,
6059                                         unsigned int max_data_bytes)
6060 {
6061         static uint16 fnf_handle = 257;
6062         char *params = *pparams;
6063         uint16 info_level;
6064
6065         if (total_params < 6) {
6066                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6067         }
6068
6069         info_level = SVAL(params,4);
6070         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6071
6072         switch (info_level) {
6073                 case 1:
6074                 case 2:
6075                         break;
6076                 default:
6077                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6078         }
6079
6080         /* Realloc the parameter and data sizes */
6081         *pparams = (char *)SMB_REALLOC(*pparams,6);
6082         if (*pparams == NULL) {
6083                 return ERROR_NT(NT_STATUS_NO_MEMORY);
6084         }
6085         params = *pparams;
6086
6087         SSVAL(params,0,fnf_handle);
6088         SSVAL(params,2,0); /* No changes */
6089         SSVAL(params,4,0); /* No EA errors */
6090
6091         fnf_handle++;
6092
6093         if(fnf_handle == 0)
6094                 fnf_handle = 257;
6095
6096         send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6097   
6098         return(-1);
6099 }
6100
6101 /****************************************************************************
6102  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
6103  changes). Currently this does nothing.
6104 ****************************************************************************/
6105
6106 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6107                                         char **pparams, int total_params, char **ppdata, int total_data,
6108                                         unsigned int max_data_bytes)
6109 {
6110         char *params = *pparams;
6111
6112         DEBUG(3,("call_trans2findnotifynext\n"));
6113
6114         /* Realloc the parameter and data sizes */
6115         *pparams = (char *)SMB_REALLOC(*pparams,4);
6116         if (*pparams == NULL) {
6117                 return ERROR_NT(NT_STATUS_NO_MEMORY);
6118         }
6119         params = *pparams;
6120
6121         SSVAL(params,0,0); /* No changes */
6122         SSVAL(params,2,0); /* No EA errors */
6123
6124         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6125   
6126         return(-1);
6127 }
6128
6129 /****************************************************************************
6130  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6131 ****************************************************************************/
6132
6133 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6134                                         char **pparams, int total_params, char **ppdata, int total_data,
6135                                         unsigned int max_data_bytes)
6136 {
6137         char *params = *pparams;
6138         pstring pathname;
6139         int reply_size = 0;
6140         int max_referral_level;
6141
6142         DEBUG(10,("call_trans2getdfsreferral\n"));
6143
6144         if (total_params < 3) {
6145                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6146         }
6147
6148         max_referral_level = SVAL(params,0);
6149
6150         if(!lp_host_msdfs())
6151                 return ERROR_DOS(ERRDOS,ERRbadfunc);
6152
6153         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6154         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
6155                 return UNIXERROR(ERRDOS,ERRbadfile);
6156     
6157         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6158         send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6159
6160         return(-1);
6161 }
6162
6163 #define LMCAT_SPL       0x53
6164 #define LMFUNC_GETJOBID 0x60
6165
6166 /****************************************************************************
6167  Reply to a TRANS2_IOCTL - used for OS/2 printing.
6168 ****************************************************************************/
6169
6170 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6171                                         char **pparams, int total_params, char **ppdata, int total_data,
6172                                         unsigned int max_data_bytes)
6173 {
6174         char *pdata = *ppdata;
6175         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6176
6177         /* check for an invalid fid before proceeding */
6178         
6179         if (!fsp)                                
6180                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
6181
6182         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6183                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6184                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6185                 if (*ppdata == NULL) {
6186                         return ERROR_NT(NT_STATUS_NO_MEMORY);
6187                 }
6188                 pdata = *ppdata;
6189
6190                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6191                         CAN ACCEPT THIS IN UNICODE. JRA. */
6192
6193                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
6194                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6195                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6196                 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6197                 return(-1);
6198         } else {
6199                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6200                 return ERROR_DOS(ERRSRV,ERRerror);
6201         }
6202 }
6203
6204 /****************************************************************************
6205  Reply to a SMBfindclose (stop trans2 directory search).
6206 ****************************************************************************/
6207
6208 int reply_findclose(connection_struct *conn,
6209                     char *inbuf,char *outbuf,int length,int bufsize)
6210 {
6211         int outsize = 0;
6212         int dptr_num=SVALS(inbuf,smb_vwv0);
6213         START_PROFILE(SMBfindclose);
6214
6215         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6216
6217         dptr_close(&dptr_num);
6218
6219         outsize = set_message(outbuf,0,0,False);
6220
6221         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6222
6223         END_PROFILE(SMBfindclose);
6224         return(outsize);
6225 }
6226
6227 /****************************************************************************
6228  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6229 ****************************************************************************/
6230
6231 int reply_findnclose(connection_struct *conn, 
6232                      char *inbuf,char *outbuf,int length,int bufsize)
6233 {
6234         int outsize = 0;
6235         int dptr_num= -1;
6236         START_PROFILE(SMBfindnclose);
6237         
6238         dptr_num = SVAL(inbuf,smb_vwv0);
6239
6240         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6241
6242         /* We never give out valid handles for a 
6243            findnotifyfirst - so any dptr_num is ok here. 
6244            Just ignore it. */
6245
6246         outsize = set_message(outbuf,0,0,False);
6247
6248         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6249
6250         END_PROFILE(SMBfindnclose);
6251         return(outsize);
6252 }
6253
6254 int handle_trans2(connection_struct *conn,
6255                   struct trans_state *state,
6256                   char *inbuf, char *outbuf, int size, int bufsize)
6257 {
6258         int outsize;
6259
6260         if (Protocol >= PROTOCOL_NT1) {
6261                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6262         }
6263
6264         /* Now we must call the relevant TRANS2 function */
6265         switch(state->call)  {
6266         case TRANSACT2_OPEN:
6267         {
6268                 START_PROFILE(Trans2_open);
6269                 outsize = call_trans2open(
6270                         conn, inbuf, outbuf, bufsize, 
6271                         &state->param, state->total_param,
6272                         &state->data, state->total_data,
6273                         state->max_data_return);
6274                 END_PROFILE(Trans2_open);
6275                 break;
6276         }
6277
6278         case TRANSACT2_FINDFIRST:
6279         {
6280                 START_PROFILE(Trans2_findfirst);
6281                 outsize = call_trans2findfirst(
6282                         conn, inbuf, outbuf, bufsize,
6283                         &state->param, state->total_param,
6284                         &state->data, state->total_data,
6285                         state->max_data_return);
6286                 END_PROFILE(Trans2_findfirst);
6287                 break;
6288         }
6289
6290         case TRANSACT2_FINDNEXT:
6291         {
6292                 START_PROFILE(Trans2_findnext);
6293                 outsize = call_trans2findnext(
6294                         conn, inbuf, outbuf, size, bufsize, 
6295                         &state->param, state->total_param,
6296                         &state->data, state->total_data,
6297                         state->max_data_return);
6298                 END_PROFILE(Trans2_findnext);
6299                 break;
6300         }
6301
6302         case TRANSACT2_QFSINFO:
6303         {
6304                 START_PROFILE(Trans2_qfsinfo);
6305                 outsize = call_trans2qfsinfo(
6306                         conn, inbuf, outbuf, size, bufsize,
6307                         &state->param, state->total_param,
6308                         &state->data, state->total_data,
6309                         state->max_data_return);
6310                 END_PROFILE(Trans2_qfsinfo);
6311             break;
6312         }
6313
6314         case TRANSACT2_SETFSINFO:
6315         {
6316                 START_PROFILE(Trans2_setfsinfo);
6317                 outsize = call_trans2setfsinfo(
6318                         conn, inbuf, outbuf, size, bufsize, 
6319                         &state->param, state->total_param,
6320                         &state->data, state->total_data,
6321                         state->max_data_return);
6322                 END_PROFILE(Trans2_setfsinfo);
6323                 break;
6324         }
6325
6326         case TRANSACT2_QPATHINFO:
6327         case TRANSACT2_QFILEINFO:
6328         {
6329                 START_PROFILE(Trans2_qpathinfo);
6330                 outsize = call_trans2qfilepathinfo(
6331                         conn, inbuf, outbuf, size, bufsize, state->call,
6332                         &state->param, state->total_param,
6333                         &state->data, state->total_data,
6334                         state->max_data_return);
6335                 END_PROFILE(Trans2_qpathinfo);
6336                 break;
6337         }
6338
6339         case TRANSACT2_SETPATHINFO:
6340         case TRANSACT2_SETFILEINFO:
6341         {
6342                 START_PROFILE(Trans2_setpathinfo);
6343                 outsize = call_trans2setfilepathinfo(
6344                         conn, inbuf, outbuf, size, bufsize, state->call,
6345                         &state->param, state->total_param,
6346                         &state->data, state->total_data,
6347                         state->max_data_return);
6348                 END_PROFILE(Trans2_setpathinfo);
6349                 break;
6350         }
6351
6352         case TRANSACT2_FINDNOTIFYFIRST:
6353         {
6354                 START_PROFILE(Trans2_findnotifyfirst);
6355                 outsize = call_trans2findnotifyfirst(
6356                         conn, inbuf, outbuf, size, bufsize, 
6357                         &state->param, state->total_param,
6358                         &state->data, state->total_data,
6359                         state->max_data_return);
6360                 END_PROFILE(Trans2_findnotifyfirst);
6361                 break;
6362         }
6363
6364         case TRANSACT2_FINDNOTIFYNEXT:
6365         {
6366                 START_PROFILE(Trans2_findnotifynext);
6367                 outsize = call_trans2findnotifynext(
6368                         conn, inbuf, outbuf, size, bufsize, 
6369                         &state->param, state->total_param,
6370                         &state->data, state->total_data,
6371                         state->max_data_return);
6372                 END_PROFILE(Trans2_findnotifynext);
6373                 break;
6374         }
6375
6376         case TRANSACT2_MKDIR:
6377         {
6378                 START_PROFILE(Trans2_mkdir);
6379                 outsize = call_trans2mkdir(
6380                         conn, inbuf, outbuf, size, bufsize,
6381                         &state->param, state->total_param,
6382                         &state->data, state->total_data,
6383                         state->max_data_return);
6384                 END_PROFILE(Trans2_mkdir);
6385                 break;
6386         }
6387
6388         case TRANSACT2_GET_DFS_REFERRAL:
6389         {
6390                 START_PROFILE(Trans2_get_dfs_referral);
6391                 outsize = call_trans2getdfsreferral(
6392                         conn, inbuf, outbuf, size, bufsize,
6393                         &state->param, state->total_param,
6394                         &state->data, state->total_data,
6395                         state->max_data_return);
6396                 END_PROFILE(Trans2_get_dfs_referral);
6397                 break;
6398         }
6399
6400         case TRANSACT2_IOCTL:
6401         {
6402                 START_PROFILE(Trans2_ioctl);
6403                 outsize = call_trans2ioctl(
6404                         conn, inbuf, outbuf, size, bufsize,
6405                         &state->param, state->total_param,
6406                         &state->data, state->total_data,
6407                         state->max_data_return);
6408                 END_PROFILE(Trans2_ioctl);
6409                 break;
6410         }
6411
6412         default:
6413                 /* Error in request */
6414                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6415                 outsize = ERROR_DOS(ERRSRV,ERRerror);
6416         }
6417
6418         return outsize;
6419 }
6420
6421 /****************************************************************************
6422  Reply to a SMBtrans2.
6423  ****************************************************************************/
6424
6425 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6426                  int size, int bufsize)
6427 {
6428         int outsize = 0;
6429         unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6430         unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6431         unsigned int psoff = SVAL(inbuf, smb_psoff);
6432         unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6433         unsigned int tran_call = SVAL(inbuf, smb_setup0);
6434         struct trans_state *state;
6435         NTSTATUS result;
6436
6437         START_PROFILE(SMBtrans2);
6438
6439         result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6440         if (!NT_STATUS_IS_OK(result)) {
6441                 DEBUG(2, ("Got invalid trans2 request: %s\n",
6442                           nt_errstr(result)));
6443                 END_PROFILE(SMBtrans2);
6444                 return ERROR_NT(result);
6445         }
6446
6447         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6448             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6449                 END_PROFILE(SMBtrans2);
6450                 return ERROR_DOS(ERRSRV,ERRaccess);
6451         }
6452
6453         if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6454                 DEBUG(0, ("talloc failed\n"));
6455                 END_PROFILE(SMBtrans2);
6456                 return ERROR_NT(NT_STATUS_NO_MEMORY);
6457         }
6458
6459         state->cmd = SMBtrans2;
6460
6461         state->mid = SVAL(inbuf, smb_mid);
6462         state->vuid = SVAL(inbuf, smb_uid);
6463         state->setup_count = SVAL(inbuf, smb_suwcnt);
6464         state->setup = NULL;
6465         state->total_param = SVAL(inbuf, smb_tpscnt);
6466         state->param = NULL;
6467         state->total_data =  SVAL(inbuf, smb_tdscnt);
6468         state->data = NULL;
6469         state->max_param_return = SVAL(inbuf, smb_mprcnt);
6470         state->max_data_return  = SVAL(inbuf, smb_mdrcnt);
6471         state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6472         state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6473         state->one_way = BITSETW(inbuf+smb_vwv5,1);
6474
6475         state->call = tran_call;
6476
6477         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6478            is so as a sanity check */
6479         if (state->setup_count != 1) {
6480                 /*
6481                  * Need to have rc=0 for ioctl to get job id for OS/2.
6482                  *  Network printing will fail if function is not successful.
6483                  *  Similar function in reply.c will be used if protocol
6484                  *  is LANMAN1.0 instead of LM1.2X002.
6485                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
6486                  *  outbuf doesn't have to be set(only job id is used).
6487                  */
6488                 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6489                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6490                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6491                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6492                 } else {
6493                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6494                         DEBUG(2,("Transaction is %d\n",tran_call));
6495                         TALLOC_FREE(state);
6496                         END_PROFILE(SMBtrans2);
6497                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6498                 }
6499         }
6500
6501         if ((dscnt > state->total_data) || (pscnt > state->total_param))
6502                 goto bad_param;
6503
6504         if (state->total_data) {
6505                 /* Can't use talloc here, the core routines do realloc on the
6506                  * params and data. */
6507                 state->data = (char *)SMB_MALLOC(state->total_data);
6508                 if (state->data == NULL) {
6509                         DEBUG(0,("reply_trans2: data malloc fail for %u "
6510                                  "bytes !\n", (unsigned int)state->total_data));
6511                         TALLOC_FREE(state);
6512                         END_PROFILE(SMBtrans2);
6513                         return(ERROR_DOS(ERRDOS,ERRnomem));
6514                 }
6515                 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6516                         goto bad_param;
6517                 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6518                     (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6519                         goto bad_param;
6520
6521                 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6522         }
6523
6524         if (state->total_param) {
6525                 /* Can't use talloc here, the core routines do realloc on the
6526                  * params and data. */
6527                 state->param = (char *)SMB_MALLOC(state->total_param);
6528                 if (state->param == NULL) {
6529                         DEBUG(0,("reply_trans: param malloc fail for %u "
6530                                  "bytes !\n", (unsigned int)state->total_param));
6531                         SAFE_FREE(state->data);
6532                         TALLOC_FREE(state);
6533                         END_PROFILE(SMBtrans2);
6534                         return(ERROR_DOS(ERRDOS,ERRnomem));
6535                 } 
6536                 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6537                         goto bad_param;
6538                 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6539                     (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6540                         goto bad_param;
6541
6542                 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6543         }
6544
6545         state->received_data  = dscnt;
6546         state->received_param = pscnt;
6547
6548         if ((state->received_param == state->total_param) &&
6549             (state->received_data == state->total_data)) {
6550
6551                 outsize = handle_trans2(conn, state, inbuf, outbuf,
6552                                         size, bufsize);
6553                 SAFE_FREE(state->data);
6554                 SAFE_FREE(state->param);
6555                 TALLOC_FREE(state);
6556                 END_PROFILE(SMBtrans2);
6557                 return outsize;
6558         }
6559
6560         DLIST_ADD(conn->pending_trans, state);
6561
6562         /* We need to send an interim response then receive the rest
6563            of the parameter/data bytes */
6564         outsize = set_message(outbuf,0,0,False);
6565         show_msg(outbuf);
6566         END_PROFILE(SMBtrans2);
6567         return outsize;
6568
6569   bad_param:
6570
6571         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6572         SAFE_FREE(state->data);
6573         SAFE_FREE(state->param);
6574         TALLOC_FREE(state);
6575         END_PROFILE(SMBtrans2);
6576         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6577 }
6578
6579
6580 /****************************************************************************
6581  Reply to a SMBtranss2
6582  ****************************************************************************/
6583
6584 int reply_transs2(connection_struct *conn,
6585                   char *inbuf,char *outbuf,int size,int bufsize)
6586 {
6587         int outsize = 0;
6588         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6589         struct trans_state *state;
6590
6591         START_PROFILE(SMBtranss2);
6592
6593         show_msg(inbuf);
6594
6595         for (state = conn->pending_trans; state != NULL;
6596              state = state->next) {
6597                 if (state->mid == SVAL(inbuf,smb_mid)) {
6598                         break;
6599                 }
6600         }
6601
6602         if ((state == NULL) || (state->cmd != SMBtrans2)) {
6603                 END_PROFILE(SMBtranss2);
6604                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6605         }
6606
6607         /* Revise state->total_param and state->total_data in case they have
6608            changed downwards */
6609
6610         if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6611                 state->total_param = SVAL(inbuf, smb_tpscnt);
6612         if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6613                 state->total_data = SVAL(inbuf, smb_tdscnt);
6614
6615         pcnt = SVAL(inbuf, smb_spscnt);
6616         poff = SVAL(inbuf, smb_spsoff);
6617         pdisp = SVAL(inbuf, smb_spsdisp);
6618
6619         dcnt = SVAL(inbuf, smb_sdscnt);
6620         doff = SVAL(inbuf, smb_sdsoff);
6621         ddisp = SVAL(inbuf, smb_sdsdisp);
6622
6623         state->received_param += pcnt;
6624         state->received_data += dcnt;
6625                 
6626         if ((state->received_data > state->total_data) ||
6627             (state->received_param > state->total_param))
6628                 goto bad_param;
6629
6630         if (pcnt) {
6631                 if (pdisp+pcnt > state->total_param)
6632                         goto bad_param;
6633                 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6634                         goto bad_param;
6635                 if (pdisp > state->total_param)
6636                         goto bad_param;
6637                 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6638                     (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6639                         goto bad_param;
6640                 if (state->param + pdisp < state->param)
6641                         goto bad_param;
6642
6643                 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6644                        pcnt);
6645         }
6646
6647         if (dcnt) {
6648                 if (ddisp+dcnt > state->total_data)
6649                         goto bad_param;
6650                 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6651                         goto bad_param;
6652                 if (ddisp > state->total_data)
6653                         goto bad_param;
6654                 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6655                     (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6656                         goto bad_param;
6657                 if (state->data + ddisp < state->data)
6658                         goto bad_param;
6659
6660                 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6661                        dcnt);      
6662         }
6663
6664         if ((state->received_param < state->total_param) ||
6665             (state->received_data < state->total_data)) {
6666                 END_PROFILE(SMBtranss2);
6667                 return -1;
6668         }
6669
6670         /* construct_reply_common has done us the favor to pre-fill the
6671          * command field with SMBtranss2 which is wrong :-)
6672          */
6673         SCVAL(outbuf,smb_com,SMBtrans2);
6674
6675         outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6676
6677         DLIST_REMOVE(conn->pending_trans, state);
6678         SAFE_FREE(state->data);
6679         SAFE_FREE(state->param);
6680         TALLOC_FREE(state);
6681
6682         if (outsize == 0) {
6683                 END_PROFILE(SMBtranss2);
6684                 return(ERROR_DOS(ERRSRV,ERRnosupport));
6685         }
6686         
6687         END_PROFILE(SMBtranss2);
6688         return(outsize);
6689
6690   bad_param:
6691
6692         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6693         DLIST_REMOVE(conn->pending_trans, state);
6694         SAFE_FREE(state->data);
6695         SAFE_FREE(state->param);
6696         TALLOC_FREE(state);
6697         END_PROFILE(SMBtranss2);
6698         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6699 }