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