4f5039e86c332e0f97e00929342cbd4ae951d705
[samba.git] / source3 / smbd / trans2.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB transaction2 handling
4    Copyright (C) Jeremy Allison                 1994-2003
5    Copyright (C) Stefan (metze) Metzmacher      2003
6    Copyright (C) Volker Lendecke                2005
7    Copyright (C) Steve French                   2005
8
9    Extensively modified by Andrew Tridgell, 1995
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 #include "includes.h"
27
28 extern int max_send;
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
33
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
36
37 /********************************************************************
38  Roundup a value to the nearest allocation roundup size boundary.
39  Only do this for Windows clients.
40 ********************************************************************/
41
42 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
43 {
44         SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
45
46         /* Only roundup for Windows clients. */
47         enum remote_arch_types ra_type = get_remote_arch();
48         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
49                 val = SMB_ROUNDUP(val,rval);
50         }
51         return val;
52 }
53
54 /********************************************************************
55  Given a stat buffer return the allocated size on disk, taking into
56  account sparse files.
57 ********************************************************************/
58
59 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
60 {
61         SMB_BIG_UINT ret;
62
63         if(S_ISDIR(sbuf->st_mode)) {
64                 return 0;
65         }
66
67 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
68         ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
69 #else
70         ret = (SMB_BIG_UINT)get_file_size(*sbuf);
71 #endif
72
73         if (fsp && fsp->initial_allocation_size)
74                 ret = MAX(ret,fsp->initial_allocation_size);
75
76         return smb_roundup(conn, ret);
77 }
78
79 /****************************************************************************
80  Utility functions for dealing with extended attributes.
81 ****************************************************************************/
82
83 static const char *prohibited_ea_names[] = {
84         SAMBA_POSIX_INHERITANCE_EA_NAME,
85         SAMBA_XATTR_DOS_ATTRIB,
86         NULL
87 };
88
89 /****************************************************************************
90  Refuse to allow clients to overwrite our private xattrs.
91 ****************************************************************************/
92
93 static BOOL samba_private_attr_name(const char *unix_ea_name)
94 {
95         int i;
96
97         for (i = 0; prohibited_ea_names[i]; i++) {
98                 if (strequal( prohibited_ea_names[i], unix_ea_name))
99                         return True;
100         }
101         return False;
102 }
103
104 /****************************************************************************
105  Get one EA value. Fill in a struct ea_struct.
106 ****************************************************************************/
107
108 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
109                                 const char *fname, char *ea_name, struct ea_struct *pea)
110 {
111         /* Get the value of this xattr. Max size is 64k. */
112         size_t attr_size = 256;
113         char *val = NULL;
114         ssize_t sizeret;
115
116  again:
117
118         val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
119         if (!val) {
120                 return False;
121         }
122
123         if (fsp && fsp->fh->fd != -1) {
124                 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
125         } else {
126                 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
127         }
128
129         if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
130                 attr_size = 65536;
131                 goto again;
132         }
133
134         if (sizeret == -1) {
135                 return False;
136         }
137
138         DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
139         dump_data(10, val, sizeret);
140
141         pea->flags = 0;
142         if (strnequal(ea_name, "user.", 5)) {
143                 pea->name = &ea_name[5];
144         } else {
145                 pea->name = ea_name;
146         }
147         pea->value.data = (unsigned char *)val;
148         pea->value.length = (size_t)sizeret;
149         return True;
150 }
151
152 /****************************************************************************
153  Return a linked list of the total EA's. Plus the total size
154 ****************************************************************************/
155
156 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
157                                         const char *fname, size_t *pea_total_len)
158 {
159         /* Get a list of all xattrs. Max namesize is 64k. */
160         size_t ea_namelist_size = 1024;
161         char *ea_namelist;
162         char *p;
163         ssize_t sizeret;
164         int i;
165         struct ea_list *ea_list_head = NULL;
166
167         *pea_total_len = 0;
168
169         if (!lp_ea_support(SNUM(conn))) {
170                 return NULL;
171         }
172
173         for (i = 0, ea_namelist = TALLOC(mem_ctx, ea_namelist_size); i < 6;
174                         ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
175                 if (fsp && fsp->fh->fd != -1) {
176                         sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
177                 } else {
178                         sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
179                 }
180
181                 if (sizeret == -1 && errno == ERANGE) {
182                         ea_namelist_size *= 2;
183                 } else {
184                         break;
185                 }
186         }
187
188         if (sizeret == -1)
189                 return NULL;
190
191         DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
192
193         if (sizeret) {
194                 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
195                         struct ea_list *listp, *tmp;
196
197                         if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
198                                 continue;
199                 
200                         listp = TALLOC_P(mem_ctx, struct ea_list);
201                         if (!listp)
202                                 return NULL;
203
204                         if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
205                                 return NULL;
206                         }
207
208                         {
209                                 fstring dos_ea_name;
210                                 push_ascii_fstring(dos_ea_name, listp->ea.name);
211                                 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
212                                 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
213                                         (unsigned int)*pea_total_len, dos_ea_name,
214                                         (unsigned int)listp->ea.value.length ));
215                         }
216                         DLIST_ADD_END(ea_list_head, listp, tmp);
217                 }
218                 /* Add on 4 for total length. */
219                 if (*pea_total_len) {
220                         *pea_total_len += 4;
221                 }
222         }
223
224         DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
225         return ea_list_head;
226 }
227
228 /****************************************************************************
229  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
230  that was filled.
231 ****************************************************************************/
232
233 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
234         connection_struct *conn, struct ea_list *ea_list)
235 {
236         unsigned int ret_data_size = 4;
237         char *p = pdata;
238
239         SMB_ASSERT(total_data_size >= 4);
240
241         if (!lp_ea_support(SNUM(conn))) {
242                 SIVAL(pdata,4,0);
243                 return 4;
244         }
245
246         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
247                 size_t dos_namelen;
248                 fstring dos_ea_name;
249                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
250                 dos_namelen = strlen(dos_ea_name);
251                 if (dos_namelen > 255 || dos_namelen == 0) {
252                         break;
253                 }
254                 if (ea_list->ea.value.length > 65535) {
255                         break;
256                 }
257                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
258                         break;
259                 }
260
261                 /* We know we have room. */
262                 SCVAL(p,0,ea_list->ea.flags);
263                 SCVAL(p,1,dos_namelen);
264                 SSVAL(p,2,ea_list->ea.value.length);
265                 fstrcpy(p+4, dos_ea_name);
266                 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
267
268                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
269                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
270         }
271
272         ret_data_size = PTR_DIFF(p, pdata);
273         DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
274         SIVAL(pdata,0,ret_data_size);
275         return ret_data_size;
276 }
277
278 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
279 {
280         size_t total_ea_len = 0;
281         TALLOC_CTX *mem_ctx = NULL;
282
283         if (!lp_ea_support(SNUM(conn))) {
284                 return 0;
285         }
286         mem_ctx = talloc_init("estimate_ea_size");
287         (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
288         talloc_destroy(mem_ctx);
289         return total_ea_len;
290 }
291
292 /****************************************************************************
293  Ensure the EA name is case insensitive by matching any existing EA name.
294 ****************************************************************************/
295
296 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
297 {
298         size_t total_ea_len;
299         TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
300         struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
301
302         for (; ea_list; ea_list = ea_list->next) {
303                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
304                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
305                                 &unix_ea_name[5], ea_list->ea.name));
306                         safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
307                         break;
308                 }
309         }
310         talloc_destroy(mem_ctx);
311 }
312
313 /****************************************************************************
314  Set or delete an extended attribute.
315 ****************************************************************************/
316
317 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
318 {
319         if (!lp_ea_support(SNUM(conn))) {
320                 return NT_STATUS_EAS_NOT_SUPPORTED;
321         }
322
323         for (;ea_list; ea_list = ea_list->next) {
324                 int ret;
325                 fstring unix_ea_name;
326
327                 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
328                 fstrcat(unix_ea_name, ea_list->ea.name);
329
330                 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
331
332                 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
333
334                 if (samba_private_attr_name(unix_ea_name)) {
335                         DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
336                         return NT_STATUS_ACCESS_DENIED;
337                 }
338
339                 if (ea_list->ea.value.length == 0) {
340                         /* Remove the attribute. */
341                         if (fsp && (fsp->fh->fd != -1)) {
342                                 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
343                                         unix_ea_name, fsp->fsp_name));
344                                 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
345                         } else {
346                                 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
347                                         unix_ea_name, fname));
348                                 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
349                         }
350 #ifdef ENOATTR
351                         /* Removing a non existent attribute always succeeds. */
352                         if (ret == -1 && errno == ENOATTR) {
353                                 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
354                                                 unix_ea_name));
355                                 ret = 0;
356                         }
357 #endif
358                 } else {
359                         if (fsp && (fsp->fh->fd != -1)) {
360                                 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
361                                         unix_ea_name, fsp->fsp_name));
362                                 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
363                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
364                         } else {
365                                 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
366                                         unix_ea_name, fname));
367                                 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
368                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
369                         }
370                 }
371
372                 if (ret == -1) {
373 #ifdef ENOTSUP
374                         if (errno == ENOTSUP) {
375                                 return NT_STATUS_EAS_NOT_SUPPORTED;
376                         }
377 #endif
378                         return map_nt_error_from_unix(errno);
379                 }
380
381         }
382         return NT_STATUS_OK;
383 }
384 /****************************************************************************
385  Read a list of EA names from an incoming data buffer. Create an ea_list with them.
386 ****************************************************************************/
387
388 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
389 {
390         struct ea_list *ea_list_head = NULL;
391         size_t offset = 0;
392
393         while (offset + 2 < data_size) {
394                 struct ea_list *tmp;
395                 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
396                 unsigned int namelen = CVAL(pdata,offset);
397
398                 offset++; /* Go past the namelen byte. */
399
400                 /* integer wrap paranioa. */
401                 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
402                                 (offset > data_size) || (namelen > data_size) ||
403                                 (offset + namelen >= data_size)) {
404                         break;
405                 }
406                 /* Ensure the name is null terminated. */
407                 if (pdata[offset + namelen] != '\0') {
408                         return NULL;
409                 }
410                 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
411                 if (!eal->ea.name) {
412                         return NULL;
413                 }
414
415                 offset += (namelen + 1); /* Go past the name + terminating zero. */
416                 DLIST_ADD_END(ea_list_head, eal, tmp);
417                 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
418         }
419
420         return ea_list_head;
421 }
422
423 /****************************************************************************
424  Read one EA list entry from the buffer.
425 ****************************************************************************/
426
427 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
428 {
429         struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
430         uint16 val_len;
431         unsigned int namelen;
432
433         if (!eal) {
434                 return NULL;
435         }
436
437         if (data_size < 6) {
438                 return NULL;
439         }
440
441         eal->ea.flags = CVAL(pdata,0);
442         namelen = CVAL(pdata,1);
443         val_len = SVAL(pdata,2);
444
445         if (4 + namelen + 1 + val_len > data_size) {
446                 return NULL;
447         }
448
449         /* Ensure the name is null terminated. */
450         if (pdata[namelen + 4] != '\0') {
451                 return NULL;
452         }
453         pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
454         if (!eal->ea.name) {
455                 return NULL;
456         }
457
458         eal->ea.value = data_blob(NULL, (size_t)val_len + 1);
459         if (!eal->ea.value.data) {
460                 return NULL;
461         }
462
463         memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
464
465         /* Ensure we're null terminated just in case we print the value. */
466         eal->ea.value.data[val_len] = '\0';
467         /* But don't count the null. */
468         eal->ea.value.length--;
469
470         if (pbytes_used) {
471                 *pbytes_used = 4 + namelen + 1 + val_len;
472         }
473
474         DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
475         dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
476
477         return eal;
478 }
479
480 /****************************************************************************
481  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
482 ****************************************************************************/
483
484 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
485 {
486         struct ea_list *ea_list_head = NULL;
487         size_t offset = 0;
488         size_t bytes_used = 0;
489
490         while (offset < data_size) {
491                 struct ea_list *tmp;
492                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
493
494                 if (!eal) {
495                         return NULL;
496                 }
497
498                 DLIST_ADD_END(ea_list_head, eal, tmp);
499                 offset += bytes_used;
500         }
501
502         return ea_list_head;
503 }
504
505 /****************************************************************************
506  Count the total EA size needed.
507 ****************************************************************************/
508
509 static size_t ea_list_size(struct ea_list *ealist)
510 {
511         fstring dos_ea_name;
512         struct ea_list *listp;
513         size_t ret = 0;
514
515         for (listp = ealist; listp; listp = listp->next) {
516                 push_ascii_fstring(dos_ea_name, listp->ea.name);
517                 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
518         }
519         /* Add on 4 for total length. */
520         if (ret) {
521                 ret += 4;
522         }
523
524         return ret;
525 }
526
527 /****************************************************************************
528  Return a union of EA's from a file list and a list of names.
529  The TALLOC context for the two lists *MUST* be identical as we steal
530  memory from one list to add to another. JRA.
531 ****************************************************************************/
532
533 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
534 {
535         struct ea_list *nlistp, *flistp;
536
537         for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
538                 for (flistp = file_list; flistp; flistp = flistp->next) {
539                         if (strequal(nlistp->ea.name, flistp->ea.name)) {
540                                 break;
541                         }
542                 }
543
544                 if (flistp) {
545                         /* Copy the data from this entry. */
546                         nlistp->ea.flags = flistp->ea.flags;
547                         nlistp->ea.value = flistp->ea.value;
548                 } else {
549                         /* Null entry. */
550                         nlistp->ea.flags = 0;
551                         ZERO_STRUCT(nlistp->ea.value);
552                 }
553         }
554
555         *total_ea_len = ea_list_size(name_list);
556         return name_list;
557 }
558
559 /****************************************************************************
560   Send the required number of replies back.
561   We assume all fields other than the data fields are
562   set correctly for the type of call.
563   HACK ! Always assumes smb_setup field is zero.
564 ****************************************************************************/
565
566 static int send_trans2_replies(char *outbuf,
567                         int bufsize,
568                         char *params, 
569                         int paramsize,
570                         char *pdata,
571                         int datasize)
572 {
573         /* As we are using a protocol > LANMAN1 then the max_send
574          variable must have been set in the sessetupX call.
575          This takes precedence over the max_xmit field in the
576          global struct. These different max_xmit variables should
577          be merged as this is now too confusing */
578
579         int data_to_send = datasize;
580         int params_to_send = paramsize;
581         int useable_space;
582         char *pp = params;
583         char *pd = pdata;
584         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
585         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
586         int data_alignment_offset = 0;
587
588         /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
589         
590         set_message(outbuf,10,0,True);
591
592         /* If there genuinely are no parameters or data to send just send the empty packet */
593
594         if(params_to_send == 0 && data_to_send == 0) {
595                 show_msg(outbuf);
596                 if (!send_smb(smbd_server_fd(),outbuf))
597                         exit_server("send_trans2_replies: send_smb failed.");
598                 return 0;
599         }
600
601         /* When sending params and data ensure that both are nicely aligned */
602         /* Only do this alignment when there is also data to send - else
603                 can cause NT redirector problems. */
604
605         if (((params_to_send % 4) != 0) && (data_to_send != 0))
606                 data_alignment_offset = 4 - (params_to_send % 4);
607
608         /* Space is bufsize minus Netbios over TCP header minus SMB header */
609         /* The alignment_offset is to align the param bytes on an even byte
610                 boundary. NT 4.0 Beta needs this to work correctly. */
611
612         useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
613
614         /* useable_space can never be more than max_send minus the alignment offset. */
615
616         useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
617
618         while (params_to_send || data_to_send) {
619                 /* Calculate whether we will totally or partially fill this packet */
620
621                 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
622
623                 /* We can never send more than useable_space */
624                 /*
625                  * Note that 'useable_space' does not include the alignment offsets,
626                  * but we must include the alignment offsets in the calculation of
627                  * the length of the data we send over the wire, as the alignment offsets
628                  * are sent here. Fix from Marc_Jacobsen@hp.com.
629                  */
630
631                 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
632
633                 set_message(outbuf, 10, total_sent_thistime, True);
634
635                 /* Set total params and data to be sent */
636                 SSVAL(outbuf,smb_tprcnt,paramsize);
637                 SSVAL(outbuf,smb_tdrcnt,datasize);
638
639                 /* Calculate how many parameters and data we can fit into
640                  * this packet. Parameters get precedence
641                  */
642
643                 params_sent_thistime = MIN(params_to_send,useable_space);
644                 data_sent_thistime = useable_space - params_sent_thistime;
645                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
646
647                 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
648
649                 /* smb_proff is the offset from the start of the SMB header to the
650                         parameter bytes, however the first 4 bytes of outbuf are
651                         the Netbios over TCP header. Thus use smb_base() to subtract
652                         them from the calculation */
653
654                 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
655
656                 if(params_sent_thistime == 0)
657                         SSVAL(outbuf,smb_prdisp,0);
658                 else
659                         /* Absolute displacement of param bytes sent in this packet */
660                         SSVAL(outbuf,smb_prdisp,pp - params);
661
662                 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
663                 if(data_sent_thistime == 0) {
664                         SSVAL(outbuf,smb_droff,0);
665                         SSVAL(outbuf,smb_drdisp, 0);
666                 } else {
667                         /* The offset of the data bytes is the offset of the
668                                 parameter bytes plus the number of parameters being sent this time */
669                         SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
670                                 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
671                         SSVAL(outbuf,smb_drdisp, pd - pdata);
672                 }
673
674                 /* Copy the param bytes into the packet */
675
676                 if(params_sent_thistime)
677                         memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
678
679                 /* Copy in the data bytes */
680                 if(data_sent_thistime)
681                         memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
682                                 data_alignment_offset,pd,data_sent_thistime);
683
684                 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
685                         params_sent_thistime, data_sent_thistime, useable_space));
686                 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
687                         params_to_send, data_to_send, paramsize, datasize));
688
689                 /* Send the packet */
690                 show_msg(outbuf);
691                 if (!send_smb(smbd_server_fd(),outbuf))
692                         exit_server("send_trans2_replies: send_smb failed.");
693
694                 pp += params_sent_thistime;
695                 pd += data_sent_thistime;
696
697                 params_to_send -= params_sent_thistime;
698                 data_to_send -= data_sent_thistime;
699
700                 /* Sanity check */
701                 if(params_to_send < 0 || data_to_send < 0) {
702                         DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
703                                 params_to_send, data_to_send));
704                         return -1;
705                 }
706         }
707
708         return 0;
709 }
710
711 /****************************************************************************
712  Reply to a TRANSACT2_OPEN.
713 ****************************************************************************/
714
715 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
716                                 char **pparams, int total_params, char **ppdata, int total_data,
717                                 unsigned int max_data_bytes)
718 {
719         char *params = *pparams;
720         char *pdata = *ppdata;
721         int deny_mode;
722         int32 open_attr;
723         BOOL oplock_request;
724 #if 0
725         BOOL return_additional_info;
726         int16 open_sattr;
727         time_t open_time;
728 #endif
729         int open_ofun;
730         int32 open_size;
731         char *pname;
732         pstring fname;
733         SMB_OFF_T size=0;
734         int fattr=0,mtime=0;
735         SMB_INO_T inode = 0;
736         SMB_STRUCT_STAT sbuf;
737         int smb_action = 0;
738         BOOL bad_path = False;
739         files_struct *fsp;
740         TALLOC_CTX *ctx = NULL;
741         struct ea_list *ea_list = NULL;
742         uint16 flags = 0;
743         NTSTATUS status;
744         uint32 access_mask;
745         uint32 share_mode;
746         uint32 create_disposition;
747         uint32 create_options = 0;
748
749         /*
750          * Ensure we have enough parameters to perform the operation.
751          */
752
753         if (total_params < 29) {
754                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
755         }
756
757         flags = SVAL(params, 0);
758         deny_mode = SVAL(params, 2);
759         open_attr = SVAL(params,6);
760         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
761         if (oplock_request) {
762                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
763         }
764
765 #if 0
766         return_additional_info = BITSETW(params,0);
767         open_sattr = SVAL(params, 4);
768         open_time = make_unix_date3(params+8);
769 #endif
770         open_ofun = SVAL(params,12);
771         open_size = IVAL(params,14);
772         pname = &params[28];
773
774         if (IS_IPC(conn)) {
775                 return(ERROR_DOS(ERRSRV,ERRaccess));
776         }
777
778         srvstr_get_path(inbuf, fname, pname, sizeof(fname), -1, STR_TERMINATE, &status);
779         if (!NT_STATUS_IS_OK(status)) {
780                 return ERROR_NT(status);
781         }
782
783         DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
784                 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
785                 (unsigned int)open_ofun, open_size));
786
787         /* XXXX we need to handle passed times, sattr and flags */
788
789         unix_convert(fname,conn,0,&bad_path,&sbuf);
790         if (bad_path) {
791                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
792         }
793     
794         if (!check_name(fname,conn)) {
795                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
796         }
797
798         if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
799                                 &access_mask,
800                                 &share_mode,
801                                 &create_disposition,
802                                 &create_options)) {
803                 return ERROR_DOS(ERRDOS, ERRbadaccess);
804         }
805
806         /* Any data in this call is an EA list. */
807         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
808                 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
809         }
810
811         if (total_data != 4) {
812                 if (total_data < 10) {
813                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
814                 }
815
816                 if (IVAL(pdata,0) > total_data) {
817                         DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
818                                 IVAL(pdata,0), (unsigned int)total_data));
819                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
820                 }
821
822                 ctx = talloc_init("TRANS2_OPEN_SET_EA");
823                 if (!ctx) {
824                         return ERROR_NT(NT_STATUS_NO_MEMORY);
825                 }
826                 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
827                 if (!ea_list) {
828                         talloc_destroy(ctx);
829                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
830                 }
831         } else if (IVAL(pdata,0) != 4) {
832                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
833         }
834
835         fsp = open_file_ntcreate(conn,fname,&sbuf,
836                 access_mask,
837                 share_mode,
838                 create_disposition,
839                 create_options,
840                 open_attr,
841                 oplock_request,
842                 &smb_action);
843       
844         if (!fsp) {
845                 talloc_destroy(ctx);
846                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
847                         /* We have re-scheduled this call. */
848                         return -1;
849                 }
850                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
851         }
852
853         size = get_file_size(sbuf);
854         fattr = dos_mode(conn,fname,&sbuf);
855         mtime = sbuf.st_mtime;
856         inode = sbuf.st_ino;
857         if (fattr & aDIR) {
858                 talloc_destroy(ctx);
859                 close_file(fsp,ERROR_CLOSE);
860                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
861         }
862
863         if (total_data && smb_action == FILE_WAS_CREATED) {
864                 status = set_ea(conn, fsp, fname, ea_list);
865                 talloc_destroy(ctx);
866                 if (!NT_STATUS_IS_OK(status)) {
867                         close_file(fsp,ERROR_CLOSE);
868                         return ERROR_NT(status);
869                 }
870         }
871
872         /* Realloc the size of parameters and data we will return */
873         *pparams = SMB_REALLOC(*pparams, 30);
874         if(*pparams == NULL ) {
875                 return ERROR_NT(NT_STATUS_NO_MEMORY);
876         }
877         params = *pparams;
878
879         SSVAL(params,0,fsp->fnum);
880         SSVAL(params,2,open_attr);
881         srv_put_dos_date2(params,4, mtime);
882         SIVAL(params,8, (uint32)size);
883         SSVAL(params,12,deny_mode);
884         SSVAL(params,14,0); /* open_type - file or directory. */
885         SSVAL(params,16,0); /* open_state - only valid for IPC device. */
886
887         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
888                 smb_action |= EXTENDED_OPLOCK_GRANTED;
889         }
890
891         SSVAL(params,18,smb_action);
892
893         /*
894          * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
895          */
896         SIVAL(params,20,inode);
897         SSVAL(params,24,0); /* Padding. */
898         if (flags & 8) {
899                 uint32 ea_size = estimate_ea_size(conn, fsp, fname);
900                 SIVAL(params, 26, ea_size);
901         } else {
902                 SIVAL(params, 26, 0);
903         }
904
905         /* Send the required number of replies */
906         send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0);
907
908         return -1;
909 }
910
911 /*********************************************************
912  Routine to check if a given string matches exactly.
913  as a special case a mask of "." does NOT match. That
914  is required for correct wildcard semantics
915  Case can be significant or not.
916 **********************************************************/
917
918 static BOOL exact_match(char *str,char *mask, BOOL case_sig) 
919 {
920         if (mask[0] == '.' && mask[1] == 0)
921                 return False;
922         if (case_sig)   
923                 return strcmp(str,mask)==0;
924         if (StrCaseCmp(str,mask) != 0) {
925                 return False;
926         }
927         if (ms_has_wild(str)) {
928                 return False;
929         }
930         return True;
931 }
932
933 /****************************************************************************
934  Return the filetype for UNIX extensions.
935 ****************************************************************************/
936
937 static uint32 unix_filetype(mode_t mode)
938 {
939         if(S_ISREG(mode))
940                 return UNIX_TYPE_FILE;
941         else if(S_ISDIR(mode))
942                 return UNIX_TYPE_DIR;
943 #ifdef S_ISLNK
944         else if(S_ISLNK(mode))
945                 return UNIX_TYPE_SYMLINK;
946 #endif
947 #ifdef S_ISCHR
948         else if(S_ISCHR(mode))
949                 return UNIX_TYPE_CHARDEV;
950 #endif
951 #ifdef S_ISBLK
952         else if(S_ISBLK(mode))
953                 return UNIX_TYPE_BLKDEV;
954 #endif
955 #ifdef S_ISFIFO
956         else if(S_ISFIFO(mode))
957                 return UNIX_TYPE_FIFO;
958 #endif
959 #ifdef S_ISSOCK
960         else if(S_ISSOCK(mode))
961                 return UNIX_TYPE_SOCKET;
962 #endif
963
964         DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
965         return UNIX_TYPE_UNKNOWN;
966 }
967
968 /****************************************************************************
969  Map wire perms onto standard UNIX permissions. Obey share restrictions.
970 ****************************************************************************/
971
972 static mode_t unix_perms_from_wire( connection_struct *conn, SMB_STRUCT_STAT *pst, uint32 perms)
973 {
974         mode_t ret = 0;
975
976         if (perms == SMB_MODE_NO_CHANGE)
977                 return pst->st_mode;
978
979         ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
980         ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
981         ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
982         ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
983         ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
984         ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
985         ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
986         ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
987         ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
988 #ifdef S_ISVTX
989         ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
990 #endif
991 #ifdef S_ISGID
992         ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
993 #endif
994 #ifdef S_ISUID
995         ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
996 #endif
997
998         if (VALID_STAT(*pst) && S_ISDIR(pst->st_mode)) {
999                 ret &= lp_dir_mask(SNUM(conn));
1000                 /* Add in force bits */
1001                 ret |= lp_force_dir_mode(SNUM(conn));
1002         } else {
1003                 /* Apply mode mask */
1004                 ret &= lp_create_mask(SNUM(conn));
1005                 /* Add in force bits */
1006                 ret |= lp_force_create_mode(SNUM(conn));
1007         }
1008
1009         return ret;
1010 }
1011
1012 /****************************************************************************
1013  Get a level dependent lanman2 dir entry.
1014 ****************************************************************************/
1015
1016 static BOOL get_lanman2_dir_entry(connection_struct *conn,
1017                                   void *inbuf, void *outbuf,
1018                                  char *path_mask,uint32 dirtype,int info_level,
1019                                  int requires_resume_key,
1020                                  BOOL dont_descend,char **ppdata, 
1021                                  char *base_data, int space_remaining, 
1022                                  BOOL *out_of_space, BOOL *got_exact_match,
1023                                  int *last_entry_off, struct ea_list *name_list, TALLOC_CTX *ea_ctx)
1024 {
1025         const char *dname;
1026         BOOL found = False;
1027         SMB_STRUCT_STAT sbuf;
1028         pstring mask;
1029         pstring pathreal;
1030         pstring fname;
1031         char *p, *q, *pdata = *ppdata;
1032         uint32 reskey=0;
1033         long prev_dirpos=0;
1034         uint32 mode=0;
1035         SMB_OFF_T file_size = 0;
1036         SMB_BIG_UINT allocation_size = 0;
1037         uint32 len;
1038         time_t mdate=0, adate=0, cdate=0;
1039         char *nameptr;
1040         char *last_entry_ptr;
1041         BOOL was_8_3;
1042         uint32 nt_extmode; /* Used for NT connections instead of mode */
1043         BOOL needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1044         BOOL check_mangled_names = lp_manglednames(SNUM(conn));
1045
1046         *fname = 0;
1047         *out_of_space = False;
1048         *got_exact_match = False;
1049
1050         if (!conn->dirptr)
1051                 return(False);
1052
1053         p = strrchr_m(path_mask,'/');
1054         if(p != NULL) {
1055                 if(p[1] == '\0')
1056                         pstrcpy(mask,"*.*");
1057                 else
1058                         pstrcpy(mask, p+1);
1059         } else
1060                 pstrcpy(mask, path_mask);
1061
1062
1063         while (!found) {
1064                 BOOL got_match;
1065                 /* Needed if we run out of space */
1066                 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1067                 dname = dptr_ReadDirName(conn->dirptr,&curr_dirpos,&sbuf);
1068
1069                 /*
1070                  * Due to bugs in NT client redirectors we are not using
1071                  * resume keys any more - set them to zero.
1072                  * Check out the related comments in findfirst/findnext.
1073                  * JRA.
1074                  */
1075
1076                 reskey = 0;
1077
1078                 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1079                         (long)conn->dirptr,curr_dirpos));
1080       
1081                 if (!dname) 
1082                         return(False);
1083
1084                 pstrcpy(fname,dname);      
1085
1086                 if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
1087                         got_match = mask_match(fname, mask, conn->case_sensitive);
1088
1089                 if(!got_match && check_mangled_names && !mangle_is_8_3(fname, False, SNUM(conn))) {
1090
1091                         /*
1092                          * It turns out that NT matches wildcards against
1093                          * both long *and* short names. This may explain some
1094                          * of the wildcard wierdness from old DOS clients
1095                          * that some people have been seeing.... JRA.
1096                          */
1097
1098                         pstring newname;
1099                         pstrcpy( newname, fname);
1100                         mangle_map( newname, True, False, SNUM(conn));
1101                         if(!(got_match = *got_exact_match = exact_match(newname, mask, conn->case_sensitive)))
1102                                 got_match = mask_match(newname, mask, conn->case_sensitive);
1103                 }
1104
1105                 if(got_match) {
1106                         BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
1107                         if (dont_descend && !isdots)
1108                                 continue;
1109           
1110                         pstrcpy(pathreal,conn->dirpath);
1111                         if(needslash)
1112                                 pstrcat(pathreal,"/");
1113                         pstrcat(pathreal,dname);
1114
1115                         if (INFO_LEVEL_IS_UNIX(info_level)) {
1116                                 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1117                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1118                                                 pathreal,strerror(errno)));
1119                                         continue;
1120                                 }
1121                         } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1122
1123                                 /* Needed to show the msdfs symlinks as 
1124                                  * directories */
1125
1126                                 if(lp_host_msdfs() && 
1127                                    lp_msdfs_root(SNUM(conn)) &&
1128                                    is_msdfs_link(NULL,conn, pathreal, NULL, NULL,
1129                                                  &sbuf)) {
1130
1131                                         DEBUG(5,("get_lanman2_dir_entry: Masquerading msdfs link %s as a directory\n", pathreal));
1132                                         sbuf.st_mode = (sbuf.st_mode & 0xFFF) | S_IFDIR;
1133
1134                                 } else {
1135
1136                                         DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1137                                                 pathreal,strerror(errno)));
1138                                         continue;
1139                                 }
1140                         }
1141
1142                         mode = dos_mode(conn,pathreal,&sbuf);
1143
1144                         if (!dir_check_ftype(conn,mode,dirtype)) {
1145                                 DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
1146                                 continue;
1147                         }
1148
1149                         if (!(mode & aDIR))
1150                                 file_size = get_file_size(sbuf);
1151                         allocation_size = get_allocation_size(conn,NULL,&sbuf);
1152                         mdate = sbuf.st_mtime;
1153                         adate = sbuf.st_atime;
1154                         cdate = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1155
1156                         if (lp_dos_filetime_resolution(SNUM(conn))) {
1157                                 cdate &= ~1;
1158                                 mdate &= ~1;
1159                                 adate &= ~1;
1160                         }
1161
1162
1163                         DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
1164           
1165                         found = True;
1166
1167                         dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1168                 }
1169         }
1170
1171         mangle_map(fname,False,True,SNUM(conn));
1172
1173         p = pdata;
1174         last_entry_ptr = p;
1175
1176         nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1177
1178         switch (info_level) {
1179                 case SMB_FIND_INFO_STANDARD:
1180                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1181                         if(requires_resume_key) {
1182                                 SIVAL(p,0,reskey);
1183                                 p += 4;
1184                         }
1185                         srv_put_dos_date2(p,0,cdate);
1186                         srv_put_dos_date2(p,4,adate);
1187                         srv_put_dos_date2(p,8,mdate);
1188                         SIVAL(p,12,(uint32)file_size);
1189                         SIVAL(p,16,(uint32)allocation_size);
1190                         SSVAL(p,20,mode);
1191                         p += 23;
1192                         nameptr = p;
1193                         p += align_string(outbuf, p, 0);
1194                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1195                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1196                                 if (len > 2) {
1197                                         SCVAL(nameptr, -1, len - 2);
1198                                 } else {
1199                                         SCVAL(nameptr, -1, 0);
1200                                 }
1201                         } else {
1202                                 if (len > 1) {
1203                                         SCVAL(nameptr, -1, len - 1);
1204                                 } else {
1205                                         SCVAL(nameptr, -1, 0);
1206                                 }
1207                         }
1208                         p += len;
1209                         break;
1210
1211                 case SMB_FIND_EA_SIZE:
1212                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1213                         if(requires_resume_key) {
1214                                 SIVAL(p,0,reskey);
1215                                 p += 4;
1216                         }
1217                         srv_put_dos_date2(p,0,cdate);
1218                         srv_put_dos_date2(p,4,adate);
1219                         srv_put_dos_date2(p,8,mdate);
1220                         SIVAL(p,12,(uint32)file_size);
1221                         SIVAL(p,16,(uint32)allocation_size);
1222                         SSVAL(p,20,mode);
1223                         {
1224                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1225                                 SIVAL(p,22,ea_size); /* Extended attributes */
1226                         }
1227                         p += 27;
1228                         nameptr = p - 1;
1229                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE | STR_NOALIGN);
1230                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1231                                 if (len > 2) {
1232                                         len -= 2;
1233                                 } else {
1234                                         len = 0;
1235                                 }
1236                         } else {
1237                                 if (len > 1) {
1238                                         len -= 1;
1239                                 } else {
1240                                         len = 0;
1241                                 }
1242                         }
1243                         SCVAL(nameptr,0,len);
1244                         p += len;
1245                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1246                         break;
1247
1248                 case SMB_FIND_EA_LIST:
1249                 {
1250                         struct ea_list *file_list = NULL;
1251                         size_t ea_len = 0;
1252
1253                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1254                         if (!name_list) {
1255                                 return False;
1256                         }
1257                         if(requires_resume_key) {
1258                                 SIVAL(p,0,reskey);
1259                                 p += 4;
1260                         }
1261                         srv_put_dos_date2(p,0,cdate);
1262                         srv_put_dos_date2(p,4,adate);
1263                         srv_put_dos_date2(p,8,mdate);
1264                         SIVAL(p,12,(uint32)file_size);
1265                         SIVAL(p,16,(uint32)allocation_size);
1266                         SSVAL(p,20,mode);
1267                         p += 22; /* p now points to the EA area. */
1268
1269                         file_list = get_ea_list_from_file(ea_ctx, conn, NULL, pathreal, &ea_len);
1270                         name_list = ea_list_union(name_list, file_list, &ea_len);
1271
1272                         /* We need to determine if this entry will fit in the space available. */
1273                         /* Max string size is 255 bytes. */
1274                         if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1275                                 /* Move the dirptr back to prev_dirpos */
1276                                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1277                                 *out_of_space = True;
1278                                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1279                                 return False; /* Not finished - just out of space */
1280                         }
1281
1282                         /* Push the ea_data followed by the name. */
1283                         p += fill_ea_buffer(ea_ctx, p, space_remaining, conn, name_list);
1284                         nameptr = p;
1285                         len = srvstr_push(outbuf, p + 1, fname, -1, STR_TERMINATE | STR_NOALIGN);
1286                         if (SVAL(outbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS) {
1287                                 if (len > 2) {
1288                                         len -= 2;
1289                                 } else {
1290                                         len = 0;
1291                                 }
1292                         } else {
1293                                 if (len > 1) {
1294                                         len -= 1;
1295                                 } else {
1296                                         len = 0;
1297                                 }
1298                         }
1299                         SCVAL(nameptr,0,len);
1300                         p += len + 1;
1301                         SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1302                         break;
1303                 }
1304
1305                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1306                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1307                         was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1308                         p += 4;
1309                         SIVAL(p,0,reskey); p += 4;
1310                         put_long_date(p,cdate); p += 8;
1311                         put_long_date(p,adate); p += 8;
1312                         put_long_date(p,mdate); p += 8;
1313                         put_long_date(p,mdate); p += 8;
1314                         SOFF_T(p,0,file_size); p += 8;
1315                         SOFF_T(p,0,allocation_size); p += 8;
1316                         SIVAL(p,0,nt_extmode); p += 4;
1317                         q = p; p += 4; /* q is placeholder for name length. */
1318                         {
1319                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1320                                 SIVAL(p,0,ea_size); /* Extended attributes */
1321                                 p += 4;
1322                         }
1323                         /* Clear the short name buffer. This is
1324                          * IMPORTANT as not doing so will trigger
1325                          * a Win2k client bug. JRA.
1326                          */
1327                         if (!was_8_3 && check_mangled_names) {
1328                                 pstring mangled_name;
1329                                 pstrcpy(mangled_name, fname);
1330                                 mangle_map(mangled_name,True,True,SNUM(conn));
1331                                 mangled_name[12] = 0;
1332                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1333                                 if (len < 24) {
1334                                         memset(p + 2 + len,'\0',24 - len);
1335                                 }
1336                                 SSVAL(p, 0, len);
1337                         } else {
1338                                 memset(p,'\0',26);
1339                         }
1340                         p += 2 + 24;
1341                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1342                         SIVAL(q,0,len);
1343                         p += len;
1344                         SIVAL(p,0,0); /* Ensure any padding is null. */
1345                         len = PTR_DIFF(p, pdata);
1346                         len = (len + 3) & ~3;
1347                         SIVAL(pdata,0,len);
1348                         p = pdata + len;
1349                         break;
1350
1351                 case SMB_FIND_FILE_DIRECTORY_INFO:
1352                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1353                         p += 4;
1354                         SIVAL(p,0,reskey); p += 4;
1355                         put_long_date(p,cdate); p += 8;
1356                         put_long_date(p,adate); p += 8;
1357                         put_long_date(p,mdate); p += 8;
1358                         put_long_date(p,mdate); p += 8;
1359                         SOFF_T(p,0,file_size); p += 8;
1360                         SOFF_T(p,0,allocation_size); p += 8;
1361                         SIVAL(p,0,nt_extmode); p += 4;
1362                         len = srvstr_push(outbuf, p + 4, fname, -1, STR_TERMINATE_ASCII);
1363                         SIVAL(p,0,len);
1364                         p += 4 + len;
1365                         SIVAL(p,0,0); /* Ensure any padding is null. */
1366                         len = PTR_DIFF(p, pdata);
1367                         len = (len + 3) & ~3;
1368                         SIVAL(pdata,0,len);
1369                         p = pdata + len;
1370                         break;
1371       
1372                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1373                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1374                         p += 4;
1375                         SIVAL(p,0,reskey); p += 4;
1376                         put_long_date(p,cdate); p += 8;
1377                         put_long_date(p,adate); p += 8;
1378                         put_long_date(p,mdate); p += 8;
1379                         put_long_date(p,mdate); p += 8;
1380                         SOFF_T(p,0,file_size); p += 8;
1381                         SOFF_T(p,0,allocation_size); p += 8;
1382                         SIVAL(p,0,nt_extmode); p += 4;
1383                         q = p; p += 4; /* q is placeholder for name length. */
1384                         {
1385                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1386                                 SIVAL(p,0,ea_size); /* Extended attributes */
1387                                 p +=4;
1388                         }
1389                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1390                         SIVAL(q, 0, len);
1391                         p += len;
1392
1393                         SIVAL(p,0,0); /* Ensure any padding is null. */
1394                         len = PTR_DIFF(p, pdata);
1395                         len = (len + 3) & ~3;
1396                         SIVAL(pdata,0,len);
1397                         p = pdata + len;
1398                         break;
1399
1400                 case SMB_FIND_FILE_NAMES_INFO:
1401                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1402                         p += 4;
1403                         SIVAL(p,0,reskey); p += 4;
1404                         p += 4;
1405                         /* this must *not* be null terminated or w2k gets in a loop trying to set an
1406                            acl on a dir (tridge) */
1407                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1408                         SIVAL(p, -4, len);
1409                         p += len;
1410                         SIVAL(p,0,0); /* Ensure any padding is null. */
1411                         len = PTR_DIFF(p, pdata);
1412                         len = (len + 3) & ~3;
1413                         SIVAL(pdata,0,len);
1414                         p = pdata + len;
1415                         break;
1416
1417                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1418                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1419                         p += 4;
1420                         SIVAL(p,0,reskey); p += 4;
1421                         put_long_date(p,cdate); p += 8;
1422                         put_long_date(p,adate); p += 8;
1423                         put_long_date(p,mdate); p += 8;
1424                         put_long_date(p,mdate); p += 8;
1425                         SOFF_T(p,0,file_size); p += 8;
1426                         SOFF_T(p,0,allocation_size); p += 8;
1427                         SIVAL(p,0,nt_extmode); p += 4;
1428                         q = p; p += 4; /* q is placeholder for name length. */
1429                         {
1430                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1431                                 SIVAL(p,0,ea_size); /* Extended attributes */
1432                                 p +=4;
1433                         }
1434                         SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1435                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1436                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1437                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1438                         SIVAL(q, 0, len);
1439                         p += len; 
1440                         SIVAL(p,0,0); /* Ensure any padding is null. */
1441                         len = PTR_DIFF(p, pdata);
1442                         len = (len + 3) & ~3;
1443                         SIVAL(pdata,0,len);
1444                         p = pdata + len;
1445                         break;
1446
1447                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1448                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1449                         was_8_3 = mangle_is_8_3(fname, True, SNUM(conn));
1450                         p += 4;
1451                         SIVAL(p,0,reskey); p += 4;
1452                         put_long_date(p,cdate); p += 8;
1453                         put_long_date(p,adate); p += 8;
1454                         put_long_date(p,mdate); p += 8;
1455                         put_long_date(p,mdate); p += 8;
1456                         SOFF_T(p,0,file_size); p += 8;
1457                         SOFF_T(p,0,allocation_size); p += 8;
1458                         SIVAL(p,0,nt_extmode); p += 4;
1459                         q = p; p += 4; /* q is placeholder for name length */
1460                         {
1461                                 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1462                                 SIVAL(p,0,ea_size); /* Extended attributes */
1463                                 p +=4;
1464                         }
1465                         /* Clear the short name buffer. This is
1466                          * IMPORTANT as not doing so will trigger
1467                          * a Win2k client bug. JRA.
1468                          */
1469                         if (!was_8_3 && check_mangled_names) {
1470                                 pstring mangled_name;
1471                                 pstrcpy(mangled_name, fname);
1472                                 mangle_map(mangled_name,True,True,SNUM(conn));
1473                                 mangled_name[12] = 0;
1474                                 len = srvstr_push(outbuf, p+2, mangled_name, 24, STR_UPPER|STR_UNICODE);
1475                                 SSVAL(p, 0, len);
1476                                 if (len < 24) {
1477                                         memset(p + 2 + len,'\0',24 - len);
1478                                 }
1479                                 SSVAL(p, 0, len);
1480                         } else {
1481                                 memset(p,'\0',26);
1482                         }
1483                         p += 26;
1484                         SSVAL(p,0,0); p += 2; /* Reserved ? */
1485                         SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1486                         SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1487                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE_ASCII);
1488                         SIVAL(q,0,len);
1489                         p += len;
1490                         SIVAL(p,0,0); /* Ensure any padding is null. */
1491                         len = PTR_DIFF(p, pdata);
1492                         len = (len + 3) & ~3;
1493                         SIVAL(pdata,0,len);
1494                         p = pdata + len;
1495                         break;
1496
1497                 /* CIFS UNIX Extension. */
1498
1499                 case SMB_FIND_FILE_UNIX:
1500                         DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1501                         p+= 4;
1502                         SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
1503
1504                         /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1505                         SOFF_T(p,0,get_file_size(sbuf));             /* File size 64 Bit */
1506                         p+= 8;
1507
1508                         SOFF_T(p,0,get_allocation_size(conn,NULL,&sbuf)); /* Number of bytes used on disk - 64 Bit */
1509                         p+= 8;
1510
1511                         put_long_date(p,sbuf.st_ctime);       /* Inode change Time 64 Bit */
1512                         put_long_date(p+8,sbuf.st_atime);     /* Last access time 64 Bit */
1513                         put_long_date(p+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
1514                         p+= 24;
1515
1516                         SIVAL(p,0,sbuf.st_uid);               /* user id for the owner */
1517                         SIVAL(p,4,0);
1518                         p+= 8;
1519
1520                         SIVAL(p,0,sbuf.st_gid);               /* group id of owner */
1521                         SIVAL(p,4,0);
1522                         p+= 8;
1523
1524                         SIVAL(p,0,unix_filetype(sbuf.st_mode));
1525                         p+= 4;
1526
1527                         SIVAL(p,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
1528                         SIVAL(p,4,0);
1529                         p+= 8;
1530
1531                         SIVAL(p,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
1532                         SIVAL(p,4,0);
1533                         p+= 8;
1534
1535                         SINO_T_VAL(p,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
1536                         p+= 8;
1537
1538                         SIVAL(p,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
1539                         SIVAL(p,4,0);
1540                         p+= 8;
1541
1542                         SIVAL(p,0,sbuf.st_nlink);             /* number of hard links */
1543                         SIVAL(p,4,0);
1544                         p+= 8;
1545
1546                         len = srvstr_push(outbuf, p, fname, -1, STR_TERMINATE);
1547                         p += len;
1548                         SIVAL(p,0,0); /* Ensure any padding is null. */
1549
1550                         len = PTR_DIFF(p, pdata);
1551                         len = (len + 3) & ~3;
1552                         SIVAL(pdata,0,len);     /* Offset from this structure to the beginning of the next one */
1553                         p = pdata + len;
1554                         /* End of SMB_QUERY_FILE_UNIX_BASIC */
1555
1556                         break;
1557
1558                 default:      
1559                         return(False);
1560         }
1561
1562
1563         if (PTR_DIFF(p,pdata) > space_remaining) {
1564                 /* Move the dirptr back to prev_dirpos */
1565                 dptr_SeekDir(conn->dirptr, prev_dirpos);
1566                 *out_of_space = True;
1567                 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1568                 return False; /* Not finished - just out of space */
1569         }
1570
1571         /* Setup the last entry pointer, as an offset from base_data */
1572         *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1573         /* Advance the data pointer to the next slot */
1574         *ppdata = p;
1575
1576         return(found);
1577 }
1578
1579 /****************************************************************************
1580  Reply to a TRANS2_FINDFIRST.
1581 ****************************************************************************/
1582
1583 static int call_trans2findfirst(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
1584                                 char **pparams, int total_params, char **ppdata, int total_data,
1585                                 unsigned int max_data_bytes)
1586 {
1587         /* We must be careful here that we don't return more than the
1588                 allowed number of data bytes. If this means returning fewer than
1589                 maxentries then so be it. We assume that the redirector has
1590                 enough room for the fixed number of parameter bytes it has
1591                 requested. */
1592         char *params = *pparams;
1593         char *pdata = *ppdata;
1594         uint32 dirtype = SVAL(params,0);
1595         int maxentries = SVAL(params,2);
1596         uint16 findfirst_flags = SVAL(params,4);
1597         BOOL close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1598         BOOL close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1599         BOOL requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1600         int info_level = SVAL(params,6);
1601         pstring directory;
1602         pstring mask;
1603         char *p;
1604         int last_entry_off=0;
1605         int dptr_num = -1;
1606         int numentries = 0;
1607         int i;
1608         BOOL finished = False;
1609         BOOL dont_descend = False;
1610         BOOL out_of_space = False;
1611         int space_remaining;
1612         BOOL bad_path = False;
1613         BOOL mask_contains_wcard = False;
1614         SMB_STRUCT_STAT sbuf;
1615         TALLOC_CTX *ea_ctx = NULL;
1616         struct ea_list *ea_list = NULL;
1617         NTSTATUS ntstatus = NT_STATUS_OK;
1618
1619         if (total_params < 12) {
1620                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1621         }
1622
1623         *directory = *mask = 0;
1624
1625         DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1626 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1627                 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1628                 info_level, max_data_bytes));
1629
1630         if (!maxentries) {
1631                 /* W2K3 seems to treat zero as 1. */
1632                 maxentries = 1;
1633         }
1634  
1635         switch (info_level) {
1636                 case SMB_FIND_INFO_STANDARD:
1637                 case SMB_FIND_EA_SIZE:
1638                 case SMB_FIND_EA_LIST:
1639                 case SMB_FIND_FILE_DIRECTORY_INFO:
1640                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1641                 case SMB_FIND_FILE_NAMES_INFO:
1642                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1643                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1644                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1645                         break;
1646                 case SMB_FIND_FILE_UNIX:
1647                         if (!lp_unix_extensions())
1648                                 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1649                         break;
1650                 default:
1651                         return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1652         }
1653
1654         srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1655         if (!NT_STATUS_IS_OK(ntstatus)) {
1656                 return ERROR_NT(ntstatus);
1657         }
1658
1659         RESOLVE_DFSPATH_WCARD(directory, conn, inbuf, outbuf);
1660
1661         unix_convert(directory,conn,0,&bad_path,&sbuf);
1662         if (bad_path) {
1663                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
1664         }
1665         if(!check_name(directory,conn)) {
1666                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
1667         }
1668
1669         p = strrchr_m(directory,'/');
1670         if(p == NULL) {
1671                 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1672                 if((directory[0] == '.') && (directory[1] == '\0')) {
1673                         pstrcpy(mask,"*");
1674                         mask_contains_wcard = True;
1675                 } else {
1676                         pstrcpy(mask,directory);
1677                 }
1678                 pstrcpy(directory,"./");
1679         } else {
1680                 pstrcpy(mask,p+1);
1681                 *p = 0;
1682         }
1683
1684         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1685
1686         if (info_level == SMB_FIND_EA_LIST) {
1687                 uint32 ea_size;
1688
1689                 if (total_data < 4) {
1690                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1691                 }
1692
1693                 ea_size = IVAL(pdata,0);
1694                 if (ea_size != total_data) {
1695                         DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
1696 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1697                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1698                 }
1699
1700                 if (!lp_ea_support(SNUM(conn))) {
1701                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
1702                 }
1703                                                                                                                                                         
1704                 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1705                         return ERROR_NT(NT_STATUS_NO_MEMORY);
1706                 }
1707                                                                                                                                                         
1708                 /* Pull out the list of names. */
1709                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1710                 if (!ea_list) {
1711                         talloc_destroy(ea_ctx);
1712                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1713                 }
1714         }
1715
1716         *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1717         if(*ppdata == NULL ) {
1718                 talloc_destroy(ea_ctx);
1719                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1720         }
1721         pdata = *ppdata;
1722
1723         /* Realloc the params space */
1724         *pparams = SMB_REALLOC(*pparams, 10);
1725         if (*pparams == NULL) {
1726                 talloc_destroy(ea_ctx);
1727                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1728         }
1729         params = *pparams;
1730
1731         /* Save the wildcard match and attribs we are using on this directory - 
1732                 needed as lanman2 assumes these are being saved between calls */
1733
1734         dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1735         if (dptr_num < 0) {
1736                 talloc_destroy(ea_ctx);
1737                 return(UNIXERROR(ERRDOS,ERRbadfile));
1738         }
1739
1740         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1741
1742         /* We don't need to check for VOL here as this is returned by 
1743                 a different TRANS2 call. */
1744   
1745         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1746         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1747                 dont_descend = True;
1748     
1749         p = pdata;
1750         space_remaining = max_data_bytes;
1751         out_of_space = False;
1752
1753         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1754                 BOOL got_exact_match = False;
1755
1756                 /* this is a heuristic to avoid seeking the dirptr except when 
1757                         absolutely necessary. It allows for a filename of about 40 chars */
1758                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1759                         out_of_space = True;
1760                         finished = False;
1761                 } else {
1762                         finished = !get_lanman2_dir_entry(conn,
1763                                         inbuf, outbuf,
1764                                         mask,dirtype,info_level,
1765                                         requires_resume_key,dont_descend,
1766                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1767                                         &last_entry_off, ea_list, ea_ctx);
1768                 }
1769
1770                 if (finished && out_of_space)
1771                         finished = False;
1772
1773                 if (!finished && !out_of_space)
1774                         numentries++;
1775
1776                 /*
1777                  * As an optimisation if we know we aren't looking
1778                  * for a wildcard name (ie. the name matches the wildcard exactly)
1779                  * then we can finish on any (first) match.
1780                  * This speeds up large directory searches. JRA.
1781                  */
1782
1783                 if(got_exact_match)
1784                         finished = True;
1785
1786                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1787         }
1788   
1789         talloc_destroy(ea_ctx);
1790
1791         /* Check if we can close the dirptr */
1792         if(close_after_first || (finished && close_if_end)) {
1793                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1794                 dptr_close(&dptr_num);
1795         }
1796
1797         /* 
1798          * If there are no matching entries we must return ERRDOS/ERRbadfile - 
1799          * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1800          * the protocol level is less than NT1. Tested with smbclient. JRA.
1801          * This should fix the OS/2 client bug #2335.
1802          */
1803
1804         if(numentries == 0) {
1805                 dptr_close(&dptr_num);
1806                 if (Protocol < PROTOCOL_NT1) {
1807                         return ERROR_DOS(ERRDOS,ERRnofiles);
1808                 } else {
1809                         return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1810                 }
1811         }
1812
1813         /* At this point pdata points to numentries directory entries. */
1814
1815         /* Set up the return parameter block */
1816         SSVAL(params,0,dptr_num);
1817         SSVAL(params,2,numentries);
1818         SSVAL(params,4,finished);
1819         SSVAL(params,6,0); /* Never an EA error */
1820         SSVAL(params,8,last_entry_off);
1821
1822         send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1823
1824         if ((! *directory) && dptr_path(dptr_num))
1825                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1826
1827         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1828                 smb_fn_name(CVAL(inbuf,smb_com)), 
1829                 mask, directory, dirtype, numentries ) );
1830
1831         /* 
1832          * Force a name mangle here to ensure that the
1833          * mask as an 8.3 name is top of the mangled cache.
1834          * The reasons for this are subtle. Don't remove
1835          * this code unless you know what you are doing
1836          * (see PR#13758). JRA.
1837          */
1838
1839         if(!mangle_is_8_3_wildcards( mask, False, SNUM(conn)))
1840                 mangle_map(mask, True, True, SNUM(conn));
1841
1842         return(-1);
1843 }
1844
1845 /****************************************************************************
1846  Reply to a TRANS2_FINDNEXT.
1847 ****************************************************************************/
1848
1849 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1850                                         char **pparams, int total_params, char **ppdata, int total_data,
1851                                         unsigned int max_data_bytes)
1852 {
1853         /* We must be careful here that we don't return more than the
1854                 allowed number of data bytes. If this means returning fewer than
1855                 maxentries then so be it. We assume that the redirector has
1856                 enough room for the fixed number of parameter bytes it has
1857                 requested. */
1858         char *params = *pparams;
1859         char *pdata = *ppdata;
1860         int dptr_num = SVAL(params,0);
1861         int maxentries = SVAL(params,2);
1862         uint16 info_level = SVAL(params,4);
1863         uint32 resume_key = IVAL(params,6);
1864         uint16 findnext_flags = SVAL(params,10);
1865         BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1866         BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1867         BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1868         BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1869         BOOL mask_contains_wcard = False;
1870         pstring resume_name;
1871         pstring mask;
1872         pstring directory;
1873         char *p;
1874         uint16 dirtype;
1875         int numentries = 0;
1876         int i, last_entry_off=0;
1877         BOOL finished = False;
1878         BOOL dont_descend = False;
1879         BOOL out_of_space = False;
1880         int space_remaining;
1881         TALLOC_CTX *ea_ctx = NULL;
1882         struct ea_list *ea_list = NULL;
1883         NTSTATUS ntstatus = NT_STATUS_OK;
1884
1885         if (total_params < 12) {
1886                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1887         }
1888
1889         *mask = *directory = *resume_name = 0;
1890
1891         srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1892         if (!NT_STATUS_IS_OK(ntstatus)) {
1893                 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1894                    complain (it thinks we're asking for the directory above the shared
1895                    path or an invalid name). Catch this as the resume name is only compared, never used in
1896                    a file access. JRA. */
1897                 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1898                         pstrcpy(resume_name, "..");
1899                 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1900                         pstrcpy(resume_name, ".");
1901                 } else {
1902                         return ERROR_NT(ntstatus);
1903                 }
1904         }
1905
1906         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1907 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1908 resume_key = %d resume name = %s continue=%d level = %d\n",
1909                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
1910                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1911
1912         if (!maxentries) {
1913                 /* W2K3 seems to treat zero as 1. */
1914                 maxentries = 1;
1915         }
1916
1917         switch (info_level) {
1918                 case SMB_FIND_INFO_STANDARD:
1919                 case SMB_FIND_EA_SIZE:
1920                 case SMB_FIND_EA_LIST:
1921                 case SMB_FIND_FILE_DIRECTORY_INFO:
1922                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1923                 case SMB_FIND_FILE_NAMES_INFO:
1924                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1925                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1926                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1927                         break;
1928                 case SMB_FIND_FILE_UNIX:
1929                         if (!lp_unix_extensions())
1930                                 return(ERROR_DOS(ERRDOS,ERRunknownlevel));
1931                         break;
1932                 default:
1933                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
1934         }
1935
1936         if (info_level == SMB_FIND_EA_LIST) {
1937                 uint32 ea_size;
1938
1939                 if (total_data < 4) {
1940                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1941                 }
1942
1943                 ea_size = IVAL(pdata,0);
1944                 if (ea_size != total_data) {
1945                         DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1946 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1947                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1948                 }
1949                                                                                                                                                      
1950                 if (!lp_ea_support(SNUM(conn))) {
1951                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
1952                 }
1953                                                                                                                                                      
1954                 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1955                         return ERROR_NT(NT_STATUS_NO_MEMORY);
1956                 }
1957
1958                 /* Pull out the list of names. */
1959                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
1960                 if (!ea_list) {
1961                         talloc_destroy(ea_ctx);
1962                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1963                 }
1964         }
1965
1966         *ppdata = SMB_REALLOC( *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1967         if(*ppdata == NULL) {
1968                 talloc_destroy(ea_ctx);
1969                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1970         }
1971
1972         pdata = *ppdata;
1973
1974         /* Realloc the params space */
1975         *pparams = SMB_REALLOC(*pparams, 6*SIZEOFWORD);
1976         if(*pparams == NULL ) {
1977                 talloc_destroy(ea_ctx);
1978                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1979         }
1980
1981         params = *pparams;
1982
1983         /* Check that the dptr is valid */
1984         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
1985                 talloc_destroy(ea_ctx);
1986                 return ERROR_DOS(ERRDOS,ERRnofiles);
1987         }
1988
1989         string_set(&conn->dirpath,dptr_path(dptr_num));
1990
1991         /* Get the wildcard mask from the dptr */
1992         if((p = dptr_wcard(dptr_num))== NULL) {
1993                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
1994                 talloc_destroy(ea_ctx);
1995                 return ERROR_DOS(ERRDOS,ERRnofiles);
1996         }
1997
1998         pstrcpy(mask, p);
1999         pstrcpy(directory,conn->dirpath);
2000
2001         /* Get the attr mask from the dptr */
2002         dirtype = dptr_attr(dptr_num);
2003
2004         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2005                 dptr_num, mask, dirtype, 
2006                 (long)conn->dirptr,
2007                 dptr_TellDir(conn->dirptr)));
2008
2009         /* We don't need to check for VOL here as this is returned by 
2010                 a different TRANS2 call. */
2011
2012         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2013         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2014                 dont_descend = True;
2015     
2016         p = pdata;
2017         space_remaining = max_data_bytes;
2018         out_of_space = False;
2019
2020         /* 
2021          * Seek to the correct position. We no longer use the resume key but
2022          * depend on the last file name instead.
2023          */
2024
2025         if(*resume_name && !continue_bit) {
2026                 SMB_STRUCT_STAT st;
2027
2028                 long current_pos = 0;
2029                 /*
2030                  * Remember, mangle_map is called by
2031                  * get_lanman2_dir_entry(), so the resume name
2032                  * could be mangled. Ensure we check the unmangled name.
2033                  */
2034
2035                 if (mangle_is_mangled(resume_name, SNUM(conn))) {
2036                         mangle_check_cache(resume_name, sizeof(resume_name)-1, SNUM(conn));
2037                 }
2038
2039                 /*
2040                  * Fix for NT redirector problem triggered by resume key indexes
2041                  * changing between directory scans. We now return a resume key of 0
2042                  * and instead look for the filename to continue from (also given
2043                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2044                  * findfirst/findnext (as is usual) then the directory pointer
2045                  * should already be at the correct place.
2046                  */
2047
2048                 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2049         } /* end if resume_name && !continue_bit */
2050
2051         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2052                 BOOL got_exact_match = False;
2053
2054                 /* this is a heuristic to avoid seeking the dirptr except when 
2055                         absolutely necessary. It allows for a filename of about 40 chars */
2056                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2057                         out_of_space = True;
2058                         finished = False;
2059                 } else {
2060                         finished = !get_lanman2_dir_entry(conn,
2061                                                 inbuf, outbuf,
2062                                                 mask,dirtype,info_level,
2063                                                 requires_resume_key,dont_descend,
2064                                                 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2065                                                 &last_entry_off, ea_list, ea_ctx);
2066                 }
2067
2068                 if (finished && out_of_space)
2069                         finished = False;
2070
2071                 if (!finished && !out_of_space)
2072                         numentries++;
2073
2074                 /*
2075                  * As an optimisation if we know we aren't looking
2076                  * for a wildcard name (ie. the name matches the wildcard exactly)
2077                  * then we can finish on any (first) match.
2078                  * This speeds up large directory searches. JRA.
2079                  */
2080
2081                 if(got_exact_match)
2082                         finished = True;
2083
2084                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2085         }
2086   
2087         talloc_destroy(ea_ctx);
2088
2089         /* Check if we can close the dirptr */
2090         if(close_after_request || (finished && close_if_end)) {
2091                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2092                 dptr_close(&dptr_num); /* This frees up the saved mask */
2093         }
2094
2095         /* Set up the return parameter block */
2096         SSVAL(params,0,numentries);
2097         SSVAL(params,2,finished);
2098         SSVAL(params,4,0); /* Never an EA error */
2099         SSVAL(params,6,last_entry_off);
2100
2101         send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2102
2103         if ((! *directory) && dptr_path(dptr_num))
2104                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2105
2106         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2107                 smb_fn_name(CVAL(inbuf,smb_com)), 
2108                 mask, directory, dirtype, numentries ) );
2109
2110         return(-1);
2111 }
2112
2113 /****************************************************************************
2114  Reply to a TRANS2_QFSINFO (query filesystem info).
2115 ****************************************************************************/
2116
2117 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2118                                         char **pparams, int total_params, char **ppdata, int total_data,
2119                                         unsigned int max_data_bytes)
2120 {
2121         char *pdata = *ppdata;
2122         char *params = *pparams;
2123         uint16 info_level = SVAL(params,0);
2124         int data_len, len;
2125         SMB_STRUCT_STAT st;
2126         char *vname = volume_label(SNUM(conn));
2127         int snum = SNUM(conn);
2128         char *fstype = lp_fstype(SNUM(conn));
2129         int quota_flag = 0;
2130
2131         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2132
2133         if(SMB_VFS_STAT(conn,".",&st)!=0) {
2134                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2135                 return ERROR_DOS(ERRSRV,ERRinvdevice);
2136         }
2137
2138         *ppdata = SMB_REALLOC(*ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2139         if (*ppdata == NULL ) {
2140                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2141         }
2142
2143         pdata = *ppdata;
2144         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2145
2146         switch (info_level) {
2147                 case SMB_INFO_ALLOCATION:
2148                 {
2149                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2150                         data_len = 18;
2151                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2152                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2153                         }
2154
2155                         block_size = lp_block_size(snum);
2156                         if (bsize < block_size) {
2157                                 SMB_BIG_UINT factor = block_size/bsize;
2158                                 bsize = block_size;
2159                                 dsize /= factor;
2160                                 dfree /= factor;
2161                         }
2162                         if (bsize > block_size) {
2163                                 SMB_BIG_UINT factor = bsize/block_size;
2164                                 bsize = block_size;
2165                                 dsize *= factor;
2166                                 dfree *= factor;
2167                         }
2168                         bytes_per_sector = 512;
2169                         sectors_per_unit = bsize/bytes_per_sector;
2170
2171                         DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2172 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2173                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2174
2175                         SIVAL(pdata,l1_idFileSystem,st.st_dev);
2176                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2177                         SIVAL(pdata,l1_cUnit,dsize);
2178                         SIVAL(pdata,l1_cUnitAvail,dfree);
2179                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
2180                         break;
2181                 }
2182
2183                 case SMB_INFO_VOLUME:
2184                         /* Return volume name */
2185                         /* 
2186                          * Add volume serial number - hash of a combination of
2187                          * the called hostname and the service name.
2188                          */
2189                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2190                         /*
2191                          * Win2k3 and previous mess this up by sending a name length
2192                          * one byte short. I believe only older clients (OS/2 Win9x) use
2193                          * this call so try fixing this by adding a terminating null to
2194                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2195                          */
2196                         len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2197                         SCVAL(pdata,l2_vol_cch,len);
2198                         data_len = l2_vol_szVolLabel + len;
2199                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2200                                 (unsigned)st.st_ctime, len, vname));
2201                         break;
2202
2203                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2204                 case SMB_FS_ATTRIBUTE_INFORMATION:
2205
2206
2207 #if defined(HAVE_SYS_QUOTAS)
2208                         quota_flag = FILE_VOLUME_QUOTAS;
2209 #endif
2210
2211                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2212                                 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2213                                 quota_flag); /* FS ATTRIBUTES */
2214
2215                         SIVAL(pdata,4,255); /* Max filename component length */
2216                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2217                                 and will think we can't do long filenames */
2218                         len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2219                         SIVAL(pdata,8,len);
2220                         data_len = 12 + len;
2221                         break;
2222
2223                 case SMB_QUERY_FS_LABEL_INFO:
2224                 case SMB_FS_LABEL_INFORMATION:
2225                         len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2226                         data_len = 4 + len;
2227                         SIVAL(pdata,0,len);
2228                         break;
2229
2230                 case SMB_QUERY_FS_VOLUME_INFO:      
2231                 case SMB_FS_VOLUME_INFORMATION:
2232
2233                         /* 
2234                          * Add volume serial number - hash of a combination of
2235                          * the called hostname and the service name.
2236                          */
2237                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
2238                                 (str_checksum(get_local_machine_name())<<16));
2239
2240                         len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2241                         SIVAL(pdata,12,len);
2242                         data_len = 18+len;
2243                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
2244                                 (int)strlen(vname),vname, lp_servicename(snum)));
2245                         break;
2246
2247                 case SMB_QUERY_FS_SIZE_INFO:
2248                 case SMB_FS_SIZE_INFORMATION:
2249                 {
2250                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2251                         data_len = 24;
2252                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2253                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2254                         }
2255                         block_size = lp_block_size(snum);
2256                         if (bsize < block_size) {
2257                                 SMB_BIG_UINT factor = block_size/bsize;
2258                                 bsize = block_size;
2259                                 dsize /= factor;
2260                                 dfree /= factor;
2261                         }
2262                         if (bsize > block_size) {
2263                                 SMB_BIG_UINT factor = bsize/block_size;
2264                                 bsize = block_size;
2265                                 dsize *= factor;
2266                                 dfree *= factor;
2267                         }
2268                         bytes_per_sector = 512;
2269                         sectors_per_unit = bsize/bytes_per_sector;
2270                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2271 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2272                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2273                         SBIG_UINT(pdata,0,dsize);
2274                         SBIG_UINT(pdata,8,dfree);
2275                         SIVAL(pdata,16,sectors_per_unit);
2276                         SIVAL(pdata,20,bytes_per_sector);
2277                         break;
2278                 }
2279
2280                 case SMB_FS_FULL_SIZE_INFORMATION:
2281                 {
2282                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2283                         data_len = 32;
2284                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2285                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2286                         }
2287                         block_size = lp_block_size(snum);
2288                         if (bsize < block_size) {
2289                                 SMB_BIG_UINT factor = block_size/bsize;
2290                                 bsize = block_size;
2291                                 dsize /= factor;
2292                                 dfree /= factor;
2293                         }
2294                         if (bsize > block_size) {
2295                                 SMB_BIG_UINT factor = bsize/block_size;
2296                                 bsize = block_size;
2297                                 dsize *= factor;
2298                                 dfree *= factor;
2299                         }
2300                         bytes_per_sector = 512;
2301                         sectors_per_unit = bsize/bytes_per_sector;
2302                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2303 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2304                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2305                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2306                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2307                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2308                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2309                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2310                         break;
2311                 }
2312
2313                 case SMB_QUERY_FS_DEVICE_INFO:
2314                 case SMB_FS_DEVICE_INFORMATION:
2315                         data_len = 8;
2316                         SIVAL(pdata,0,0); /* dev type */
2317                         SIVAL(pdata,4,0); /* characteristics */
2318                         break;
2319
2320 #ifdef HAVE_SYS_QUOTAS
2321                 case SMB_FS_QUOTA_INFORMATION:
2322                 /* 
2323                  * what we have to send --metze:
2324                  *
2325                  * Unknown1:            24 NULL bytes
2326                  * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2327                  * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
2328                  * Quota Flags:         2 byte :
2329                  * Unknown3:            6 NULL bytes
2330                  *
2331                  * 48 bytes total
2332                  * 
2333                  * details for Quota Flags:
2334                  * 
2335                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2336                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2337                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2338                  * 0x0001 Enable Quotas: enable quota for this fs
2339                  *
2340                  */
2341                 {
2342                         /* we need to fake up a fsp here,
2343                          * because its not send in this call
2344                          */
2345                         files_struct fsp;
2346                         SMB_NTQUOTA_STRUCT quotas;
2347                         
2348                         ZERO_STRUCT(fsp);
2349                         ZERO_STRUCT(quotas);
2350                         
2351                         fsp.conn = conn;
2352                         fsp.fnum = -1;
2353                         
2354                         /* access check */
2355                         if (current_user.ut.uid != 0) {
2356                                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2357                                         lp_servicename(SNUM(conn)),conn->user));
2358                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2359                         }
2360                         
2361                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2362                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2363                                 return ERROR_DOS(ERRSRV,ERRerror);
2364                         }
2365
2366                         data_len = 48;
2367
2368                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
2369                 
2370                         /* Unknown1 24 NULL bytes*/
2371                         SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2372                         SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2373                         SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2374                 
2375                         /* Default Soft Quota 8 bytes */
2376                         SBIG_UINT(pdata,24,quotas.softlim);
2377
2378                         /* Default Hard Quota 8 bytes */
2379                         SBIG_UINT(pdata,32,quotas.hardlim);
2380         
2381                         /* Quota flag 2 bytes */
2382                         SSVAL(pdata,40,quotas.qflags);
2383                 
2384                         /* Unknown3 6 NULL bytes */
2385                         SSVAL(pdata,42,0);
2386                         SIVAL(pdata,44,0);
2387                         
2388                         break;
2389                 }
2390 #endif /* HAVE_SYS_QUOTAS */
2391                 case SMB_FS_OBJECTID_INFORMATION:
2392                         data_len = 64;
2393                         break;
2394
2395                 /*
2396                  * Query the version and capabilities of the CIFS UNIX extensions
2397                  * in use.
2398                  */
2399
2400                 case SMB_QUERY_CIFS_UNIX_INFO:
2401                         if (!lp_unix_extensions())
2402                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2403                         data_len = 12;
2404                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2405                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2406                         SBIG_UINT(pdata,4,((SMB_BIG_UINT)(CIFS_UNIX_POSIX_ACLS_CAP|
2407                                         CIFS_UNIX_POSIX_PATHNAMES_CAP))); /* We have POSIX ACLs and pathname capability. */
2408                         break;
2409
2410                 case SMB_QUERY_POSIX_FS_INFO:
2411                 {
2412                         int rc;
2413                         vfs_statvfs_struct svfs;
2414
2415                         if (!lp_unix_extensions())
2416                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2417                         
2418                         rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2419
2420                         if (!rc) {
2421                                 data_len = 56;
2422                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
2423                                 SIVAL(pdata,4,svfs.BlockSize);
2424                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2425                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2426                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2427                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2428                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2429                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2430                                 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2431 #ifdef EOPNOTSUPP
2432                         } else if (rc == EOPNOTSUPP) {
2433                                 return ERROR_DOS(ERRDOS, ERRunknownlevel);
2434 #endif /* EOPNOTSUPP */
2435                         } else {
2436                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2437                                 return ERROR_DOS(ERRSRV,ERRerror);
2438                         }
2439                         break;
2440                 }
2441
2442                 case SMB_MAC_QUERY_FS_INFO:
2443                         /*
2444                          * Thursby MAC extension... ONLY on NTFS filesystems
2445                          * once we do streams then we don't need this
2446                          */
2447                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2448                                 data_len = 88;
2449                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2450                                 break;
2451                         }
2452                         /* drop through */
2453                 default:
2454                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2455         }
2456
2457
2458         send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2459
2460         DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2461
2462         return -1;
2463 }
2464
2465 /****************************************************************************
2466  Reply to a TRANS2_SETFSINFO (set filesystem info).
2467 ****************************************************************************/
2468
2469 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2470                                         char **pparams, int total_params, char **ppdata, int total_data,
2471                                         unsigned int max_data_bytes)
2472 {
2473         char *pdata = *ppdata;
2474         char *params = *pparams;
2475         uint16 info_level;
2476         int outsize;
2477
2478         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2479
2480         /*  */
2481         if (total_params < 4) {
2482                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2483                         total_params));
2484                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2485         }
2486
2487         info_level = SVAL(params,2);
2488
2489         switch(info_level) {
2490                 case SMB_SET_CIFS_UNIX_INFO:
2491                         {
2492                                 uint16 client_unix_major;
2493                                 uint16 client_unix_minor;
2494                                 uint32 client_unix_cap_low;
2495                                 uint32 client_unix_cap_high;
2496
2497                                 if (!lp_unix_extensions()) {
2498                                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2499                                 }
2500
2501                                 /* There should be 12 bytes of capabilities set. */
2502                                 if (total_data < 8) {
2503                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2504                                 }
2505                                 client_unix_major = SVAL(pdata,0);
2506                                 client_unix_minor = SVAL(pdata,2);
2507                                 client_unix_cap_low = IVAL(pdata,4);
2508                                 client_unix_cap_high = IVAL(pdata,8);
2509                                 /* Just print these values for now. */
2510                                 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2511 cap_low = 0x%x, cap_high = 0x%x\n",
2512                                         (unsigned int)client_unix_major,
2513                                         (unsigned int)client_unix_minor,
2514                                         (unsigned int)client_unix_cap_low,
2515                                         (unsigned int)client_unix_cap_high ));
2516
2517                                 /* Here is where we must switch to posix pathname processing... */
2518                                 lp_set_posix_pathnames();
2519                                 mangle_change_to_posix();
2520                                 break;
2521                         }
2522                 case SMB_FS_QUOTA_INFORMATION:
2523                         {
2524                                 files_struct *fsp = NULL;
2525                                 SMB_NTQUOTA_STRUCT quotas;
2526         
2527                                 ZERO_STRUCT(quotas);
2528
2529                                 /* access check */
2530                                 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2531                                         DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2532                                                 lp_servicename(SNUM(conn)),conn->user));
2533                                         return ERROR_DOS(ERRSRV,ERRaccess);
2534                                 }
2535
2536                                 /* note: normaly there're 48 bytes,
2537                                  * but we didn't use the last 6 bytes for now 
2538                                  * --metze 
2539                                  */
2540                                 fsp = file_fsp(params,0);
2541                                 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2542                                         DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2543                                         return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2544                                 }
2545
2546                                 if (total_data < 42) {
2547                                         DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2548                                                 total_data));
2549                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2550                                 }
2551                         
2552                                 /* unknown_1 24 NULL bytes in pdata*/
2553                 
2554                                 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2555                                 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2556 #ifdef LARGE_SMB_OFF_T
2557                                 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2558 #else /* LARGE_SMB_OFF_T */
2559                                 if ((IVAL(pdata,28) != 0)&&
2560                                         ((quotas.softlim != 0xFFFFFFFF)||
2561                                         (IVAL(pdata,28)!=0xFFFFFFFF))) {
2562                                         /* more than 32 bits? */
2563                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2564                                 }
2565 #endif /* LARGE_SMB_OFF_T */
2566                 
2567                                 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2568                                 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2569 #ifdef LARGE_SMB_OFF_T
2570                                 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2571 #else /* LARGE_SMB_OFF_T */
2572                                 if ((IVAL(pdata,36) != 0)&&
2573                                         ((quotas.hardlim != 0xFFFFFFFF)||
2574                                         (IVAL(pdata,36)!=0xFFFFFFFF))) {
2575                                         /* more than 32 bits? */
2576                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2577                                 }
2578 #endif /* LARGE_SMB_OFF_T */
2579                 
2580                                 /* quota_flags 2 bytes **/
2581                                 quotas.qflags = SVAL(pdata,40);
2582                 
2583                                 /* unknown_2 6 NULL bytes follow*/
2584                 
2585                                 /* now set the quotas */
2586                                 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2587                                         DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2588                                         return ERROR_DOS(ERRSRV,ERRerror);
2589                                 }
2590                         
2591                                 break;
2592                         }
2593                 default:
2594                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2595                                 info_level));
2596                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
2597                         break;
2598         }
2599
2600         /* 
2601          * sending this reply works fine, 
2602          * but I'm not sure it's the same 
2603          * like windows do...
2604          * --metze
2605          */ 
2606         outsize = set_message(outbuf,10,0,True);
2607
2608         return outsize;
2609 }
2610
2611 /****************************************************************************
2612  Utility function to set bad path error.
2613 ****************************************************************************/
2614
2615 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2616 {
2617         DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2618                         err, (int)bad_path ));
2619
2620         if(err == ENOENT) {
2621                 if (bad_path) {
2622                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2623                 } else {
2624                         return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2625                 }
2626         }
2627         return UNIXERROR(def_class,def_code);
2628 }
2629
2630 #if defined(HAVE_POSIX_ACLS)
2631 /****************************************************************************
2632  Utility function to count the number of entries in a POSIX acl.
2633 ****************************************************************************/
2634
2635 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2636 {
2637         unsigned int ace_count = 0;
2638         int entry_id = SMB_ACL_FIRST_ENTRY;
2639         SMB_ACL_ENTRY_T entry;
2640
2641         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2642                 /* get_next... */
2643                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2644                         entry_id = SMB_ACL_NEXT_ENTRY;
2645                 }
2646                 ace_count++;
2647         }
2648         return ace_count;
2649 }
2650
2651 /****************************************************************************
2652  Utility function to marshall a POSIX acl into wire format.
2653 ****************************************************************************/
2654
2655 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2656 {
2657         int entry_id = SMB_ACL_FIRST_ENTRY;
2658         SMB_ACL_ENTRY_T entry;
2659
2660         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2661                 SMB_ACL_TAG_T tagtype;
2662                 SMB_ACL_PERMSET_T permset;
2663                 unsigned char perms = 0;
2664                 unsigned int own_grp;
2665
2666                 /* get_next... */
2667                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2668                         entry_id = SMB_ACL_NEXT_ENTRY;
2669                 }
2670
2671                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2672                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2673                         return False;
2674                 }
2675
2676                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2677                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2678                         return False;
2679                 }
2680
2681                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2682                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2683                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2684
2685                 SCVAL(pdata,1,perms);
2686
2687                 switch (tagtype) {
2688                         case SMB_ACL_USER_OBJ:
2689                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2690                                 own_grp = (unsigned int)pst->st_uid;
2691                                 SIVAL(pdata,2,own_grp);
2692                                 SIVAL(pdata,6,0);
2693                                 break;
2694                         case SMB_ACL_USER:
2695                                 {
2696                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2697                                         if (!puid) {
2698                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2699                                         }
2700                                         own_grp = (unsigned int)*puid;
2701                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2702                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2703                                         SIVAL(pdata,2,own_grp);
2704                                         SIVAL(pdata,6,0);
2705                                         break;
2706                                 }
2707                         case SMB_ACL_GROUP_OBJ:
2708                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2709                                 own_grp = (unsigned int)pst->st_gid;
2710                                 SIVAL(pdata,2,own_grp);
2711                                 SIVAL(pdata,6,0);
2712                                 break;
2713                         case SMB_ACL_GROUP:
2714                                 {
2715                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2716                                         if (!pgid) {
2717                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2718                                         }
2719                                         own_grp = (unsigned int)*pgid;
2720                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2721                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2722                                         SIVAL(pdata,2,own_grp);
2723                                         SIVAL(pdata,6,0);
2724                                         break;
2725                                 }
2726                         case SMB_ACL_MASK:
2727                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2728                                 SIVAL(pdata,2,0xFFFFFFFF);
2729                                 SIVAL(pdata,6,0xFFFFFFFF);
2730                                 break;
2731                         case SMB_ACL_OTHER:
2732                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2733                                 SIVAL(pdata,2,0xFFFFFFFF);
2734                                 SIVAL(pdata,6,0xFFFFFFFF);
2735                                 break;
2736                         default:
2737                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2738                                 return False;
2739                 }
2740                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2741         }
2742
2743         return True;
2744 }
2745 #endif
2746
2747 /****************************************************************************
2748  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2749  file name or file id).
2750 ****************************************************************************/
2751
2752 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2753                                         unsigned int tran_call,
2754                                         char **pparams, int total_params, char **ppdata, int total_data,
2755                                         unsigned int max_data_bytes)
2756 {
2757         char *params = *pparams;
2758         char *pdata = *ppdata;
2759         uint16 info_level;
2760         int mode=0;
2761         int nlink;
2762         SMB_OFF_T file_size=0;
2763         SMB_BIG_UINT allocation_size=0;
2764         unsigned int data_size = 0;
2765         unsigned int param_size = 2;
2766         SMB_STRUCT_STAT sbuf;
2767         pstring fname, dos_fname;
2768         char *fullpathname;
2769         char *base_name;
2770         char *p;
2771         SMB_OFF_T pos = 0;
2772         BOOL bad_path = False;
2773         BOOL delete_pending = False;
2774         int len;
2775         time_t c_time;
2776         files_struct *fsp = NULL;
2777         TALLOC_CTX *ea_ctx = NULL;
2778         struct ea_list *ea_list = NULL;
2779         uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2780
2781         if (!params)
2782                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2783
2784         ZERO_STRUCT(sbuf);
2785
2786         if (tran_call == TRANSACT2_QFILEINFO) {
2787                 if (total_params < 4) {
2788                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2789                 }
2790
2791                 fsp = file_fsp(params,0);
2792                 info_level = SVAL(params,2);
2793
2794                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2795
2796                 if(fsp && (fsp->fake_file_handle)) {
2797                         /*
2798                          * This is actually for the QUOTA_FAKE_FILE --metze
2799                          */
2800                                                 
2801                         pstrcpy(fname, fsp->fsp_name);
2802                         /* We know this name is ok, it's already passed the checks. */
2803                         
2804                 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2805                         /*
2806                          * This is actually a QFILEINFO on a directory
2807                          * handle (returned from an NT SMB). NT5.0 seems
2808                          * to do this call. JRA.
2809                          */
2810                         /* We know this name is ok, it's already passed the checks. */
2811                         pstrcpy(fname, fsp->fsp_name);
2812                   
2813                         if (INFO_LEVEL_IS_UNIX(info_level)) {
2814                                 /* Always do lstat for UNIX calls. */
2815                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2816                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2817                                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2818                                 }
2819                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2820                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2821                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2822                         }
2823
2824                         delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2825                 } else {
2826                         /*
2827                          * Original code - this is an open file.
2828                          */
2829                         CHECK_FSP(fsp,conn);
2830
2831                         pstrcpy(fname, fsp->fsp_name);
2832                         if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2833                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2834                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2835                         }
2836                         pos = fsp->fh->position_information;
2837                         delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2838                         access_mask = fsp->access_mask;
2839                 }
2840         } else {
2841                 NTSTATUS status = NT_STATUS_OK;
2842
2843                 /* qpathinfo */
2844                 if (total_params < 6) {
2845                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2846                 }
2847
2848                 info_level = SVAL(params,0);
2849
2850                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2851
2852                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
2853                 if (!NT_STATUS_IS_OK(status)) {
2854                         return ERROR_NT(status);
2855                 }
2856
2857                 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2858
2859                 unix_convert(fname,conn,0,&bad_path,&sbuf);
2860                 if (bad_path) {
2861                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2862                 }
2863                 if (!check_name(fname,conn)) {
2864                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2865                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2866                 }
2867
2868                 if (INFO_LEVEL_IS_UNIX(info_level)) {
2869                         /* Always do lstat for UNIX calls. */
2870                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2871                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2872                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2873                         }
2874                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2875                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2876                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2877                 }
2878
2879                 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2880                 if (delete_pending) {
2881                         return ERROR_NT(NT_STATUS_DELETE_PENDING);
2882                 }
2883         }
2884
2885         nlink = sbuf.st_nlink;
2886
2887         if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2888                 /* NTFS does not seem to count ".." */
2889                 nlink -= 1;
2890         }
2891
2892         if ((nlink > 0) && delete_pending) {
2893                 nlink -= 1;
2894         }
2895
2896         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
2897                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
2898
2899         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2900                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2901
2902         p = strrchr_m(fname,'/'); 
2903         if (!p)
2904                 base_name = fname;
2905         else
2906                 base_name = p+1;
2907
2908         mode = dos_mode(conn,fname,&sbuf);
2909         if (!mode)
2910                 mode = FILE_ATTRIBUTE_NORMAL;
2911
2912         fullpathname = fname;
2913         if (!(mode & aDIR))
2914                 file_size = get_file_size(sbuf);
2915
2916         /* Pull any EA list from the data portion. */
2917         if (info_level == SMB_INFO_QUERY_EAS_FROM_LIST) {
2918                 uint32 ea_size;
2919
2920                 if (total_data < 4) {
2921                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2922                 }
2923                 ea_size = IVAL(pdata,0);
2924
2925                 if (total_data > 0 && ea_size != total_data) {
2926                         DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2927 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2928                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2929                 }
2930
2931                 if (!lp_ea_support(SNUM(conn))) {
2932                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
2933                 }
2934
2935                 if ((ea_ctx = talloc_init("ea_list")) == NULL) {
2936                         return ERROR_NT(NT_STATUS_NO_MEMORY);
2937                 }
2938
2939                 /* Pull out the list of names. */
2940                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2941                 if (!ea_list) {
2942                         talloc_destroy(ea_ctx);
2943                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2944                 }
2945         }
2946
2947         *pparams = SMB_REALLOC(*pparams,2);
2948         if (*pparams == NULL) {
2949                 talloc_destroy(ea_ctx);
2950                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2951         }
2952         params = *pparams;
2953         SSVAL(params,0,0);
2954         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
2955         *ppdata = SMB_REALLOC(*ppdata, data_size); 
2956         if (*ppdata == NULL ) {
2957                 talloc_destroy(ea_ctx);
2958                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2959         }
2960         pdata = *ppdata;
2961
2962         c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
2963
2964         allocation_size = get_allocation_size(conn,fsp,&sbuf);
2965
2966         if (fsp) {
2967                 if (fsp->pending_modtime) {
2968                         /* the pending modtime overrides the current modtime */
2969                         sbuf.st_mtime = fsp->pending_modtime;
2970                 }
2971         } else {
2972                 /* Do we have this path open ? */
2973                 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
2974                 if (fsp1 && fsp1->pending_modtime) {
2975                         /* the pending modtime overrides the current modtime */
2976                         sbuf.st_mtime = fsp1->pending_modtime;
2977                 }
2978                 if (fsp1 && fsp1->initial_allocation_size) {
2979                         allocation_size = get_allocation_size(conn, fsp1, &sbuf);
2980                 }
2981         }
2982
2983         if (lp_dos_filetime_resolution(SNUM(conn))) {
2984                 c_time &= ~1;
2985                 sbuf.st_atime &= ~1;
2986                 sbuf.st_ctime &= ~1;
2987                 sbuf.st_mtime &= ~1;
2988         }
2989
2990         /* NT expects the name to be in an exact form of the *full*
2991            filename. See the trans2 torture test */
2992         if (strequal(base_name,".")) {
2993                 pstrcpy(dos_fname, "\\");
2994         } else {
2995                 pstr_sprintf(dos_fname, "\\%s", fname);
2996                 string_replace(dos_fname, '/', '\\');
2997         }
2998
2999         switch (info_level) {
3000                 case SMB_INFO_STANDARD:
3001                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3002                         data_size = 22;
3003                         srv_put_dos_date2(pdata,l1_fdateCreation,c_time);
3004                         srv_put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
3005                         srv_put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
3006                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
3007                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3008                         SSVAL(pdata,l1_attrFile,mode);
3009                         break;
3010
3011                 case SMB_INFO_QUERY_EA_SIZE:
3012                 {
3013                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3014                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3015                         data_size = 26;
3016                         srv_put_dos_date2(pdata,0,c_time);
3017                         srv_put_dos_date2(pdata,4,sbuf.st_atime);
3018                         srv_put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
3019                         SIVAL(pdata,12,(uint32)file_size);
3020                         SIVAL(pdata,16,(uint32)allocation_size);
3021                         SSVAL(pdata,20,mode);
3022                         SIVAL(pdata,22,ea_size);
3023                         break;
3024                 }
3025
3026                 case SMB_INFO_IS_NAME_VALID:
3027                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3028                         if (tran_call == TRANSACT2_QFILEINFO) {
3029                                 /* os/2 needs this ? really ?*/      
3030                                 return ERROR_DOS(ERRDOS,ERRbadfunc); 
3031                         }
3032                         data_size = 0;
3033                         param_size = 0;
3034                         break;
3035                         
3036                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3037                 {
3038                         size_t total_ea_len = 0;
3039                         struct ea_list *ea_file_list = NULL;
3040
3041                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3042
3043                         ea_file_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3044                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3045
3046                         if (!ea_list || (total_ea_len > data_size)) {
3047                                 talloc_destroy(ea_ctx);
3048                                 data_size = 4;
3049                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3050                                 break;
3051                         }
3052
3053                         data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3054                         talloc_destroy(ea_ctx);
3055                         break;
3056                 }
3057
3058                 case SMB_INFO_QUERY_ALL_EAS:
3059                 {
3060                         /* We have data_size bytes to put EA's into. */
3061                         size_t total_ea_len = 0;
3062
3063                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3064
3065                         ea_ctx = talloc_init("ea_ctx");
3066                         if (!ea_ctx) {
3067                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3068                         }
3069
3070                         ea_list = get_ea_list_from_file(ea_ctx, conn, fsp, fname, &total_ea_len);
3071                         if (!ea_list || (total_ea_len > data_size)) {
3072                                 talloc_destroy(ea_ctx);
3073                                 data_size = 4;
3074                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3075                                 break;
3076                         }
3077
3078                         data_size = fill_ea_buffer(ea_ctx, pdata, data_size, conn, ea_list);
3079                         talloc_destroy(ea_ctx);
3080                         break;
3081                 }
3082
3083                 case SMB_FILE_BASIC_INFORMATION:
3084                 case SMB_QUERY_FILE_BASIC_INFO:
3085
3086                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3087                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3088                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3089                         } else {
3090                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3091                                 data_size = 40;
3092                                 SIVAL(pdata,36,0);
3093                         }
3094                         put_long_date(pdata,c_time);
3095                         put_long_date(pdata+8,sbuf.st_atime);
3096                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3097                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3098                         SIVAL(pdata,32,mode);
3099
3100                         DEBUG(5,("SMB_QFBI - "));
3101                         {
3102                                 time_t create_time = c_time;
3103                                 DEBUG(5,("create: %s ", ctime(&create_time)));
3104                         }
3105                         DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3106                         DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3107                         DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3108                         DEBUG(5,("mode: %x\n", mode));
3109                         break;
3110
3111                 case SMB_FILE_STANDARD_INFORMATION:
3112                 case SMB_QUERY_FILE_STANDARD_INFO:
3113
3114                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3115                         data_size = 24;
3116                         SOFF_T(pdata,0,allocation_size);
3117                         SOFF_T(pdata,8,file_size);
3118                         SIVAL(pdata,16,nlink);
3119                         SCVAL(pdata,20,delete_pending?1:0);
3120                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3121                         SSVAL(pdata,22,0); /* Padding. */
3122                         break;
3123
3124                 case SMB_FILE_EA_INFORMATION:
3125                 case SMB_QUERY_FILE_EA_INFO:
3126                 {
3127                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3128                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3129                         data_size = 4;
3130                         SIVAL(pdata,0,ea_size);
3131                         break;
3132                 }
3133
3134                 /* Get the 8.3 name - used if NT SMB was negotiated. */
3135                 case SMB_QUERY_FILE_ALT_NAME_INFO:
3136                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3137                 {
3138                         pstring short_name;
3139
3140                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3141                         pstrcpy(short_name,base_name);
3142                         /* Mangle if not already 8.3 */
3143                         if(!mangle_is_8_3(short_name, True, SNUM(conn))) {
3144                                 mangle_map(short_name,True,True,SNUM(conn));
3145                         }
3146                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3147                         data_size = 4 + len;
3148                         SIVAL(pdata,0,len);
3149                         break;
3150                 }
3151
3152                 case SMB_QUERY_FILE_NAME_INFO:
3153                         /*
3154                           this must be *exactly* right for ACLs on mapped drives to work
3155                          */
3156                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3157                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3158                         data_size = 4 + len;
3159                         SIVAL(pdata,0,len);
3160                         break;
3161
3162                 case SMB_FILE_ALLOCATION_INFORMATION:
3163                 case SMB_QUERY_FILE_ALLOCATION_INFO:
3164                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3165                         data_size = 8;
3166                         SOFF_T(pdata,0,allocation_size);
3167                         break;
3168
3169                 case SMB_FILE_END_OF_FILE_INFORMATION:
3170                 case SMB_QUERY_FILE_END_OF_FILEINFO:
3171                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3172                         data_size = 8;
3173                         SOFF_T(pdata,0,file_size);
3174                         break;
3175
3176                 case SMB_QUERY_FILE_ALL_INFO:
3177                 case SMB_FILE_ALL_INFORMATION:
3178                 {
3179                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3180                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3181                         put_long_date(pdata,c_time);
3182                         put_long_date(pdata+8,sbuf.st_atime);
3183                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3184                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3185                         SIVAL(pdata,32,mode);
3186                         SIVAL(pdata,36,0); /* padding. */
3187                         pdata += 40;
3188                         SOFF_T(pdata,0,allocation_size);
3189                         SOFF_T(pdata,8,file_size);
3190                         SIVAL(pdata,16,nlink);
3191                         SCVAL(pdata,20,delete_pending);
3192                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3193                         SSVAL(pdata,22,0);
3194                         pdata += 24;
3195                         SIVAL(pdata,0,ea_size);
3196                         pdata += 4; /* EA info */
3197                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3198                         SIVAL(pdata,0,len);
3199                         pdata += 4 + len;
3200                         data_size = PTR_DIFF(pdata,(*ppdata));
3201                         break;
3202                 }
3203                 case SMB_FILE_INTERNAL_INFORMATION:
3204                         /* This should be an index number - looks like
3205                            dev/ino to me :-) 
3206
3207                            I think this causes us to fail the IFSKIT
3208                            BasicFileInformationTest. -tpot */
3209
3210                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3211                         SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3212                         SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3213                         data_size = 8;
3214                         break;
3215
3216                 case SMB_FILE_ACCESS_INFORMATION:
3217                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3218                         SIVAL(pdata,0,access_mask);
3219                         data_size = 4;
3220                         break;
3221
3222                 case SMB_FILE_NAME_INFORMATION:
3223                         /* Pathname with leading '\'. */
3224                         {
3225                                 size_t byte_len;
3226                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3227                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3228                                 SIVAL(pdata,0,byte_len);
3229                                 data_size = 4 + byte_len;
3230                                 break;
3231                         }
3232
3233                 case SMB_FILE_DISPOSITION_INFORMATION:
3234                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3235                         data_size = 1;
3236                         SCVAL(pdata,0,delete_pending);
3237                         break;
3238
3239                 case SMB_FILE_POSITION_INFORMATION:
3240                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3241                         data_size = 8;
3242                         SOFF_T(pdata,0,pos);
3243                         break;
3244
3245                 case SMB_FILE_MODE_INFORMATION:
3246                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3247                         SIVAL(pdata,0,mode);
3248                         data_size = 4;
3249                         break;
3250
3251                 case SMB_FILE_ALIGNMENT_INFORMATION:
3252                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3253                         SIVAL(pdata,0,0); /* No alignment needed. */
3254                         data_size = 4;
3255                         break;
3256
3257 #if 0
3258                 /*
3259                  * NT4 server just returns "invalid query" to this - if we try to answer
3260                  * it then NTws gets a BSOD! (tridge).
3261                  * W2K seems to want this. JRA.
3262                  */
3263                 case SMB_QUERY_FILE_STREAM_INFO:
3264 #endif
3265                 case SMB_FILE_STREAM_INFORMATION:
3266                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3267                         if (mode & aDIR) {
3268                                 data_size = 0;
3269                         } else {
3270                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3271                                 SIVAL(pdata,0,0); /* ??? */
3272                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3273                                 SOFF_T(pdata,8,file_size);
3274                                 SIVAL(pdata,16,allocation_size);
3275                                 SIVAL(pdata,20,0); /* ??? */
3276                                 data_size = 24 + byte_len;
3277                         }
3278                         break;
3279
3280                 case SMB_QUERY_COMPRESSION_INFO:
3281                 case SMB_FILE_COMPRESSION_INFORMATION:
3282                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3283                         SOFF_T(pdata,0,file_size);
3284                         SIVAL(pdata,8,0); /* ??? */
3285                         SIVAL(pdata,12,0); /* ??? */
3286                         data_size = 16;
3287                         break;
3288
3289                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3290                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3291                         put_long_date(pdata,c_time);
3292                         put_long_date(pdata+8,sbuf.st_atime);
3293                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3294                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3295                         SIVAL(pdata,32,allocation_size);
3296                         SOFF_T(pdata,40,file_size);
3297                         SIVAL(pdata,48,mode);
3298                         SIVAL(pdata,52,0); /* ??? */
3299                         data_size = 56;
3300                         break;
3301
3302                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3303                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3304                         SIVAL(pdata,0,mode);
3305                         SIVAL(pdata,4,0);
3306                         data_size = 8;
3307                         break;
3308
3309                 /*
3310                  * CIFS UNIX Extensions.
3311                  */
3312
3313                 case SMB_QUERY_FILE_UNIX_BASIC:
3314
3315                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3316                         DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3317
3318                         SOFF_T(pdata,0,get_file_size(sbuf));             /* File size 64 Bit */
3319                         pdata += 8;
3320
3321                         SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3322                         pdata += 8;
3323
3324                         put_long_date(pdata,sbuf.st_ctime);       /* Creation Time 64 Bit */
3325                         put_long_date(pdata+8,sbuf.st_atime);     /* Last access time 64 Bit */
3326                         put_long_date(pdata+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
3327                         pdata += 24;
3328
3329                         SIVAL(pdata,0,sbuf.st_uid);               /* user id for the owner */
3330                         SIVAL(pdata,4,0);
3331                         pdata += 8;
3332
3333                         SIVAL(pdata,0,sbuf.st_gid);               /* group id of owner */
3334                         SIVAL(pdata,4,0);
3335                         pdata += 8;
3336
3337                         SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3338                         pdata += 4;
3339
3340                         SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
3341                         SIVAL(pdata,4,0);
3342                         pdata += 8;
3343
3344                         SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
3345                         SIVAL(pdata,4,0);
3346                         pdata += 8;
3347
3348                         SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
3349                         pdata += 8;
3350                                 
3351                         SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
3352                         SIVAL(pdata,4,0);
3353                         pdata += 8;
3354
3355                         SIVAL(pdata,0,sbuf.st_nlink);             /* number of hard links */
3356                         SIVAL(pdata,4,0);
3357                         pdata += 8+1;
3358                         data_size = PTR_DIFF(pdata,(*ppdata));
3359
3360                         {
3361                                 int i;
3362                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC"));
3363
3364                                 for (i=0; i<100; i++)
3365                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3366                                 DEBUG(4,("\n"));
3367                         }
3368
3369                         break;
3370
3371                 case SMB_QUERY_FILE_UNIX_LINK:
3372                         {
3373                                 pstring buffer;
3374
3375                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3376 #ifdef S_ISLNK
3377                                 if(!S_ISLNK(sbuf.st_mode))
3378                                         return(UNIXERROR(ERRSRV,ERRbadlink));
3379 #else
3380                                 return(UNIXERROR(ERRDOS,ERRbadlink));
3381 #endif
3382                                 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
3383                                 if (len == -1)
3384                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3385                                 buffer[len] = 0;
3386                                 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3387                                 pdata += len;
3388                                 data_size = PTR_DIFF(pdata,(*ppdata));
3389
3390                                 break;
3391                         }
3392
3393 #if defined(HAVE_POSIX_ACLS)
3394                 case SMB_QUERY_POSIX_ACL:
3395                         {
3396                                 SMB_ACL_T file_acl = NULL;
3397                                 SMB_ACL_T def_acl = NULL;
3398                                 uint16 num_file_acls = 0;
3399                                 uint16 num_def_acls = 0;
3400
3401                                 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3402                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3403                                 } else {
3404                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3405                                 }
3406
3407                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3408                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3409                                                 fname ));
3410                                         return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3411                                 }
3412
3413                                 if (S_ISDIR(sbuf.st_mode)) {
3414                                         if (fsp && fsp->is_directory) {
3415                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3416                                         } else {
3417                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3418                                         }
3419                                         def_acl = free_empty_sys_acl(conn, def_acl);
3420                                 }
3421
3422                                 num_file_acls = count_acl_entries(conn, file_acl);
3423                                 num_def_acls = count_acl_entries(conn, def_acl);
3424
3425                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3426                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3427                                                 data_size,
3428                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3429                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
3430                                         if (file_acl) {
3431                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3432                                         }
3433                                         if (def_acl) {
3434                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3435                                         }
3436                                         return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3437                                 }
3438
3439                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3440                                 SSVAL(pdata,2,num_file_acls);
3441                                 SSVAL(pdata,4,num_def_acls);
3442                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3443                                         if (file_acl) {
3444                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3445                                         }
3446                                         if (def_acl) {
3447                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3448                                         }
3449                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3450                                 }
3451                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3452                                         if (file_acl) {
3453                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3454                                         }
3455                                         if (def_acl) {
3456                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3457                                         }
3458                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3459                                 }
3460
3461                                 if (file_acl) {
3462                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3463                                 }
3464                                 if (def_acl) {
3465                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3466                                 }
3467                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3468                                 break;
3469                         }
3470 #endif
3471
3472                 default:
3473                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
3474         }
3475
3476         send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3477
3478         return(-1);
3479 }
3480
3481 /****************************************************************************
3482  Set a hard link (called by UNIX extensions and by NT rename with HARD link
3483  code.
3484 ****************************************************************************/
3485
3486 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3487 {
3488         BOOL bad_path_oldname = False;
3489         BOOL bad_path_newname = False;
3490         SMB_STRUCT_STAT sbuf1, sbuf2;
3491         pstring last_component_oldname;
3492         pstring last_component_newname;
3493         NTSTATUS status = NT_STATUS_OK;
3494
3495         ZERO_STRUCT(sbuf1);
3496         ZERO_STRUCT(sbuf2);
3497
3498         /* No wildcards. */
3499         if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3500                 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3501         }
3502
3503         unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3504         if (bad_path_oldname) {
3505                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3506         }
3507
3508         /* Quick check for "." and ".." */
3509         if (last_component_oldname[0] == '.') {
3510                 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3511                         return NT_STATUS_OBJECT_NAME_INVALID;
3512                 }
3513         }
3514
3515         /* source must already exist. */
3516         if (!VALID_STAT(sbuf1)) {
3517                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3518         }
3519
3520         if (!check_name(oldname,conn)) {
3521                 return NT_STATUS_ACCESS_DENIED;
3522         }
3523
3524         unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3525         if (bad_path_newname) {
3526                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3527         }
3528
3529         /* Quick check for "." and ".." */
3530         if (last_component_newname[0] == '.') {
3531                 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3532                         return NT_STATUS_OBJECT_NAME_INVALID;
3533                 }
3534         }
3535
3536         /* Disallow if newname already exists. */
3537         if (VALID_STAT(sbuf2)) {
3538                 return NT_STATUS_OBJECT_NAME_COLLISION;
3539         }
3540
3541         if (!check_name(newname,conn)) {
3542                 return NT_STATUS_ACCESS_DENIED;
3543         }
3544
3545         /* No links from a directory. */
3546         if (S_ISDIR(sbuf1.st_mode)) {
3547                 return NT_STATUS_FILE_IS_A_DIRECTORY;
3548         }
3549
3550         /* Ensure this is within the share. */
3551         if (!reduce_name(conn, oldname) != 0)
3552                 return NT_STATUS_ACCESS_DENIED;
3553
3554         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3555
3556         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3557                 status = map_nt_error_from_unix(errno);
3558                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3559                                 nt_errstr(status), newname, oldname));
3560         }
3561
3562         return status;
3563 }
3564
3565 /****************************************************************************
3566  Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3567 ****************************************************************************/
3568
3569 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3570                                         unsigned int tran_call,
3571                                         char **pparams, int total_params, char **ppdata, int total_data,
3572                                         unsigned int max_data_bytes)
3573 {
3574         char *params = *pparams;
3575         char *pdata = *ppdata;
3576         uint16 info_level;
3577         int dosmode=0;
3578         SMB_OFF_T size=0;
3579         struct utimbuf tvs;
3580         SMB_STRUCT_STAT sbuf;
3581         pstring fname;
3582         int fd = -1;
3583         BOOL bad_path = False;
3584         files_struct *fsp = NULL;
3585         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3586         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3587         mode_t unixmode = 0;
3588         NTSTATUS status = NT_STATUS_OK;
3589
3590         if (!params)
3591                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3592
3593         ZERO_STRUCT(sbuf);
3594         ZERO_STRUCT(tvs);
3595
3596         if (tran_call == TRANSACT2_SETFILEINFO) {
3597                 if (total_params < 4) {
3598                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3599                 }
3600
3601                 fsp = file_fsp(params,0);
3602                 info_level = SVAL(params,2);    
3603
3604                 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3605                         /*
3606                          * This is actually a SETFILEINFO on a directory
3607                          * handle (returned from an NT SMB). NT5.0 seems
3608                          * to do this call. JRA.
3609                          */
3610                         pstrcpy(fname, fsp->fsp_name);
3611                         if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3612                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3613                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3614                         }
3615                 } else if (fsp && fsp->print_file) {
3616                         /*
3617                          * Doing a DELETE_ON_CLOSE should cancel a print job.
3618                          */
3619                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3620                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3621
3622                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3623         
3624                                 SSVAL(params,0,0);
3625                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3626                                 return(-1);
3627                         } else
3628                                 return (UNIXERROR(ERRDOS,ERRbadpath));
3629             } else {
3630                         /*
3631                          * Original code - this is an open file.
3632                          */
3633                         CHECK_FSP(fsp,conn);
3634
3635                         pstrcpy(fname, fsp->fsp_name);
3636                         fd = fsp->fh->fd;
3637
3638                         if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3639                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3640                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3641                         }
3642                 }
3643         } else {
3644                 /* set path info */
3645                 if (total_params < 6) {
3646                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3647                 }
3648
3649                 info_level = SVAL(params,0);    
3650                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
3651                 if (!NT_STATUS_IS_OK(status)) {
3652                         return ERROR_NT(status);
3653                 }
3654                 unix_convert(fname,conn,0,&bad_path,&sbuf);
3655                 if (bad_path) {
3656                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3657                 }
3658
3659                 /*
3660                  * For CIFS UNIX extensions the target name may not exist.
3661                  */
3662
3663                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3664                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3665                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3666                 }    
3667
3668                 if(!check_name(fname, conn)) {
3669                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3670                 }
3671
3672         }
3673
3674         if (!CAN_WRITE(conn))
3675                 return ERROR_DOS(ERRSRV,ERRaccess);
3676
3677         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions())
3678                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3679
3680         if (VALID_STAT(sbuf))
3681                 unixmode = sbuf.st_mode;
3682
3683         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3684                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3685
3686         /* Realloc the parameter size */
3687         *pparams = SMB_REALLOC(*pparams,2);
3688         if (*pparams == NULL) {
3689                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3690         }
3691         params = *pparams;
3692
3693         SSVAL(params,0,0);
3694
3695         if (fsp && fsp->pending_modtime) {
3696                 /* the pending modtime overrides the current modtime */
3697                 sbuf.st_mtime = fsp->pending_modtime;
3698         }
3699
3700         size = get_file_size(sbuf);
3701         tvs.modtime = sbuf.st_mtime;
3702         tvs.actime = sbuf.st_atime;
3703         dosmode = dos_mode(conn,fname,&sbuf);
3704         unixmode = sbuf.st_mode;
3705
3706         set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3707         set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3708
3709         switch (info_level) {
3710                 case SMB_INFO_STANDARD:
3711                 {
3712                         if (total_data < 12) {
3713                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3714                         }
3715
3716                         /* access time */
3717                         tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
3718                         /* write time */
3719                         tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
3720                         break;
3721                 }
3722
3723                 case SMB_INFO_SET_EA:
3724                 {
3725                         struct ea_list *ea_list = NULL;
3726                         TALLOC_CTX *ctx = NULL;
3727
3728                         if (total_data < 10) {
3729
3730                                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3731                                    length. They seem to have no effect. Bug #3212. JRA */
3732
3733                                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3734                                         /* We're done. We only get EA info in this call. */
3735                                         SSVAL(params,0,0);
3736                                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3737                                         return(-1);
3738                                 }
3739
3740                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3741                         }
3742
3743                         if (IVAL(pdata,0) > total_data) {
3744                                 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3745                                         IVAL(pdata,0), (unsigned int)total_data));
3746                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3747                         }
3748
3749                         ctx = talloc_init("SMB_INFO_SET_EA");
3750                         if (!ctx) {
3751                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3752                         }
3753                         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3754                         if (!ea_list) {
3755                                 talloc_destroy(ctx);
3756                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3757                         }
3758                         status = set_ea(conn, fsp, fname, ea_list);
3759                         talloc_destroy(ctx);
3760
3761                         if (!NT_STATUS_IS_OK(status)) {
3762                                 return ERROR_NT(status);
3763                         }
3764
3765                         /* We're done. We only get EA info in this call. */
3766                         SSVAL(params,0,0);
3767                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3768                         return(-1);
3769                 }
3770
3771 #if 0
3772                 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3773                 /* XXXX um, i don't think this is right.
3774                         it's also not in the cifs6.txt spec.
3775                 */
3776                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3777                         if (total_data < 28)
3778                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3779
3780                         tvs.actime = make_unix_date2(pdata+8);
3781                         tvs.modtime = make_unix_date2(pdata+12);
3782                         size = IVAL(pdata,16);
3783                         dosmode = IVAL(pdata,24);
3784                         break;
3785
3786                 /* XXXX nor this.  not in cifs6.txt, either. */
3787                 case SMB_INFO_QUERY_ALL_EAS:
3788                         if (total_data < 28)
3789                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3790
3791                         tvs.actime = make_unix_date2(pdata+8);
3792                         tvs.modtime = make_unix_date2(pdata+12);
3793                         size = IVAL(pdata,16);
3794                         dosmode = IVAL(pdata,24);
3795                         break;
3796 #endif
3797
3798                 case SMB_SET_FILE_BASIC_INFO:
3799                 case SMB_FILE_BASIC_INFORMATION:
3800                 {
3801                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3802                         time_t write_time;
3803                         time_t changed_time;
3804
3805                         if (total_data < 36) {
3806                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3807                         }
3808
3809                         /* Ignore create time at offset pdata. */
3810
3811                         /* access time */
3812                         tvs.actime = interpret_long_date(pdata+8);
3813
3814                         write_time = interpret_long_date(pdata+16);
3815                         changed_time = interpret_long_date(pdata+24);
3816
3817                         tvs.modtime = MIN(write_time, changed_time);
3818
3819                         if (write_time > tvs.modtime && write_time != (time_t)-1) {
3820                                 tvs.modtime = write_time;
3821                         }
3822                         /* Prefer a defined time to an undefined one. */
3823                         if (null_mtime(tvs.modtime)) {
3824                                 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3825                         }
3826
3827                         /* attributes */
3828                         dosmode = IVAL(pdata,32);
3829                         break;
3830                 }
3831
3832                 case SMB_FILE_ALLOCATION_INFORMATION:
3833                 case SMB_SET_FILE_ALLOCATION_INFO:
3834                 {
3835                         int ret = -1;
3836                         SMB_BIG_UINT allocation_size;
3837
3838                         if (total_data < 8) {
3839                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3840                         }
3841
3842                         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
3843 #ifdef LARGE_SMB_OFF_T
3844                         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3845 #else /* LARGE_SMB_OFF_T */
3846                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3847                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3848 #endif /* LARGE_SMB_OFF_T */
3849                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
3850                                         fname, (double)allocation_size ));
3851
3852                         if (allocation_size) {
3853                                 allocation_size = smb_roundup(conn, allocation_size);
3854                         }
3855
3856                         if(allocation_size != get_file_size(sbuf)) {
3857                                 SMB_STRUCT_STAT new_sbuf;
3858  
3859                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
3860                                         fname, (double)allocation_size ));
3861  
3862                                 if (fd == -1) {
3863                                         files_struct *new_fsp = NULL;
3864  
3865                                         new_fsp = open_file_ntcreate(conn, fname, &sbuf,
3866                                                                         FILE_WRITE_DATA,
3867                                                                         FILE_SHARE_READ|FILE_SHARE_WRITE,
3868                                                                         FILE_OPEN,
3869                                                                         0,
3870                                                                         FILE_ATTRIBUTE_NORMAL,
3871                                                                         INTERNAL_OPEN_ONLY,
3872                                                                         NULL);
3873  
3874                                         if (new_fsp == NULL) {
3875                                                 return(UNIXERROR(ERRDOS,ERRbadpath));
3876                                         }
3877                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
3878                                         if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
3879                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3880                                                                         new_fsp->fnum, strerror(errno)));
3881                                                 ret = -1;
3882                                         }
3883                                         close_file(new_fsp,NORMAL_CLOSE);
3884                                 } else {
3885                                         ret = vfs_allocate_file_space(fsp, allocation_size);
3886                                         if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
3887                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
3888                                                                         fsp->fnum, strerror(errno)));
3889                                                 ret = -1;
3890                                         }
3891                                 }
3892                                 if (ret == -1)
3893                                         return ERROR_NT(NT_STATUS_DISK_FULL);
3894
3895                                 /* Allocate can truncate size... */
3896                                 size = get_file_size(new_sbuf);
3897                         }
3898
3899                         break;
3900                 }
3901
3902                 case SMB_FILE_END_OF_FILE_INFORMATION:
3903                 case SMB_SET_FILE_END_OF_FILE_INFO:
3904                 {
3905                         if (total_data < 8) {
3906                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3907                         }
3908
3909                         size = IVAL(pdata,0);
3910 #ifdef LARGE_SMB_OFF_T
3911                         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
3912 #else /* LARGE_SMB_OFF_T */
3913                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3914                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3915 #endif /* LARGE_SMB_OFF_T */
3916                         DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
3917                         break;
3918                 }
3919
3920                 case SMB_FILE_DISPOSITION_INFORMATION:
3921                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
3922                 {
3923                         BOOL delete_on_close;
3924
3925                         if (total_data < 1) {
3926                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3927                         }
3928
3929                         delete_on_close = (CVAL(pdata,0) ? True : False);
3930
3931                         /* Just ignore this set on a path. */
3932                         if (tran_call != TRANSACT2_SETFILEINFO)
3933                                 break;
3934
3935                         if (fsp == NULL)
3936                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3937
3938                         status = can_set_delete_on_close(fsp, delete_on_close,
3939                                                          dosmode);
3940  
3941                         if (!NT_STATUS_IS_OK(status)) {
3942                                 return ERROR_NT(status);
3943                         }
3944
3945                         /* The set is across all open files on this dev/inode pair. */
3946                         if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
3947                                 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3948                         }
3949
3950                         SSVAL(params,0,0);
3951                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3952                         return(-1);
3953                 }
3954
3955                 case SMB_FILE_POSITION_INFORMATION:
3956                 {
3957                         SMB_BIG_UINT position_information;
3958
3959                         if (total_data < 8) {
3960                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3961                         }
3962
3963                         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3964 #ifdef LARGE_SMB_OFF_T
3965                         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3966 #else /* LARGE_SMB_OFF_T */
3967                         if (IVAL(pdata,4) != 0) /* more than 32 bits? */
3968                                 return ERROR_DOS(ERRDOS,ERRunknownlevel);
3969 #endif /* LARGE_SMB_OFF_T */
3970                         DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
3971                                         fname, (double)position_information ));
3972                         if (fsp) {
3973                                 fsp->fh->position_information = position_information;
3974                         }
3975
3976                         /* We're done. We only get position info in this call. */
3977                         SSVAL(params,0,0);
3978                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3979                         return(-1);
3980                 }
3981
3982                 /* From tridge Samba4 : 
3983                  * MODE_INFORMATION in setfileinfo (I have no
3984                  * idea what "mode information" on a file is - it takes a value of 0,
3985                  * 2, 4 or 6. What could it be?).
3986                  */
3987
3988                 case SMB_FILE_MODE_INFORMATION:
3989                 {
3990                         uint32 mode;
3991
3992                         if (total_data < 4) {
3993                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3994                         }
3995                         mode = IVAL(pdata,0);
3996                         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
3997                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3998                         }
3999
4000                         /* We're done. We only get mode info in this call. */
4001                         SSVAL(params,0,0);
4002                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4003                         return(-1);
4004                 }
4005
4006                 /*
4007                  * CIFS UNIX extensions.
4008                  */
4009
4010                 case SMB_SET_FILE_UNIX_BASIC:
4011                 {
4012                         uint32 raw_unixmode;
4013
4014                         if (total_data < 100) {
4015                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4016                         }
4017
4018                         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4019                            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4020                                 size=IVAL(pdata,0); /* first 8 Bytes are size */
4021 #ifdef LARGE_SMB_OFF_T
4022                                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4023 #else /* LARGE_SMB_OFF_T */
4024                                 if (IVAL(pdata,4) != 0) /* more than 32 bits? */
4025                                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
4026 #endif /* LARGE_SMB_OFF_T */
4027                         }
4028                         pdata+=24;          /* ctime & st_blocks are not changed */
4029                         tvs.actime = interpret_long_date(pdata); /* access_time */
4030                         tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4031                         pdata+=16;
4032                         set_owner = (uid_t)IVAL(pdata,0);
4033                         pdata += 8;
4034                         set_grp = (gid_t)IVAL(pdata,0);
4035                         pdata += 8;
4036                         raw_unixmode = IVAL(pdata,28);
4037                         unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4038                         dosmode = 0; /* Ensure dos mode change doesn't override this. */
4039
4040                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4041 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4042                                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4043
4044                         if (!VALID_STAT(sbuf)) {
4045
4046                                 /*
4047                                  * The only valid use of this is to create character and block
4048                                  * devices, and named pipes. This is deprecated (IMHO) and 
4049                                  * a new info level should be used for mknod. JRA.
4050                                  */
4051
4052                                 uint32 file_type = IVAL(pdata,0);
4053 #if defined(HAVE_MAKEDEV)
4054                                 uint32 dev_major = IVAL(pdata,4);
4055                                 uint32 dev_minor = IVAL(pdata,12);
4056 #endif
4057
4058                                 uid_t myuid = geteuid();
4059                                 gid_t mygid = getegid();
4060                                 SMB_DEV_T dev = (SMB_DEV_T)0;
4061
4062                                 if (tran_call == TRANSACT2_SETFILEINFO)
4063                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
4064
4065                                 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4066                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4067                                 }
4068
4069 #if defined(HAVE_MAKEDEV)
4070                                 dev = makedev(dev_major, dev_minor);
4071 #endif
4072
4073                                 /* We can only create as the owner/group we are. */
4074
4075                                 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4076                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
4077                                 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4078                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
4079
4080                                 switch (file_type) {
4081 #if defined(S_IFIFO)
4082                                         case UNIX_TYPE_FIFO:
4083                                                 unixmode |= S_IFIFO;
4084                                                 break;
4085 #endif
4086 #if defined(S_IFSOCK)
4087                                         case UNIX_TYPE_SOCKET:
4088                                                 unixmode |= S_IFSOCK;
4089                                                 break;
4090 #endif
4091 #if defined(S_IFCHR)
4092                                         case UNIX_TYPE_CHARDEV:
4093                                                 unixmode |= S_IFCHR;
4094                                                 break;
4095 #endif
4096 #if defined(S_IFBLK)
4097                                         case UNIX_TYPE_BLKDEV:
4098                                                 unixmode |= S_IFBLK;
4099                                                 break;
4100 #endif
4101                                         default:
4102                                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4103                                 }
4104
4105                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4106 0%o for file %s\n", (double)dev, unixmode, fname ));
4107
4108                                 /* Ok - do the mknod. */
4109                                 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4110                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4111
4112                                 inherit_access_acl(conn, fname, unixmode);
4113
4114                                 SSVAL(params,0,0);
4115                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4116                                 return(-1);
4117                         }
4118
4119                         /*
4120                          * Deal with the UNIX specific mode set.
4121                          */
4122
4123                         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4124                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4125                                         (unsigned int)unixmode, fname ));
4126                                 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4127                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4128                         }
4129
4130                         /*
4131                          * Deal with the UNIX specific uid set.
4132                          */
4133
4134                         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4135                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4136                                         (unsigned int)set_owner, fname ));
4137                                 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4138                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4139                         }
4140
4141                         /*
4142                          * Deal with the UNIX specific gid set.
4143                          */
4144
4145                         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4146                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4147                                         (unsigned int)set_owner, fname ));
4148                                 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4149                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4150                         }
4151                         break;
4152                 }
4153
4154                 case SMB_SET_FILE_UNIX_LINK:
4155                 {
4156                         pstring link_target;
4157                         char *newname = fname;
4158
4159                         /* Set a symbolic link. */
4160                         /* Don't allow this if follow links is false. */
4161
4162                         if (!lp_symlinks(SNUM(conn)))
4163                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4164
4165                         srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4166
4167                         /* !widelinks forces the target path to be within the share. */
4168                         /* This means we can interpret the target as a pathname. */
4169                         if (!lp_widelinks(SNUM(conn))) {
4170                                 pstring rel_name;
4171                                 char *last_dirp = NULL;
4172
4173                                 unix_format(link_target);
4174                                 if (*link_target == '/') {
4175                                         /* No absolute paths allowed. */
4176                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4177                                 }
4178                                 pstrcpy(rel_name, newname);
4179                                 last_dirp = strrchr_m(rel_name, '/');
4180                                 if (last_dirp) {
4181                                         last_dirp[1] = '\0';
4182                                 } else {
4183                                         pstrcpy(rel_name, "./");
4184                                 }
4185                                 pstrcat(rel_name, link_target);
4186
4187                                 if (!check_name(rel_name, conn)) {
4188                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4189                                 }
4190                         }
4191
4192                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4193                                 fname, link_target ));
4194
4195                         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4196                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4197                         SSVAL(params,0,0);
4198                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4199                         return(-1);
4200                 }
4201
4202                 case SMB_SET_FILE_UNIX_HLINK:
4203                 {
4204                         pstring oldname;
4205                         char *newname = fname;
4206
4207                         /* Set a hard link. */
4208                         srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
4209                         if (!NT_STATUS_IS_OK(status)) {
4210                                 return ERROR_NT(status);
4211                         }
4212
4213                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4214                                 fname, oldname));
4215
4216                         status = hardlink_internals(conn, oldname, newname);
4217                         if (!NT_STATUS_IS_OK(status)) {
4218                                 return ERROR_NT(status);
4219                         }
4220
4221                         SSVAL(params,0,0);
4222                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4223                         return(-1);
4224                 }
4225
4226                 case SMB_FILE_RENAME_INFORMATION:
4227                 {
4228                         BOOL overwrite;
4229                         uint32 root_fid;
4230                         uint32 len;
4231                         pstring newname;
4232                         pstring base_name;
4233                         char *p;
4234
4235                         if (total_data < 12) {
4236                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4237                         }
4238
4239                         overwrite = (CVAL(pdata,0) ? True : False);
4240                         root_fid = IVAL(pdata,4);
4241                         len = IVAL(pdata,8);
4242                         srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4243                         if (!NT_STATUS_IS_OK(status)) {
4244                                 return ERROR_NT(status);
4245                         }
4246
4247                         /* Check the new name has no '/' characters. */
4248                         if (strchr_m(newname, '/'))
4249                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4250
4251                         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4252
4253                         /* Create the base directory. */
4254                         pstrcpy(base_name, fname);
4255                         p = strrchr_m(base_name, '/');
4256                         if (p)
4257                                 *p = '\0';
4258                         /* Append the new name. */
4259                         pstrcat(base_name, "/");
4260                         pstrcat(base_name, newname);
4261
4262                         if (fsp) {
4263                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4264                                         fsp->fnum, fsp->fsp_name, base_name ));
4265                                 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4266                         } else {
4267                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4268                                         fname, newname ));
4269                                 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4270                         }
4271                         if (!NT_STATUS_IS_OK(status)) {
4272                                 return ERROR_NT(status);
4273                         }
4274                         process_pending_change_notify_queue((time_t)0);
4275                         SSVAL(params,0,0);
4276                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4277                         return(-1);
4278                 }
4279
4280 #if defined(HAVE_POSIX_ACLS)
4281                 case SMB_SET_POSIX_ACL:
4282                 {
4283                         uint16 posix_acl_version;
4284                         uint16 num_file_acls;
4285                         uint16 num_def_acls;
4286                         BOOL valid_file_acls = True;
4287                         BOOL valid_def_acls = True;
4288
4289                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4290                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4291                         }
4292                         posix_acl_version = SVAL(pdata,0);
4293                         num_file_acls = SVAL(pdata,2);
4294                         num_def_acls = SVAL(pdata,4);
4295
4296                         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4297                                 valid_file_acls = False;
4298                                 num_file_acls = 0;
4299                         }
4300
4301                         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4302                                 valid_def_acls = False;
4303                                 num_def_acls = 0;
4304                         }
4305
4306                         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4307                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4308                         }
4309
4310                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4311                                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4312                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4313                         }
4314
4315                         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4316                                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4317                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4318                         }
4319
4320                         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4321                                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
4322                                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4323                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4324                         }
4325
4326                         SSVAL(params,0,0);
4327                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4328                         return(-1);
4329                 }
4330 #endif
4331
4332                 default:
4333                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
4334         }
4335
4336         /* get some defaults (no modifications) if any info is zero or -1. */
4337         if (null_mtime(tvs.actime)) {
4338                 tvs.actime = sbuf.st_atime;
4339         }
4340
4341         if (null_mtime(tvs.modtime)) {
4342                 tvs.modtime = sbuf.st_mtime;
4343         }
4344
4345         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4346         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4347         DEBUG(6,("size: %.0f ", (double)size));
4348
4349         if (dosmode) {
4350                 if (S_ISDIR(sbuf.st_mode))
4351                         dosmode |= aDIR;
4352                 else
4353                         dosmode &= ~aDIR;
4354         }
4355
4356         DEBUG(6,("dosmode: %x\n"  , dosmode));
4357
4358         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4359                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4360                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4361                 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4362
4363                 /*
4364                  * Only do this test if we are not explicitly
4365                  * changing the size of a file.
4366                  */
4367                 if (!size)
4368                         size = get_file_size(sbuf);
4369         }
4370
4371         /*
4372          * Try and set the times, size and mode of this file -
4373          * if they are different from the current values
4374          */
4375
4376         /* check the mode isn't different, before changing it */
4377         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4378
4379                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4380
4381                 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4382                         DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4383                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4384                 }
4385         }
4386
4387         /* Now the size. */
4388         if (size != get_file_size(sbuf)) {
4389
4390                 int ret;
4391
4392                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4393                         fname, (double)size ));
4394
4395                 if (fd == -1) {
4396                         files_struct *new_fsp = NULL;
4397
4398                         new_fsp = open_file_ntcreate(conn, fname, &sbuf,
4399                                                 FILE_WRITE_DATA,
4400                                                 FILE_SHARE_READ|FILE_SHARE_WRITE,
4401                                                 FILE_OPEN,
4402                                                 0,
4403                                                 FILE_ATTRIBUTE_NORMAL,
4404                                                 INTERNAL_OPEN_ONLY,
4405                                                 NULL);
4406         
4407                         if (new_fsp == NULL) {
4408                                 return(UNIXERROR(ERRDOS,ERRbadpath));
4409                         }
4410                         ret = vfs_set_filelen(new_fsp, size);
4411                         close_file(new_fsp,NORMAL_CLOSE);
4412                 } else {
4413                         ret = vfs_set_filelen(fsp, size);
4414                 }
4415
4416                 if (ret == -1) {
4417                         return (UNIXERROR(ERRHRD,ERRdiskfull));
4418                 }
4419         }
4420
4421         /*
4422          * Finally the times.
4423          */
4424         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4425                 if(fsp != NULL) {
4426                         /*
4427                          * This was a setfileinfo on an open file.
4428                          * NT does this a lot. We also need to 
4429                          * set the time here, as it can be read by 
4430                          * FindFirst/FindNext and with the patch for bug #2045
4431                          * in smbd/fileio.c it ensures that this timestamp is
4432                          * kept sticky even after a write. We save the request
4433                          * away and will set it on file close and after a write. JRA.
4434                          */
4435
4436                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4437                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4438                                 fsp_set_pending_modtime(fsp, tvs.modtime);
4439                         }
4440
4441                 }
4442                 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4443
4444                 if(file_utime(conn, fname, &tvs)!=0) {
4445                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4446                 }
4447         }
4448
4449         SSVAL(params,0,0);
4450         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4451   
4452         return(-1);
4453 }
4454
4455 /****************************************************************************
4456  Reply to a TRANS2_MKDIR (make directory with extended attributes).
4457 ****************************************************************************/
4458
4459 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4460                                         char **pparams, int total_params, char **ppdata, int total_data,
4461                                         unsigned int max_data_bytes)
4462 {
4463         char *params = *pparams;
4464         char *pdata = *ppdata;
4465         pstring directory;
4466         int ret = -1;
4467         SMB_STRUCT_STAT sbuf;
4468         BOOL bad_path = False;
4469         NTSTATUS status = NT_STATUS_OK;
4470         TALLOC_CTX *ctx = NULL;
4471         struct ea_list *ea_list = NULL;
4472
4473         if (!CAN_WRITE(conn))
4474                 return ERROR_DOS(ERRSRV,ERRaccess);
4475
4476         if (total_params < 4) {
4477                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4478         }
4479
4480         srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status);
4481         if (!NT_STATUS_IS_OK(status)) {
4482                 return ERROR_NT(status);
4483         }
4484
4485         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4486
4487         unix_convert(directory,conn,0,&bad_path,&sbuf);
4488         if (bad_path) {
4489                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4490         }
4491
4492         /* Any data in this call is an EA list. */
4493         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
4494                 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4495         }
4496
4497         /*
4498          * OS/2 workplace shell seems to send SET_EA requests of "null"
4499          * length (4 bytes containing IVAL 4).
4500          * They seem to have no effect. Bug #3212. JRA.
4501          */
4502
4503         if (total_data != 4) {
4504                 if (total_data < 10) {
4505                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4506                 }
4507
4508                 if (IVAL(pdata,0) > total_data) {
4509                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4510                                 IVAL(pdata,0), (unsigned int)total_data));
4511                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4512                 }
4513
4514                 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4515                 if (!ctx) {
4516                         return ERROR_NT(NT_STATUS_NO_MEMORY);
4517                 }
4518                 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4519                 if (!ea_list) {
4520                         talloc_destroy(ctx);
4521                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4522                 }
4523         } else if (IVAL(pdata,0) != 4) {
4524                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4525         }
4526
4527         if (check_name(directory,conn)) {
4528                 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4529         }
4530   
4531         if(ret < 0) {
4532                 talloc_destroy(ctx);
4533                 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4534                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4535         }
4536
4537         /* Try and set any given EA. */
4538         if (total_data) {
4539                 status = set_ea(conn, NULL, directory, ea_list);
4540                 talloc_destroy(ctx);
4541                 if (!NT_STATUS_IS_OK(status)) {
4542                         return ERROR_NT(status);
4543                 }
4544         }
4545
4546         /* Realloc the parameter and data sizes */
4547         *pparams = SMB_REALLOC(*pparams,2);
4548         if(*pparams == NULL) {
4549                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4550         }
4551         params = *pparams;
4552
4553         SSVAL(params,0,0);
4554
4555         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4556   
4557         return(-1);
4558 }
4559
4560 /****************************************************************************
4561  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4562  We don't actually do this - we just send a null response.
4563 ****************************************************************************/
4564
4565 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4566                                         char **pparams, int total_params, char **ppdata, int total_data,
4567                                         unsigned int max_data_bytes)
4568 {
4569         static uint16 fnf_handle = 257;
4570         char *params = *pparams;
4571         uint16 info_level;
4572
4573         if (total_params < 6) {
4574                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4575         }
4576
4577         info_level = SVAL(params,4);
4578         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4579
4580         switch (info_level) {
4581                 case 1:
4582                 case 2:
4583                         break;
4584                 default:
4585                         return ERROR_DOS(ERRDOS,ERRunknownlevel);
4586         }
4587
4588         /* Realloc the parameter and data sizes */
4589         *pparams = SMB_REALLOC(*pparams,6);
4590         if (*pparams == NULL) {
4591                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4592         }
4593         params = *pparams;
4594
4595         SSVAL(params,0,fnf_handle);
4596         SSVAL(params,2,0); /* No changes */
4597         SSVAL(params,4,0); /* No EA errors */
4598
4599         fnf_handle++;
4600
4601         if(fnf_handle == 0)
4602                 fnf_handle = 257;
4603
4604         send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4605   
4606         return(-1);
4607 }
4608
4609 /****************************************************************************
4610  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
4611  changes). Currently this does nothing.
4612 ****************************************************************************/
4613
4614 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4615                                         char **pparams, int total_params, char **ppdata, int total_data,
4616                                         unsigned int max_data_bytes)
4617 {
4618         char *params = *pparams;
4619
4620         DEBUG(3,("call_trans2findnotifynext\n"));
4621
4622         /* Realloc the parameter and data sizes */
4623         *pparams = SMB_REALLOC(*pparams,4);
4624         if (*pparams == NULL) {
4625                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4626         }
4627         params = *pparams;
4628
4629         SSVAL(params,0,0); /* No changes */
4630         SSVAL(params,2,0); /* No EA errors */
4631
4632         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4633   
4634         return(-1);
4635 }
4636
4637 /****************************************************************************
4638  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4639 ****************************************************************************/
4640
4641 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4642                                         char **pparams, int total_params, char **ppdata, int total_data,
4643                                         unsigned int max_data_bytes)
4644 {
4645         char *params = *pparams;
4646         pstring pathname;
4647         int reply_size = 0;
4648         int max_referral_level;
4649
4650         DEBUG(10,("call_trans2getdfsreferral\n"));
4651
4652         if (total_params < 2) {
4653                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4654         }
4655
4656         max_referral_level = SVAL(params,0);
4657
4658         if(!lp_host_msdfs())
4659                 return ERROR_DOS(ERRDOS,ERRbadfunc);
4660
4661         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4662         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4663                 return UNIXERROR(ERRDOS,ERRbadfile);
4664     
4665         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4666         send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4667
4668         return(-1);
4669 }
4670
4671 #define LMCAT_SPL       0x53
4672 #define LMFUNC_GETJOBID 0x60
4673
4674 /****************************************************************************
4675  Reply to a TRANS2_IOCTL - used for OS/2 printing.
4676 ****************************************************************************/
4677
4678 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4679                                         char **pparams, int total_params, char **ppdata, int total_data,
4680                                         unsigned int max_data_bytes)
4681 {
4682         char *pdata = *ppdata;
4683         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4684
4685         /* check for an invalid fid before proceeding */
4686         
4687         if (!fsp)                                
4688                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
4689
4690         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4691                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4692                 *ppdata = SMB_REALLOC(*ppdata, 32);
4693                 if (*ppdata == NULL) {
4694                         return ERROR_NT(NT_STATUS_NO_MEMORY);
4695                 }
4696                 pdata = *ppdata;
4697
4698                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4699                         CAN ACCEPT THIS IN UNICODE. JRA. */
4700
4701                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
4702                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4703                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4704                 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4705                 return(-1);
4706         } else {
4707                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4708                 return ERROR_DOS(ERRSRV,ERRerror);
4709         }
4710 }
4711
4712 /****************************************************************************
4713  Reply to a SMBfindclose (stop trans2 directory search).
4714 ****************************************************************************/
4715
4716 int reply_findclose(connection_struct *conn,
4717                     char *inbuf,char *outbuf,int length,int bufsize)
4718 {
4719         int outsize = 0;
4720         int dptr_num=SVALS(inbuf,smb_vwv0);
4721         START_PROFILE(SMBfindclose);
4722
4723         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
4724
4725         dptr_close(&dptr_num);
4726
4727         outsize = set_message(outbuf,0,0,True);
4728
4729         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
4730
4731         END_PROFILE(SMBfindclose);
4732         return(outsize);
4733 }
4734
4735 /****************************************************************************
4736  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
4737 ****************************************************************************/
4738
4739 int reply_findnclose(connection_struct *conn, 
4740                      char *inbuf,char *outbuf,int length,int bufsize)
4741 {
4742         int outsize = 0;
4743         int dptr_num= -1;
4744         START_PROFILE(SMBfindnclose);
4745         
4746         dptr_num = SVAL(inbuf,smb_vwv0);
4747
4748         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
4749
4750         /* We never give out valid handles for a 
4751            findnotifyfirst - so any dptr_num is ok here. 
4752            Just ignore it. */
4753
4754         outsize = set_message(outbuf,0,0,True);
4755
4756         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
4757
4758         END_PROFILE(SMBfindnclose);
4759         return(outsize);
4760 }
4761
4762 /****************************************************************************
4763  Reply to a SMBtranss2 - just ignore it!
4764 ****************************************************************************/
4765
4766 int reply_transs2(connection_struct *conn,
4767                   char *inbuf,char *outbuf,int length,int bufsize)
4768 {
4769         START_PROFILE(SMBtranss2);
4770         DEBUG(4,("Ignoring transs2 of length %d\n",length));
4771         END_PROFILE(SMBtranss2);
4772         return(-1);
4773 }
4774
4775 /****************************************************************************
4776  Reply to a SMBtrans2.
4777 ****************************************************************************/
4778
4779 int reply_trans2(connection_struct *conn,
4780                  char *inbuf,char *outbuf,int length,int bufsize)
4781 {
4782         int outsize = 0;
4783         unsigned int total_params = SVAL(inbuf, smb_tpscnt);
4784         unsigned int total_data =SVAL(inbuf, smb_tdscnt);
4785         unsigned int max_data_bytes = SVAL(inbuf, smb_mdrcnt);
4786 #if 0
4787         unsigned int max_param_reply = SVAL(inbuf, smb_mprcnt);
4788         unsigned int max_setup_fields = SVAL(inbuf, smb_msrcnt);
4789         BOOL close_tid = BITSETW(inbuf+smb_flags,0);
4790         BOOL no_final_response = BITSETW(inbuf+smb_flags,1);
4791         int32 timeout = IVALS(inbuf,smb_timeout);
4792 #endif
4793         unsigned int suwcnt = SVAL(inbuf, smb_suwcnt);
4794         unsigned int tran_call = SVAL(inbuf, smb_setup0);
4795         char *params = NULL, *data = NULL;
4796         unsigned int num_params, num_params_sofar, num_data, num_data_sofar;
4797         START_PROFILE(SMBtrans2);
4798
4799         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
4800             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
4801                 END_PROFILE(SMBtrans2);
4802                 return ERROR_DOS(ERRSRV,ERRaccess);
4803         }
4804
4805         outsize = set_message(outbuf,0,0,True);
4806
4807         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
4808            is so as a sanity check */
4809         if (suwcnt != 1) {
4810                 /*
4811                  * Need to have rc=0 for ioctl to get job id for OS/2.
4812                  *  Network printing will fail if function is not successful.
4813                  *  Similar function in reply.c will be used if protocol
4814                  *  is LANMAN1.0 instead of LM1.2X002.
4815                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
4816                  *  outbuf doesn't have to be set(only job id is used).
4817                  */
4818                 if ( (suwcnt == 4) && (tran_call == TRANSACT2_IOCTL) &&
4819                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4820                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4821                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
4822                 } else {
4823                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",suwcnt));
4824                         DEBUG(2,("Transaction is %d\n",tran_call));
4825                         END_PROFILE(SMBtrans2);
4826                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4827                 }
4828         }
4829     
4830         /* Allocate the space for the maximum needed parameters and data */
4831         if (total_params > 0)
4832                 params = (char *)SMB_MALLOC(total_params);
4833         if (total_data > 0)
4834                 data = (char *)SMB_MALLOC(total_data);
4835   
4836         if ((total_params && !params)  || (total_data && !data)) {
4837                 DEBUG(2,("Out of memory in reply_trans2\n"));
4838                 SAFE_FREE(params);
4839                 SAFE_FREE(data); 
4840                 END_PROFILE(SMBtrans2);
4841                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4842         }
4843
4844         /* Copy the param and data bytes sent with this request into
4845            the params buffer */
4846         num_params = num_params_sofar = SVAL(inbuf,smb_pscnt);
4847         num_data = num_data_sofar = SVAL(inbuf, smb_dscnt);
4848
4849         if (num_params > total_params || num_data > total_data)
4850                 exit_server("invalid params in reply_trans2");
4851
4852         if(params) {
4853                 unsigned int psoff = SVAL(inbuf, smb_psoff);
4854                 if ((psoff + num_params < psoff) || (psoff + num_params < num_params))
4855                         goto bad_param;
4856                 if ((smb_base(inbuf) + psoff + num_params > inbuf + length) ||
4857                                 (smb_base(inbuf) + psoff + num_params < smb_base(inbuf)))
4858                         goto bad_param;
4859                 memcpy( params, smb_base(inbuf) + psoff, num_params);
4860         }
4861         if(data) {
4862                 unsigned int dsoff = SVAL(inbuf, smb_dsoff);
4863                 if ((dsoff + num_data < dsoff) || (dsoff + num_data < num_data))
4864                         goto bad_param;
4865                 if ((smb_base(inbuf) + dsoff + num_data > inbuf + length) ||
4866                                 (smb_base(inbuf) + dsoff + num_data < smb_base(inbuf)))
4867                         goto bad_param;
4868                 memcpy( data, smb_base(inbuf) + dsoff, num_data);
4869         }
4870
4871         srv_signing_trans_start(SVAL(inbuf,smb_mid));
4872
4873         if(num_data_sofar < total_data || num_params_sofar < total_params)  {
4874                 /* We need to send an interim response then receive the rest
4875                    of the parameter/data bytes */
4876                 outsize = set_message(outbuf,0,0,True);
4877                 srv_signing_trans_stop();
4878                 show_msg(outbuf);
4879                 if (!send_smb(smbd_server_fd(),outbuf))
4880                         exit_server("reply_trans2: send_smb failed.");
4881
4882                 while (num_data_sofar < total_data || 
4883                        num_params_sofar < total_params) {
4884                         BOOL ret;
4885                         unsigned int param_disp;
4886                         unsigned int param_off;
4887                         unsigned int data_disp;
4888                         unsigned int data_off;
4889
4890                         ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
4891
4892                         /* We need to re-calcuate the new length after we've read the secondary packet. */
4893                         length = smb_len(inbuf) + 4;
4894                         
4895                         /*
4896                          * The sequence number for the trans reply is always
4897                          * based on the last secondary received.
4898                          */
4899
4900                         srv_signing_trans_start(SVAL(inbuf,smb_mid));
4901
4902                         if ((ret && 
4903                              (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret) {
4904                                 outsize = set_message(outbuf,0,0,True);
4905                                 if(ret)
4906                                         DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
4907                                 else
4908                                         DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
4909                                                  (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
4910                                 goto bad_param;
4911                         }
4912       
4913                         /* Revise total_params and total_data in case
4914                            they have changed downwards */
4915                         if (SVAL(inbuf, smb_tpscnt) < total_params)
4916                                 total_params = SVAL(inbuf, smb_tpscnt);
4917                         if (SVAL(inbuf, smb_tdscnt) < total_data)
4918                                 total_data = SVAL(inbuf, smb_tdscnt);
4919
4920                         num_params = SVAL(inbuf,smb_spscnt);
4921                         param_off = SVAL(inbuf, smb_spsoff);
4922                         param_disp = SVAL(inbuf, smb_spsdisp);
4923                         num_params_sofar += num_params;
4924
4925                         num_data = SVAL(inbuf, smb_sdscnt);
4926                         data_off = SVAL(inbuf, smb_sdsoff);
4927                         data_disp = SVAL(inbuf, smb_sdsdisp);
4928                         num_data_sofar += num_data;
4929
4930                         if (num_params_sofar > total_params || num_data_sofar > total_data)
4931                                 goto bad_param;
4932                         
4933                         if (num_params) {
4934                                 if (param_disp + num_params > total_params)
4935                                         goto bad_param;
4936                                 if ((param_disp + num_params < param_disp) ||
4937                                                 (param_disp + num_params < num_params))
4938                                         goto bad_param;
4939                                 if (param_disp > total_params)
4940                                         goto bad_param;
4941                                 if ((smb_base(inbuf) + param_off + num_params > inbuf + length) ||
4942                                                 (smb_base(inbuf) + param_off + num_params < smb_base(inbuf)))
4943                                         goto bad_param;
4944                                 if (params + param_disp < params)
4945                                         goto bad_param;
4946
4947                                 memcpy( &params[param_disp], smb_base(inbuf) + param_off, num_params);
4948                         }
4949                         if (num_data) {
4950                                 if (data_disp + num_data > total_data)
4951                                         goto bad_param;
4952                                 if ((data_disp + num_data < data_disp) ||
4953                                                 (data_disp + num_data < num_data))
4954                                         goto bad_param;
4955                                 if (data_disp > total_data)
4956                                         goto bad_param;
4957                                 if ((smb_base(inbuf) + data_off + num_data > inbuf + length) ||
4958                                                 (smb_base(inbuf) + data_off + num_data < smb_base(inbuf)))
4959                                         goto bad_param;
4960                                 if (data + data_disp < data)
4961                                         goto bad_param;
4962
4963                                 memcpy( &data[data_disp], smb_base(inbuf) + data_off, num_data);
4964                         }
4965                 }
4966         }
4967         
4968         if (Protocol >= PROTOCOL_NT1) {
4969                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
4970         }
4971
4972         /* Now we must call the relevant TRANS2 function */
4973         switch(tran_call)  {
4974         case TRANSACT2_OPEN:
4975                 START_PROFILE_NESTED(Trans2_open);
4976                 outsize = call_trans2open(conn, inbuf, outbuf, bufsize, 
4977                                           &params, total_params, &data, total_data, max_data_bytes);
4978                 END_PROFILE_NESTED(Trans2_open);
4979                 break;
4980
4981         case TRANSACT2_FINDFIRST:
4982                 START_PROFILE_NESTED(Trans2_findfirst);
4983                 outsize = call_trans2findfirst(conn, inbuf, outbuf, bufsize,
4984                                           &params, total_params, &data, total_data, max_data_bytes);
4985                 END_PROFILE_NESTED(Trans2_findfirst);
4986                 break;
4987
4988         case TRANSACT2_FINDNEXT:
4989                 START_PROFILE_NESTED(Trans2_findnext);
4990                 outsize = call_trans2findnext(conn, inbuf, outbuf, length, bufsize, 
4991                                           &params, total_params, &data, total_data, max_data_bytes);
4992                 END_PROFILE_NESTED(Trans2_findnext);
4993                 break;
4994
4995         case TRANSACT2_QFSINFO:
4996                 START_PROFILE_NESTED(Trans2_qfsinfo);
4997                 outsize = call_trans2qfsinfo(conn, inbuf, outbuf, length, bufsize,
4998                                           &params, total_params, &data, total_data, max_data_bytes);
4999                 END_PROFILE_NESTED(Trans2_qfsinfo);
5000             break;
5001
5002         case TRANSACT2_SETFSINFO:
5003                 START_PROFILE_NESTED(Trans2_setfsinfo);
5004                 outsize = call_trans2setfsinfo(conn, inbuf, outbuf, length, bufsize, 
5005                                           &params, total_params, &data, total_data, max_data_bytes);
5006                 END_PROFILE_NESTED(Trans2_setfsinfo);
5007                 break;
5008
5009         case TRANSACT2_QPATHINFO:
5010         case TRANSACT2_QFILEINFO:
5011                 START_PROFILE_NESTED(Trans2_qpathinfo);
5012                 outsize = call_trans2qfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5013                                           &params, total_params, &data, total_data, max_data_bytes);
5014                 END_PROFILE_NESTED(Trans2_qpathinfo);
5015                 break;
5016         case TRANSACT2_SETPATHINFO:
5017         case TRANSACT2_SETFILEINFO:
5018                 START_PROFILE_NESTED(Trans2_setpathinfo);
5019                 outsize = call_trans2setfilepathinfo(conn, inbuf, outbuf, length, bufsize, tran_call,
5020                                           &params, total_params, &data, total_data, max_data_bytes);
5021                 END_PROFILE_NESTED(Trans2_setpathinfo);
5022                 break;
5023
5024         case TRANSACT2_FINDNOTIFYFIRST:
5025                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5026                 outsize = call_trans2findnotifyfirst(conn, inbuf, outbuf, length, bufsize, 
5027                                           &params, total_params, &data, total_data, max_data_bytes);
5028                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5029                 break;
5030
5031         case TRANSACT2_FINDNOTIFYNEXT:
5032                 START_PROFILE_NESTED(Trans2_findnotifynext);
5033                 outsize = call_trans2findnotifynext(conn, inbuf, outbuf, length, bufsize, 
5034                                           &params, total_params, &data, total_data, max_data_bytes);
5035                 END_PROFILE_NESTED(Trans2_findnotifynext);
5036                 break;
5037         case TRANSACT2_MKDIR:
5038                 START_PROFILE_NESTED(Trans2_mkdir);
5039                 outsize = call_trans2mkdir(conn, inbuf, outbuf, length, bufsize,
5040                                           &params, total_params, &data, total_data, max_data_bytes);
5041                 END_PROFILE_NESTED(Trans2_mkdir);
5042                 break;
5043
5044         case TRANSACT2_GET_DFS_REFERRAL:
5045                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5046                 outsize = call_trans2getdfsreferral(conn,inbuf,outbuf,length, bufsize,
5047                                           &params, total_params, &data, total_data, max_data_bytes);
5048                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5049                 break;
5050         case TRANSACT2_IOCTL:
5051                 START_PROFILE_NESTED(Trans2_ioctl);
5052                 outsize = call_trans2ioctl(conn,inbuf,outbuf,length, bufsize,
5053                                           &params, total_params, &data, total_data, max_data_bytes);
5054                 END_PROFILE_NESTED(Trans2_ioctl);
5055                 break;
5056         default:
5057                 /* Error in request */
5058                 DEBUG(2,("Unknown request %d in trans2 call\n", tran_call));
5059                 SAFE_FREE(params);
5060                 SAFE_FREE(data);
5061                 END_PROFILE(SMBtrans2);
5062                 srv_signing_trans_stop();
5063                 return ERROR_DOS(ERRSRV,ERRerror);
5064         }
5065         
5066         /* As we do not know how many data packets will need to be
5067            returned here the various call_trans2xxxx calls
5068            must send their own. Thus a call_trans2xxx routine only
5069            returns a value other than -1 when it wants to send
5070            an error packet. 
5071         */
5072         
5073         srv_signing_trans_stop();
5074
5075         SAFE_FREE(params);
5076         SAFE_FREE(data);
5077         END_PROFILE(SMBtrans2);
5078         return outsize; /* If a correct response was needed the
5079                            call_trans2xxx calls have already sent
5080                            it. If outsize != -1 then it is returning */
5081
5082   bad_param:
5083
5084         srv_signing_trans_stop();
5085         SAFE_FREE(params);
5086         SAFE_FREE(data);
5087         END_PROFILE(SMBtrans2);
5088         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5089 }