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