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