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