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