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