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