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