r21207: Make the code match the spec :-).
[sfrench/samba-autobuild/.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  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2869  file name or file id).
2870 ****************************************************************************/
2871
2872 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2873                                         unsigned int tran_call,
2874                                         char **pparams, int total_params, char **ppdata, int total_data,
2875                                         unsigned int max_data_bytes)
2876 {
2877         char *params = *pparams;
2878         char *pdata = *ppdata;
2879         uint16 info_level;
2880         int mode=0;
2881         int nlink;
2882         SMB_OFF_T file_size=0;
2883         SMB_BIG_UINT allocation_size=0;
2884         unsigned int data_size = 0;
2885         unsigned int param_size = 2;
2886         SMB_STRUCT_STAT sbuf;
2887         pstring fname, dos_fname;
2888         char *fullpathname;
2889         char *base_name;
2890         char *p;
2891         SMB_OFF_T pos = 0;
2892         BOOL delete_pending = False;
2893         int len;
2894         time_t create_time, mtime, atime;
2895         struct timespec create_time_ts, mtime_ts, atime_ts;
2896         files_struct *fsp = NULL;
2897         TALLOC_CTX *data_ctx = NULL;
2898         struct ea_list *ea_list = NULL;
2899         uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2900         char *lock_data = NULL;
2901
2902         if (!params)
2903                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2904
2905         ZERO_STRUCT(sbuf);
2906
2907         if (tran_call == TRANSACT2_QFILEINFO) {
2908                 if (total_params < 4) {
2909                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2910                 }
2911
2912                 fsp = file_fsp(params,0);
2913                 info_level = SVAL(params,2);
2914
2915                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2916
2917                 if(fsp && (fsp->fake_file_handle)) {
2918                         /*
2919                          * This is actually for the QUOTA_FAKE_FILE --metze
2920                          */
2921                                                 
2922                         pstrcpy(fname, fsp->fsp_name);
2923                         /* We know this name is ok, it's already passed the checks. */
2924                         
2925                 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2926                         /*
2927                          * This is actually a QFILEINFO on a directory
2928                          * handle (returned from an NT SMB). NT5.0 seems
2929                          * to do this call. JRA.
2930                          */
2931                         /* We know this name is ok, it's already passed the checks. */
2932                         pstrcpy(fname, fsp->fsp_name);
2933                   
2934                         if (INFO_LEVEL_IS_UNIX(info_level)) {
2935                                 /* Always do lstat for UNIX calls. */
2936                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2937                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2938                                         return UNIXERROR(ERRDOS,ERRbadpath);
2939                                 }
2940                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2941                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2942                                 return UNIXERROR(ERRDOS,ERRbadpath);
2943                         }
2944
2945                         delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2946                 } else {
2947                         /*
2948                          * Original code - this is an open file.
2949                          */
2950                         CHECK_FSP(fsp,conn);
2951
2952                         pstrcpy(fname, fsp->fsp_name);
2953                         if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2954                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2955                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2956                         }
2957                         pos = fsp->fh->position_information;
2958                         delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2959                         access_mask = fsp->access_mask;
2960                 }
2961         } else {
2962                 NTSTATUS status = NT_STATUS_OK;
2963
2964                 /* qpathinfo */
2965                 if (total_params < 7) {
2966                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2967                 }
2968
2969                 info_level = SVAL(params,0);
2970
2971                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2972
2973                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
2974                 if (!NT_STATUS_IS_OK(status)) {
2975                         return ERROR_NT(status);
2976                 }
2977
2978                 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2979
2980                 status = unix_convert(conn, fname, False, NULL, &sbuf);
2981                 if (!NT_STATUS_IS_OK(status)) {
2982                         return ERROR_NT(status);
2983                 }
2984                 status = check_name(conn, fname);
2985                 if (!NT_STATUS_IS_OK(status)) {
2986                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
2987                         return ERROR_NT(status);
2988                 }
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 (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
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                 if (delete_pending) {
3003                         return ERROR_NT(NT_STATUS_DELETE_PENDING);
3004                 }
3005         }
3006
3007         nlink = sbuf.st_nlink;
3008
3009         if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3010                 /* NTFS does not seem to count ".." */
3011                 nlink -= 1;
3012         }
3013
3014         if ((nlink > 0) && delete_pending) {
3015                 nlink -= 1;
3016         }
3017
3018         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3019                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3020         }
3021
3022         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3023                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3024
3025         p = strrchr_m(fname,'/'); 
3026         if (!p)
3027                 base_name = fname;
3028         else
3029                 base_name = p+1;
3030
3031         mode = dos_mode(conn,fname,&sbuf);
3032         if (!mode)
3033                 mode = FILE_ATTRIBUTE_NORMAL;
3034
3035         fullpathname = fname;
3036         if (!(mode & aDIR))
3037                 file_size = get_file_size(sbuf);
3038
3039         /* Pull out any data sent here before we realloc. */
3040         switch (info_level) {
3041                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3042                 {
3043                         /* Pull any EA list from the data portion. */
3044                         uint32 ea_size;
3045
3046                         if (total_data < 4) {
3047                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3048                         }
3049                         ea_size = IVAL(pdata,0);
3050
3051                         if (total_data > 0 && ea_size != total_data) {
3052                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3053 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3054                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3055                         }
3056
3057                         if (!lp_ea_support(SNUM(conn))) {
3058                                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3059                         }
3060
3061                         if ((data_ctx = talloc_init("ea_list")) == NULL) {
3062                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3063                         }
3064
3065                         /* Pull out the list of names. */
3066                         ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3067                         if (!ea_list) {
3068                                 talloc_destroy(data_ctx);
3069                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3070                         }
3071                         break;
3072                 }
3073
3074                 case SMB_QUERY_POSIX_LOCK:
3075                 {
3076                         if (fsp == NULL || fsp->fh->fd == -1) {
3077                                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3078                         }
3079
3080                         if (total_data != POSIX_LOCK_DATA_SIZE) {
3081                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3082                         }
3083
3084                         if ((data_ctx = talloc_init("lock_request")) == NULL) {
3085                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3086                         }
3087
3088                         /* Copy the lock range data. */
3089                         lock_data = (char *)talloc_memdup(
3090                                 data_ctx, pdata, total_data);
3091                         if (!lock_data) {
3092                                 talloc_destroy(data_ctx);
3093                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3094                         }
3095                 }
3096                 default:
3097                         break;
3098         }
3099
3100         *pparams = (char *)SMB_REALLOC(*pparams,2);
3101         if (*pparams == NULL) {
3102                 talloc_destroy(data_ctx);
3103                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3104         }
3105         params = *pparams;
3106         SSVAL(params,0,0);
3107         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3108         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3109         if (*ppdata == NULL ) {
3110                 talloc_destroy(data_ctx);
3111                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3112         }
3113         pdata = *ppdata;
3114
3115         create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3116         mtime_ts = get_mtimespec(&sbuf);
3117         atime_ts = get_atimespec(&sbuf);
3118
3119         allocation_size = get_allocation_size(conn,fsp,&sbuf);
3120
3121         if (fsp) {
3122                 if (fsp->pending_modtime) {
3123                         /* the pending modtime overrides the current modtime */
3124                         mtime_ts.tv_sec = fsp->pending_modtime;
3125                         mtime_ts.tv_nsec = 0;
3126                 }
3127         } else {
3128                 /* Do we have this path open ? */
3129                 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3130                 if (fsp1 && fsp1->pending_modtime) {
3131                         /* the pending modtime overrides the current modtime */
3132                         mtime_ts.tv_sec = fsp1->pending_modtime;
3133                         mtime_ts.tv_nsec = 0;
3134                 }
3135                 if (fsp1 && fsp1->initial_allocation_size) {
3136                         allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3137                 }
3138         }
3139
3140         if (lp_dos_filetime_resolution(SNUM(conn))) {
3141                 dos_filetime_timespec(&create_time_ts);
3142                 dos_filetime_timespec(&mtime_ts);
3143                 dos_filetime_timespec(&atime_ts);
3144         }
3145
3146         create_time = convert_timespec_to_time_t(create_time_ts);
3147         mtime = convert_timespec_to_time_t(mtime_ts);
3148         atime = convert_timespec_to_time_t(atime_ts);
3149
3150         /* NT expects the name to be in an exact form of the *full*
3151            filename. See the trans2 torture test */
3152         if (strequal(base_name,".")) {
3153                 pstrcpy(dos_fname, "\\");
3154         } else {
3155                 pstr_sprintf(dos_fname, "\\%s", fname);
3156                 string_replace(dos_fname, '/', '\\');
3157         }
3158
3159         switch (info_level) {
3160                 case SMB_INFO_STANDARD:
3161                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3162                         data_size = 22;
3163                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3164                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3165                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3166                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
3167                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3168                         SSVAL(pdata,l1_attrFile,mode);
3169                         break;
3170
3171                 case SMB_INFO_QUERY_EA_SIZE:
3172                 {
3173                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3174                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3175                         data_size = 26;
3176                         srv_put_dos_date2(pdata,0,create_time);
3177                         srv_put_dos_date2(pdata,4,atime);
3178                         srv_put_dos_date2(pdata,8,mtime); /* write time */
3179                         SIVAL(pdata,12,(uint32)file_size);
3180                         SIVAL(pdata,16,(uint32)allocation_size);
3181                         SSVAL(pdata,20,mode);
3182                         SIVAL(pdata,22,ea_size);
3183                         break;
3184                 }
3185
3186                 case SMB_INFO_IS_NAME_VALID:
3187                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3188                         if (tran_call == TRANSACT2_QFILEINFO) {
3189                                 /* os/2 needs this ? really ?*/      
3190                                 return ERROR_DOS(ERRDOS,ERRbadfunc); 
3191                         }
3192                         data_size = 0;
3193                         param_size = 0;
3194                         break;
3195                         
3196                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3197                 {
3198                         size_t total_ea_len = 0;
3199                         struct ea_list *ea_file_list = NULL;
3200
3201                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3202
3203                         ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3204                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3205
3206                         if (!ea_list || (total_ea_len > data_size)) {
3207                                 talloc_destroy(data_ctx);
3208                                 data_size = 4;
3209                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3210                                 break;
3211                         }
3212
3213                         data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3214                         talloc_destroy(data_ctx);
3215                         break;
3216                 }
3217
3218                 case SMB_INFO_QUERY_ALL_EAS:
3219                 {
3220                         /* We have data_size bytes to put EA's into. */
3221                         size_t total_ea_len = 0;
3222
3223                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3224
3225                         data_ctx = talloc_init("ea_ctx");
3226                         if (!data_ctx) {
3227                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3228                         }
3229
3230                         ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3231                         if (!ea_list || (total_ea_len > data_size)) {
3232                                 talloc_destroy(data_ctx);
3233                                 data_size = 4;
3234                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3235                                 break;
3236                         }
3237
3238                         data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3239                         talloc_destroy(data_ctx);
3240                         break;
3241                 }
3242
3243                 case SMB_FILE_BASIC_INFORMATION:
3244                 case SMB_QUERY_FILE_BASIC_INFO:
3245
3246                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3247                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3248                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3249                         } else {
3250                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3251                                 data_size = 40;
3252                                 SIVAL(pdata,36,0);
3253                         }
3254                         put_long_date_timespec(pdata,create_time_ts);
3255                         put_long_date_timespec(pdata+8,atime_ts);
3256                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3257                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3258                         SIVAL(pdata,32,mode);
3259
3260                         DEBUG(5,("SMB_QFBI - "));
3261                         DEBUG(5,("create: %s ", ctime(&create_time)));
3262                         DEBUG(5,("access: %s ", ctime(&atime)));
3263                         DEBUG(5,("write: %s ", ctime(&mtime)));
3264                         DEBUG(5,("change: %s ", ctime(&mtime)));
3265                         DEBUG(5,("mode: %x\n", mode));
3266                         break;
3267
3268                 case SMB_FILE_STANDARD_INFORMATION:
3269                 case SMB_QUERY_FILE_STANDARD_INFO:
3270
3271                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3272                         data_size = 24;
3273                         SOFF_T(pdata,0,allocation_size);
3274                         SOFF_T(pdata,8,file_size);
3275                         SIVAL(pdata,16,nlink);
3276                         SCVAL(pdata,20,delete_pending?1:0);
3277                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3278                         SSVAL(pdata,22,0); /* Padding. */
3279                         break;
3280
3281                 case SMB_FILE_EA_INFORMATION:
3282                 case SMB_QUERY_FILE_EA_INFO:
3283                 {
3284                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3285                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3286                         data_size = 4;
3287                         SIVAL(pdata,0,ea_size);
3288                         break;
3289                 }
3290
3291                 /* Get the 8.3 name - used if NT SMB was negotiated. */
3292                 case SMB_QUERY_FILE_ALT_NAME_INFO:
3293                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3294                 {
3295                         pstring short_name;
3296
3297                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3298                         pstrcpy(short_name,base_name);
3299                         /* Mangle if not already 8.3 */
3300                         if(!mangle_is_8_3(short_name, True, conn->params)) {
3301                                 mangle_map(short_name,True,True,conn->params);
3302                         }
3303                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3304                         data_size = 4 + len;
3305                         SIVAL(pdata,0,len);
3306                         break;
3307                 }
3308
3309                 case SMB_QUERY_FILE_NAME_INFO:
3310                         /*
3311                           this must be *exactly* right for ACLs on mapped drives to work
3312                          */
3313                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3314                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3315                         data_size = 4 + len;
3316                         SIVAL(pdata,0,len);
3317                         break;
3318
3319                 case SMB_FILE_ALLOCATION_INFORMATION:
3320                 case SMB_QUERY_FILE_ALLOCATION_INFO:
3321                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3322                         data_size = 8;
3323                         SOFF_T(pdata,0,allocation_size);
3324                         break;
3325
3326                 case SMB_FILE_END_OF_FILE_INFORMATION:
3327                 case SMB_QUERY_FILE_END_OF_FILEINFO:
3328                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3329                         data_size = 8;
3330                         SOFF_T(pdata,0,file_size);
3331                         break;
3332
3333                 case SMB_QUERY_FILE_ALL_INFO:
3334                 case SMB_FILE_ALL_INFORMATION:
3335                 {
3336                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3337                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3338                         put_long_date_timespec(pdata,create_time_ts);
3339                         put_long_date_timespec(pdata+8,atime_ts);
3340                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3341                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3342                         SIVAL(pdata,32,mode);
3343                         SIVAL(pdata,36,0); /* padding. */
3344                         pdata += 40;
3345                         SOFF_T(pdata,0,allocation_size);
3346                         SOFF_T(pdata,8,file_size);
3347                         SIVAL(pdata,16,nlink);
3348                         SCVAL(pdata,20,delete_pending);
3349                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3350                         SSVAL(pdata,22,0);
3351                         pdata += 24;
3352                         SIVAL(pdata,0,ea_size);
3353                         pdata += 4; /* EA info */
3354                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3355                         SIVAL(pdata,0,len);
3356                         pdata += 4 + len;
3357                         data_size = PTR_DIFF(pdata,(*ppdata));
3358                         break;
3359                 }
3360                 case SMB_FILE_INTERNAL_INFORMATION:
3361                         /* This should be an index number - looks like
3362                            dev/ino to me :-) 
3363
3364                            I think this causes us to fail the IFSKIT
3365                            BasicFileInformationTest. -tpot */
3366
3367                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3368                         SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3369                         SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3370                         data_size = 8;
3371                         break;
3372
3373                 case SMB_FILE_ACCESS_INFORMATION:
3374                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3375                         SIVAL(pdata,0,access_mask);
3376                         data_size = 4;
3377                         break;
3378
3379                 case SMB_FILE_NAME_INFORMATION:
3380                         /* Pathname with leading '\'. */
3381                         {
3382                                 size_t byte_len;
3383                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3384                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3385                                 SIVAL(pdata,0,byte_len);
3386                                 data_size = 4 + byte_len;
3387                                 break;
3388                         }
3389
3390                 case SMB_FILE_DISPOSITION_INFORMATION:
3391                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3392                         data_size = 1;
3393                         SCVAL(pdata,0,delete_pending);
3394                         break;
3395
3396                 case SMB_FILE_POSITION_INFORMATION:
3397                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3398                         data_size = 8;
3399                         SOFF_T(pdata,0,pos);
3400                         break;
3401
3402                 case SMB_FILE_MODE_INFORMATION:
3403                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3404                         SIVAL(pdata,0,mode);
3405                         data_size = 4;
3406                         break;
3407
3408                 case SMB_FILE_ALIGNMENT_INFORMATION:
3409                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3410                         SIVAL(pdata,0,0); /* No alignment needed. */
3411                         data_size = 4;
3412                         break;
3413
3414 #if 0
3415                 /*
3416                  * NT4 server just returns "invalid query" to this - if we try to answer
3417                  * it then NTws gets a BSOD! (tridge).
3418                  * W2K seems to want this. JRA.
3419                  */
3420                 case SMB_QUERY_FILE_STREAM_INFO:
3421 #endif
3422                 case SMB_FILE_STREAM_INFORMATION:
3423                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3424                         if (mode & aDIR) {
3425                                 data_size = 0;
3426                         } else {
3427                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3428                                 SIVAL(pdata,0,0); /* ??? */
3429                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3430                                 SOFF_T(pdata,8,file_size);
3431                                 SIVAL(pdata,16,allocation_size);
3432                                 SIVAL(pdata,20,0); /* ??? */
3433                                 data_size = 24 + byte_len;
3434                         }
3435                         break;
3436
3437                 case SMB_QUERY_COMPRESSION_INFO:
3438                 case SMB_FILE_COMPRESSION_INFORMATION:
3439                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3440                         SOFF_T(pdata,0,file_size);
3441                         SIVAL(pdata,8,0); /* ??? */
3442                         SIVAL(pdata,12,0); /* ??? */
3443                         data_size = 16;
3444                         break;
3445
3446                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3447                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3448                         put_long_date_timespec(pdata,create_time_ts);
3449                         put_long_date_timespec(pdata+8,atime_ts);
3450                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3451                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3452                         SIVAL(pdata,32,allocation_size);
3453                         SOFF_T(pdata,40,file_size);
3454                         SIVAL(pdata,48,mode);
3455                         SIVAL(pdata,52,0); /* ??? */
3456                         data_size = 56;
3457                         break;
3458
3459                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3460                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3461                         SIVAL(pdata,0,mode);
3462                         SIVAL(pdata,4,0);
3463                         data_size = 8;
3464                         break;
3465
3466                 /*
3467                  * CIFS UNIX Extensions.
3468                  */
3469
3470                 case SMB_QUERY_FILE_UNIX_BASIC:
3471
3472                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3473                         DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3474
3475                         SOFF_T(pdata,0,get_file_size(sbuf));             /* File size 64 Bit */
3476                         pdata += 8;
3477
3478                         SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3479                         pdata += 8;
3480
3481                         put_long_date_timespec(pdata,get_ctimespec(&sbuf));       /* Creation Time 64 Bit */
3482                         put_long_date_timespec(pdata+8,get_atimespec(&sbuf));     /* Last access time 64 Bit */
3483                         put_long_date_timespec(pdata+16,get_mtimespec(&sbuf));    /* Last modification time 64 Bit */
3484                         pdata += 24;
3485
3486                         SIVAL(pdata,0,sbuf.st_uid);               /* user id for the owner */
3487                         SIVAL(pdata,4,0);
3488                         pdata += 8;
3489
3490                         SIVAL(pdata,0,sbuf.st_gid);               /* group id of owner */
3491                         SIVAL(pdata,4,0);
3492                         pdata += 8;
3493
3494                         SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3495                         pdata += 4;
3496
3497                         SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
3498                         SIVAL(pdata,4,0);
3499                         pdata += 8;
3500
3501                         SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
3502                         SIVAL(pdata,4,0);
3503                         pdata += 8;
3504
3505                         SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
3506                         pdata += 8;
3507                                 
3508                         SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
3509                         SIVAL(pdata,4,0);
3510                         pdata += 8;
3511
3512                         SIVAL(pdata,0,sbuf.st_nlink);             /* number of hard links */
3513                         SIVAL(pdata,4,0);
3514                         pdata += 8;
3515                         data_size = PTR_DIFF(pdata,(*ppdata));
3516
3517                         {
3518                                 int i;
3519                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3520
3521                                 for (i=0; i<100; i++)
3522                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3523                                 DEBUG(4,("\n"));
3524                         }
3525
3526                         break;
3527
3528                 case SMB_QUERY_FILE_UNIX_LINK:
3529                         {
3530                                 pstring buffer;
3531
3532                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3533 #ifdef S_ISLNK
3534                                 if(!S_ISLNK(sbuf.st_mode))
3535                                         return(UNIXERROR(ERRSRV,ERRbadlink));
3536 #else
3537                                 return(UNIXERROR(ERRDOS,ERRbadlink));
3538 #endif
3539                                 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
3540                                 if (len == -1)
3541                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3542                                 buffer[len] = 0;
3543                                 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3544                                 pdata += len;
3545                                 data_size = PTR_DIFF(pdata,(*ppdata));
3546
3547                                 break;
3548                         }
3549
3550 #if defined(HAVE_POSIX_ACLS)
3551                 case SMB_QUERY_POSIX_ACL:
3552                         {
3553                                 SMB_ACL_T file_acl = NULL;
3554                                 SMB_ACL_T def_acl = NULL;
3555                                 uint16 num_file_acls = 0;
3556                                 uint16 num_def_acls = 0;
3557
3558                                 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3559                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3560                                 } else {
3561                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3562                                 }
3563
3564                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3565                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3566                                                 fname ));
3567                                         return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3568                                 }
3569
3570                                 if (S_ISDIR(sbuf.st_mode)) {
3571                                         if (fsp && fsp->is_directory) {
3572                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3573                                         } else {
3574                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3575                                         }
3576                                         def_acl = free_empty_sys_acl(conn, def_acl);
3577                                 }
3578
3579                                 num_file_acls = count_acl_entries(conn, file_acl);
3580                                 num_def_acls = count_acl_entries(conn, def_acl);
3581
3582                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3583                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3584                                                 data_size,
3585                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3586                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
3587                                         if (file_acl) {
3588                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3589                                         }
3590                                         if (def_acl) {
3591                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3592                                         }
3593                                         return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3594                                 }
3595
3596                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3597                                 SSVAL(pdata,2,num_file_acls);
3598                                 SSVAL(pdata,4,num_def_acls);
3599                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3600                                         if (file_acl) {
3601                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3602                                         }
3603                                         if (def_acl) {
3604                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3605                                         }
3606                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3607                                 }
3608                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3609                                         if (file_acl) {
3610                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3611                                         }
3612                                         if (def_acl) {
3613                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3614                                         }
3615                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3616                                 }
3617
3618                                 if (file_acl) {
3619                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3620                                 }
3621                                 if (def_acl) {
3622                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3623                                 }
3624                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3625                                 break;
3626                         }
3627 #endif
3628
3629
3630                 case SMB_QUERY_POSIX_LOCK:
3631                 {
3632                         NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3633                         SMB_BIG_UINT count;
3634                         SMB_BIG_UINT offset;
3635                         uint32 lock_pid;
3636                         enum brl_type lock_type;
3637
3638                         if (total_data != POSIX_LOCK_DATA_SIZE) {
3639                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3640                         }
3641
3642                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3643                                 case POSIX_LOCK_TYPE_READ:
3644                                         lock_type = READ_LOCK;
3645                                         break;
3646                                 case POSIX_LOCK_TYPE_WRITE:
3647                                         lock_type = WRITE_LOCK;
3648                                         break;
3649                                 case POSIX_LOCK_TYPE_UNLOCK:
3650                                 default:
3651                                         /* There's no point in asking for an unlock... */
3652                                         talloc_destroy(data_ctx);
3653                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3654                         }
3655
3656                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3657 #if defined(HAVE_LONGLONG)
3658                         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3659                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3660                         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3661                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3662 #else /* HAVE_LONGLONG */
3663                         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3664                         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3665 #endif /* HAVE_LONGLONG */
3666
3667                         status = query_lock(fsp,
3668                                         &lock_pid,
3669                                         &count,
3670                                         &offset,
3671                                         &lock_type,
3672                                         POSIX_LOCK);
3673
3674                         if (ERROR_WAS_LOCK_DENIED(status)) {
3675                                 /* Here we need to report who has it locked... */
3676                                 data_size = POSIX_LOCK_DATA_SIZE;
3677
3678                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3679                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3680                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3681 #if defined(HAVE_LONGLONG)
3682                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3683                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3684                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3685                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3686 #else /* HAVE_LONGLONG */
3687                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3688                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3689 #endif /* HAVE_LONGLONG */
3690
3691                         } else if (NT_STATUS_IS_OK(status)) {
3692                                 /* For success we just return a copy of what we sent
3693                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3694                                 data_size = POSIX_LOCK_DATA_SIZE;
3695                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3696                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3697                         } else {
3698                                 return ERROR_NT(status);
3699                         }
3700                         break;
3701                 }
3702
3703                 default:
3704                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3705         }
3706
3707         send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3708
3709         return(-1);
3710 }
3711
3712 /****************************************************************************
3713  Set a hard link (called by UNIX extensions and by NT rename with HARD link
3714  code.
3715 ****************************************************************************/
3716
3717 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
3718 {
3719         SMB_STRUCT_STAT sbuf1, sbuf2;
3720         pstring last_component_oldname;
3721         pstring last_component_newname;
3722         NTSTATUS status = NT_STATUS_OK;
3723
3724         ZERO_STRUCT(sbuf1);
3725         ZERO_STRUCT(sbuf2);
3726
3727         status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
3728         if (!NT_STATUS_IS_OK(status)) {
3729                 return status;
3730         }
3731
3732         /* source must already exist. */
3733         if (!VALID_STAT(sbuf1)) {
3734                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3735         }
3736
3737         status = check_name(conn, oldname);
3738         if (!NT_STATUS_IS_OK(status)) {
3739                 return NT_STATUS_ACCESS_DENIED;
3740         }
3741
3742         status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
3743         if (!NT_STATUS_IS_OK(status)) {
3744                 return status;
3745         }
3746
3747         /* Disallow if newname already exists. */
3748         if (VALID_STAT(sbuf2)) {
3749                 return NT_STATUS_OBJECT_NAME_COLLISION;
3750         }
3751
3752         status = check_name(conn, newname);
3753         if (!NT_STATUS_IS_OK(status)) {
3754                 return NT_STATUS_ACCESS_DENIED;
3755         }
3756
3757         /* No links from a directory. */
3758         if (S_ISDIR(sbuf1.st_mode)) {
3759                 return NT_STATUS_FILE_IS_A_DIRECTORY;
3760         }
3761
3762         /* Ensure this is within the share. */
3763         status = reduce_name(conn, oldname);
3764         if (!NT_STATUS_IS_OK(status)) {
3765                 return status;
3766         }
3767
3768         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3769
3770         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3771                 status = map_nt_error_from_unix(errno);
3772                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3773                                 nt_errstr(status), newname, oldname));
3774         }
3775
3776         return status;
3777 }
3778
3779 /****************************************************************************
3780  Deal with setting the time from any of the setfilepathinfo functions.
3781 ****************************************************************************/
3782
3783 static NTSTATUS smb_set_file_time(connection_struct *conn,
3784                                 files_struct *fsp,
3785                                 const char *fname,
3786                                 const SMB_STRUCT_STAT *psbuf,
3787                                 struct utimbuf tvs)
3788 {
3789         uint32 action =
3790                 FILE_NOTIFY_CHANGE_LAST_ACCESS
3791                 |FILE_NOTIFY_CHANGE_LAST_WRITE;
3792
3793         
3794         if (!VALID_STAT(*psbuf)) {
3795                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3796         }
3797
3798         /* get some defaults (no modifications) if any info is zero or -1. */
3799         if (null_mtime(tvs.actime)) {
3800                 tvs.actime = psbuf->st_atime;
3801                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3802         }
3803
3804         if (null_mtime(tvs.modtime)) {
3805                 tvs.modtime = psbuf->st_mtime;
3806                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3807         }
3808
3809         DEBUG(6,("smb_set_file_time: actime: %s " , ctime(&tvs.actime)));
3810         DEBUG(6,("smb_set_file_time: modtime: %s ", ctime(&tvs.modtime)));
3811
3812         /*
3813          * Try and set the times of this file if
3814          * they are different from the current values.
3815          */
3816
3817         if (psbuf->st_mtime == tvs.modtime && psbuf->st_atime == tvs.actime) {
3818                 return NT_STATUS_OK;
3819         }
3820
3821         if(fsp != NULL) {
3822                 /*
3823                  * This was a setfileinfo on an open file.
3824                  * NT does this a lot. We also need to 
3825                  * set the time here, as it can be read by 
3826                  * FindFirst/FindNext and with the patch for bug #2045
3827                  * in smbd/fileio.c it ensures that this timestamp is
3828                  * kept sticky even after a write. We save the request
3829                  * away and will set it on file close and after a write. JRA.
3830                  */
3831
3832                 if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
3833                         DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
3834                         fsp_set_pending_modtime(fsp, tvs.modtime);
3835                 }
3836
3837         }
3838         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3839
3840         if(file_utime(conn, fname, &tvs)!=0) {
3841                 return map_nt_error_from_unix(errno);
3842         }
3843         if (action != 0) {
3844                 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
3845         }
3846         return NT_STATUS_OK;
3847 }
3848
3849 /****************************************************************************
3850  Deal with setting the dosmode from any of the setfilepathinfo functions.
3851 ****************************************************************************/
3852
3853 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
3854                                 const char *fname,
3855                                 SMB_STRUCT_STAT *psbuf,
3856                                 uint32 dosmode)
3857 {
3858         if (!VALID_STAT(*psbuf)) {
3859                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3860         }
3861
3862         if (dosmode) {
3863                 if (S_ISDIR(psbuf->st_mode)) {
3864                         dosmode |= aDIR;
3865                 } else {
3866                         dosmode &= ~aDIR;
3867                 }
3868         }
3869
3870         DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
3871
3872         /* check the mode isn't different, before changing it */
3873         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
3874
3875                 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
3876                                         fname, (unsigned int)dosmode ));
3877
3878                 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
3879                         DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
3880                                                 fname, strerror(errno)));
3881                         return map_nt_error_from_unix(errno);
3882                 }
3883         }
3884         return NT_STATUS_OK;
3885 }
3886
3887 /****************************************************************************
3888  Deal with setting the size from any of the setfilepathinfo functions.
3889 ****************************************************************************/
3890
3891 static NTSTATUS smb_set_file_size(connection_struct *conn,
3892                                 files_struct *fsp,
3893                                 const char *fname,
3894                                 SMB_STRUCT_STAT *psbuf,
3895                                 SMB_OFF_T size)
3896 {
3897         NTSTATUS status = NT_STATUS_OK;
3898         files_struct *new_fsp = NULL;
3899
3900         if (!VALID_STAT(*psbuf)) {
3901                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3902         }
3903
3904         DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
3905
3906         if (size == get_file_size(*psbuf)) {
3907                 return NT_STATUS_OK;
3908         }
3909
3910         DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
3911                 fname, (double)size ));
3912
3913         if (fsp && fsp->fh->fd != -1) {
3914                 /* Handle based call. */
3915                 if (vfs_set_filelen(fsp, size) == -1) {
3916                         return map_nt_error_from_unix(errno);
3917                 }
3918                 return NT_STATUS_OK;
3919         }
3920
3921         status = open_file_ntcreate(conn, fname, psbuf,
3922                                 FILE_WRITE_DATA,
3923                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
3924                                 FILE_OPEN,
3925                                 0,
3926                                 FILE_ATTRIBUTE_NORMAL,
3927                                 FORCE_OPLOCK_BREAK_TO_NONE,
3928                                 NULL, &new_fsp);
3929         
3930         if (!NT_STATUS_IS_OK(status)) {
3931                 /* NB. We check for open_was_deferred in the caller. */
3932                 return status;
3933         }
3934
3935         if (vfs_set_filelen(new_fsp, size) == -1) {
3936                 status = map_nt_error_from_unix(errno);
3937                 close_file(new_fsp,NORMAL_CLOSE);
3938                 return status;
3939         }
3940
3941         close_file(new_fsp,NORMAL_CLOSE);
3942         return NT_STATUS_OK;
3943 }
3944
3945 /****************************************************************************
3946  Deal with SMB_INFO_SET_EA.
3947 ****************************************************************************/
3948
3949 static NTSTATUS smb_info_set_ea(connection_struct *conn,
3950                                 const char *pdata,
3951                                 int total_data,
3952                                 files_struct *fsp,
3953                                 const char *fname)
3954 {
3955         struct ea_list *ea_list = NULL;
3956         TALLOC_CTX *ctx = NULL;
3957         NTSTATUS status = NT_STATUS_OK;
3958
3959         if (total_data < 10) {
3960
3961                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3962                    length. They seem to have no effect. Bug #3212. JRA */
3963
3964                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3965                         /* We're done. We only get EA info in this call. */
3966                         return NT_STATUS_OK;
3967                 }
3968
3969                 return NT_STATUS_INVALID_PARAMETER;
3970         }
3971
3972         if (IVAL(pdata,0) > total_data) {
3973                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
3974                         IVAL(pdata,0), (unsigned int)total_data));
3975                 return NT_STATUS_INVALID_PARAMETER;
3976         }
3977
3978         ctx = talloc_init("SMB_INFO_SET_EA");
3979         if (!ctx) {
3980                 return NT_STATUS_NO_MEMORY;
3981         }
3982         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3983         if (!ea_list) {
3984                 talloc_destroy(ctx);
3985                 return NT_STATUS_INVALID_PARAMETER;
3986         }
3987         status = set_ea(conn, fsp, fname, ea_list);
3988         talloc_destroy(ctx);
3989
3990         return status;
3991 }
3992
3993 /****************************************************************************
3994  Deal with SMB_SET_FILE_DISPOSITION_INFO.
3995 ****************************************************************************/
3996
3997 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
3998                                 const char *pdata,
3999                                 int total_data,
4000                                 files_struct *fsp,
4001                                 const char *fname,
4002                                 SMB_STRUCT_STAT *psbuf)
4003 {
4004         NTSTATUS status = NT_STATUS_OK;
4005         BOOL delete_on_close;
4006         uint32 dosmode = 0;
4007
4008         if (total_data < 1) {
4009                 return NT_STATUS_INVALID_PARAMETER;
4010         }
4011
4012         if (fsp == NULL) {
4013                 return NT_STATUS_INVALID_HANDLE;
4014         }
4015
4016         delete_on_close = (CVAL(pdata,0) ? True : False);
4017         dosmode = dos_mode(conn, fname, psbuf);
4018
4019         status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4020  
4021         if (!NT_STATUS_IS_OK(status)) {
4022                 return status;
4023         }
4024
4025         /* The set is across all open files on this dev/inode pair. */
4026         if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4027                 return NT_STATUS_ACCESS_DENIED;
4028         }
4029         return NT_STATUS_OK;
4030 }
4031
4032 /****************************************************************************
4033  Deal with SMB_FILE_POSITION_INFORMATION.
4034 ****************************************************************************/
4035
4036 static NTSTATUS smb_file_position_information(connection_struct *conn,
4037                                 const char *pdata,
4038                                 int total_data,
4039                                 files_struct *fsp)
4040 {
4041         SMB_BIG_UINT position_information;
4042
4043         if (total_data < 8) {
4044                 return NT_STATUS_INVALID_PARAMETER;
4045         }
4046
4047         if (fsp == NULL) {
4048                 /* Ignore on pathname based set. */
4049                 return NT_STATUS_OK;
4050         }
4051
4052         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4053 #ifdef LARGE_SMB_OFF_T
4054         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4055 #else /* LARGE_SMB_OFF_T */
4056         if (IVAL(pdata,4) != 0) {
4057                 /* more than 32 bits? */
4058                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4059         }
4060 #endif /* LARGE_SMB_OFF_T */
4061
4062         DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4063                 fsp->fsp_name, (double)position_information ));
4064         fsp->fh->position_information = position_information;
4065         return NT_STATUS_OK;
4066 }
4067
4068 /****************************************************************************
4069  Deal with SMB_FILE_MODE_INFORMATION.
4070 ****************************************************************************/
4071
4072 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4073                                 const char *pdata,
4074                                 int total_data)
4075 {
4076         uint32 mode;
4077
4078         if (total_data < 4) {
4079                 return NT_STATUS_INVALID_PARAMETER;
4080         }
4081         mode = IVAL(pdata,0);
4082         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4083                 return NT_STATUS_INVALID_PARAMETER;
4084         }
4085         return NT_STATUS_OK;
4086 }
4087
4088 /****************************************************************************
4089  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4090 ****************************************************************************/
4091
4092 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4093                                 char *inbuf,
4094                                 const char *pdata,
4095                                 int total_data,
4096                                 const char *fname)
4097 {
4098         pstring link_target;
4099         const char *newname = fname;
4100         NTSTATUS status = NT_STATUS_OK;
4101
4102         /* Set a symbolic link. */
4103         /* Don't allow this if follow links is false. */
4104
4105         if (total_data == 0) {
4106                 return NT_STATUS_INVALID_PARAMETER;
4107         }
4108
4109         if (!lp_symlinks(SNUM(conn))) {
4110                 return NT_STATUS_ACCESS_DENIED;
4111         }
4112
4113         srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4114
4115         /* !widelinks forces the target path to be within the share. */
4116         /* This means we can interpret the target as a pathname. */
4117         if (!lp_widelinks(SNUM(conn))) {
4118                 pstring rel_name;
4119                 char *last_dirp = NULL;
4120
4121                 unix_format(link_target);
4122                 if (*link_target == '/') {
4123                         /* No absolute paths allowed. */
4124                         return NT_STATUS_ACCESS_DENIED;
4125                 }
4126                 pstrcpy(rel_name, newname);
4127                 last_dirp = strrchr_m(rel_name, '/');
4128                 if (last_dirp) {
4129                         last_dirp[1] = '\0';
4130                 } else {
4131                         pstrcpy(rel_name, "./");
4132                 }
4133                 pstrcat(rel_name, link_target);
4134
4135                 status = check_name(conn, rel_name);
4136                 if (!NT_STATUS_IS_OK(status)) {
4137                         return status;
4138                 }
4139         }
4140
4141         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4142                         newname, link_target ));
4143
4144         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4145                 return map_nt_error_from_unix(errno);
4146         }
4147
4148         return NT_STATUS_OK;
4149 }
4150
4151 /****************************************************************************
4152  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4153 ****************************************************************************/
4154
4155 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4156                                 char *inbuf,
4157                                 const char *pdata,
4158                                 int total_data,
4159                                 pstring fname)
4160 {
4161         pstring oldname;
4162         NTSTATUS status = NT_STATUS_OK;
4163
4164         /* Set a hard link. */
4165         if (total_data == 0) {
4166                 return NT_STATUS_INVALID_PARAMETER;
4167         }
4168
4169         srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4170         if (!NT_STATUS_IS_OK(status)) {
4171                 return status;
4172         }
4173
4174         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4175                 fname, oldname));
4176
4177         return hardlink_internals(conn, oldname, fname);
4178 }
4179
4180 /****************************************************************************
4181  Deal with SMB_FILE_RENAME_INFORMATION.
4182 ****************************************************************************/
4183
4184 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4185                                 char *inbuf,
4186                                 char *outbuf,
4187                                 const char *pdata,
4188                                 int total_data,
4189                                 files_struct *fsp,
4190                                 pstring fname)
4191 {
4192         BOOL overwrite;
4193         /* uint32 root_fid; */  /* Not used */
4194         uint32 len;
4195         pstring newname;
4196         pstring base_name;
4197         NTSTATUS status = NT_STATUS_OK;
4198         char *p;
4199
4200         if (total_data < 13) {
4201                 return NT_STATUS_INVALID_PARAMETER;
4202         }
4203
4204         overwrite = (CVAL(pdata,0) ? True : False);
4205         /* root_fid = IVAL(pdata,4); */
4206         len = IVAL(pdata,8);
4207
4208         if (len > (total_data - 12) || (len == 0)) {
4209                 return NT_STATUS_INVALID_PARAMETER;
4210         }
4211
4212         srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4213         if (!NT_STATUS_IS_OK(status)) {
4214                 return status;
4215         }
4216
4217         /* Check the new name has no '/' characters. */
4218         if (strchr_m(newname, '/')) {
4219                 return NT_STATUS_NOT_SUPPORTED;
4220         }
4221
4222         RESOLVE_DFSPATH_STATUS(newname, conn, inbuf, outbuf);
4223
4224         /* Create the base directory. */
4225         pstrcpy(base_name, fname);
4226         p = strrchr_m(base_name, '/');
4227         if (p) {
4228                 *p = '\0';
4229         }
4230         /* Append the new name. */
4231         pstrcat(base_name, "/");
4232         pstrcat(base_name, newname);
4233
4234         if (fsp) {
4235                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4236                         fsp->fnum, fsp->fsp_name, base_name ));
4237                 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4238         } else {
4239                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4240                         fname, newname ));
4241                 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4242         }
4243
4244         return status;
4245 }
4246
4247 /****************************************************************************
4248  Deal with SMB_SET_POSIX_ACL.
4249 ****************************************************************************/
4250
4251 #if defined(HAVE_POSIX_ACLS)
4252 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4253                                 const char *pdata,
4254                                 int total_data,
4255                                 files_struct *fsp,
4256                                 const char *fname,
4257                                 SMB_STRUCT_STAT *psbuf)
4258 {
4259         uint16 posix_acl_version;
4260         uint16 num_file_acls;
4261         uint16 num_def_acls;
4262         BOOL valid_file_acls = True;
4263         BOOL valid_def_acls = True;
4264
4265         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4266                 return NT_STATUS_INVALID_PARAMETER;
4267         }
4268         posix_acl_version = SVAL(pdata,0);
4269         num_file_acls = SVAL(pdata,2);
4270         num_def_acls = SVAL(pdata,4);
4271
4272         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4273                 valid_file_acls = False;
4274                 num_file_acls = 0;
4275         }
4276
4277         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4278                 valid_def_acls = False;
4279                 num_def_acls = 0;
4280         }
4281
4282         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4283                 return NT_STATUS_INVALID_PARAMETER;
4284         }
4285
4286         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4287                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4288                 return NT_STATUS_INVALID_PARAMETER;
4289         }
4290
4291         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4292                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4293                 return map_nt_error_from_unix(errno);
4294         }
4295
4296         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4297                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
4298                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4299                 return map_nt_error_from_unix(errno);
4300         }
4301         return NT_STATUS_OK;
4302 }
4303 #endif
4304
4305 /****************************************************************************
4306  Deal with SMB_SET_POSIX_LOCK.
4307 ****************************************************************************/
4308
4309 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4310                                 char *inbuf,
4311                                 int length,
4312                                 const char *pdata,
4313                                 int total_data,
4314                                 files_struct *fsp)
4315 {
4316         SMB_BIG_UINT count;
4317         SMB_BIG_UINT offset;
4318         uint32 lock_pid;
4319         BOOL blocking_lock = False;
4320         enum brl_type lock_type;
4321         NTSTATUS status = NT_STATUS_OK;
4322
4323         if (fsp == NULL || fsp->fh->fd == -1) {
4324                 return NT_STATUS_INVALID_HANDLE;
4325         }
4326
4327         if (total_data != POSIX_LOCK_DATA_SIZE) {
4328                 return NT_STATUS_INVALID_PARAMETER;
4329         }
4330
4331         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4332                 case POSIX_LOCK_TYPE_READ:
4333                         lock_type = READ_LOCK;
4334                         break;
4335                 case POSIX_LOCK_TYPE_WRITE:
4336                         /* Return the right POSIX-mappable error code for files opened read-only. */
4337                         if (!fsp->can_write) {
4338                                 return NT_STATUS_INVALID_HANDLE;
4339                         }
4340                         lock_type = WRITE_LOCK;
4341                         break;
4342                 case POSIX_LOCK_TYPE_UNLOCK:
4343                         lock_type = UNLOCK_LOCK;
4344                         break;
4345                 default:
4346                         return NT_STATUS_INVALID_PARAMETER;
4347         }
4348
4349         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4350                 blocking_lock = False;
4351         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4352                 blocking_lock = True;
4353         } else {
4354                 return NT_STATUS_INVALID_PARAMETER;
4355         }
4356
4357         if (!lp_blocking_locks(SNUM(conn))) { 
4358                 blocking_lock = False;
4359         }
4360
4361         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4362 #if defined(HAVE_LONGLONG)
4363         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4364                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4365         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4366                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4367 #else /* HAVE_LONGLONG */
4368         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4369         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4370 #endif /* HAVE_LONGLONG */
4371
4372         if (lock_type == UNLOCK_LOCK) {
4373                 status = do_unlock(fsp,
4374                                 lock_pid,
4375                                 count,
4376                                 offset,
4377                                 POSIX_LOCK);
4378         } else {
4379                 struct byte_range_lock *br_lck = do_lock(fsp,
4380                                                         lock_pid,
4381                                                         count,
4382                                                         offset,
4383                                                         lock_type,
4384                                                         POSIX_LOCK,
4385                                                         blocking_lock,
4386                                                         &status);
4387
4388                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4389                         /*
4390                          * A blocking lock was requested. Package up
4391                          * this smb into a queued request and push it
4392                          * onto the blocking lock queue.
4393                          */
4394                         if(push_blocking_lock_request(br_lck,
4395                                                 inbuf, length,
4396                                                 fsp,
4397                                                 -1, /* infinite timeout. */
4398                                                 0,
4399                                                 lock_pid,
4400                                                 lock_type,
4401                                                 POSIX_LOCK,
4402                                                 offset,
4403                                                 count)) {
4404                                 TALLOC_FREE(br_lck);
4405                                 return status;
4406                         }
4407                 }
4408                 TALLOC_FREE(br_lck);
4409         }
4410
4411         return status;
4412 }
4413
4414 /****************************************************************************
4415  Deal with SMB_INFO_STANDARD.
4416 ****************************************************************************/
4417
4418 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4419                                         const char *pdata,
4420                                         int total_data,
4421                                         files_struct *fsp,
4422                                         const char *fname,
4423                                         const SMB_STRUCT_STAT *psbuf)
4424 {
4425         struct utimbuf tvs;
4426
4427         if (total_data < 12) {
4428                 return NT_STATUS_INVALID_PARAMETER;
4429         }
4430
4431         /* access time */
4432         tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
4433         /* write time */
4434         tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
4435
4436         return smb_set_file_time(conn,
4437                                 fsp,
4438                                 fname,
4439                                 psbuf,
4440                                 tvs);
4441 }
4442
4443 /****************************************************************************
4444  Deal with SMB_SET_FILE_BASIC_INFO.
4445 ****************************************************************************/
4446
4447 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4448                                         const char *pdata,
4449                                         int total_data,
4450                                         files_struct *fsp,
4451                                         const char *fname,
4452                                         SMB_STRUCT_STAT *psbuf)
4453 {
4454         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4455         time_t write_time;
4456         time_t changed_time;
4457         uint32 dosmode = 0;
4458         struct utimbuf tvs;
4459         NTSTATUS status = NT_STATUS_OK;
4460
4461         if (total_data < 36) {
4462                 return NT_STATUS_INVALID_PARAMETER;
4463         }
4464
4465         /* Set the attributes */
4466         dosmode = IVAL(pdata,32);
4467         status = smb_set_file_dosmode(conn,
4468                                         fname,
4469                                         psbuf,
4470                                         dosmode);
4471         if (!NT_STATUS_IS_OK(status)) {
4472                 return status;
4473         }
4474
4475         /* Ignore create time at offset pdata. */
4476
4477         /* access time */
4478         tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+8));
4479
4480         write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16));
4481         changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24));
4482
4483         tvs.modtime = MIN(write_time, changed_time);
4484
4485         if (write_time > tvs.modtime && write_time != (time_t)-1) {
4486                 tvs.modtime = write_time;
4487         }
4488         /* Prefer a defined time to an undefined one. */
4489         if (null_mtime(tvs.modtime)) {
4490                 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
4491         }
4492
4493         return smb_set_file_time(conn,
4494                                 fsp,
4495                                 fname,
4496                                 psbuf,
4497                                 tvs);
4498 }
4499
4500 /****************************************************************************
4501  Deal with SMB_SET_FILE_ALLOCATION_INFO.
4502 ****************************************************************************/
4503
4504 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4505                                         const char *pdata,
4506                                         int total_data,
4507                                         files_struct *fsp,
4508                                         const char *fname,
4509                                         SMB_STRUCT_STAT *psbuf)
4510 {
4511         SMB_BIG_UINT allocation_size = 0;
4512         NTSTATUS status = NT_STATUS_OK;
4513         files_struct *new_fsp = NULL;
4514
4515         if (!VALID_STAT(*psbuf)) {
4516                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4517         }
4518
4519         if (total_data < 8) {
4520                 return NT_STATUS_INVALID_PARAMETER;
4521         }
4522
4523         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4524 #ifdef LARGE_SMB_OFF_T
4525         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4526 #else /* LARGE_SMB_OFF_T */
4527         if (IVAL(pdata,4) != 0) {
4528                 /* more than 32 bits? */
4529                 return NT_STATUS_INVALID_PARAMETER;
4530         }
4531 #endif /* LARGE_SMB_OFF_T */
4532
4533         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4534                         fname, (double)allocation_size ));
4535
4536         if (allocation_size) {
4537                 allocation_size = smb_roundup(conn, allocation_size);
4538         }
4539
4540         if(allocation_size == get_file_size(*psbuf)) {
4541                 return NT_STATUS_OK;
4542         }
4543  
4544         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4545                         fname, (double)allocation_size ));
4546  
4547         if (fsp && fsp->fh->fd != -1) {
4548                 /* Open file handle. */
4549                 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4550                         return map_nt_error_from_unix(errno);
4551                 }
4552                 return NT_STATUS_OK;
4553         }
4554
4555         /* Pathname or stat or directory file. */
4556
4557         status = open_file_ntcreate(conn, fname, psbuf,
4558                                 FILE_WRITE_DATA,
4559                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4560                                 FILE_OPEN,
4561                                 0,
4562                                 FILE_ATTRIBUTE_NORMAL,
4563                                 FORCE_OPLOCK_BREAK_TO_NONE,
4564                                 NULL, &new_fsp);
4565  
4566         if (!NT_STATUS_IS_OK(status)) {
4567                 /* NB. We check for open_was_deferred in the caller. */
4568                 return status;
4569         }
4570         if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4571                 status = map_nt_error_from_unix(errno);
4572                 close_file(new_fsp,NORMAL_CLOSE);
4573                 return status;
4574         }
4575
4576         close_file(new_fsp,NORMAL_CLOSE);
4577         return NT_STATUS_OK;
4578 }
4579
4580 /****************************************************************************
4581  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4582 ****************************************************************************/
4583
4584 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4585                                         const char *pdata,
4586                                         int total_data,
4587                                         files_struct *fsp,
4588                                         const char *fname,
4589                                         SMB_STRUCT_STAT *psbuf)
4590 {
4591         SMB_OFF_T size;
4592
4593         if (total_data < 8) {
4594                 return NT_STATUS_INVALID_PARAMETER;
4595         }
4596
4597         size = IVAL(pdata,0);
4598 #ifdef LARGE_SMB_OFF_T
4599         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4600 #else /* LARGE_SMB_OFF_T */
4601         if (IVAL(pdata,4) != 0) {
4602                 /* more than 32 bits? */
4603                 return NT_STATUS_INVALID_PARAMETER;
4604         }
4605 #endif /* LARGE_SMB_OFF_T */
4606         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4607                 "file %s to %.0f\n", fname, (double)size ));
4608
4609         return smb_set_file_size(conn,
4610                                 fsp,
4611                                 fname,
4612                                 psbuf,
4613                                 size);
4614 }
4615
4616 /****************************************************************************
4617  Allow a UNIX info mknod.
4618 ****************************************************************************/
4619
4620 static NTSTATUS smb_unix_mknod(connection_struct *conn,
4621                                         const char *pdata,
4622                                         int total_data,
4623                                         const char *fname,
4624                                         SMB_STRUCT_STAT *psbuf)
4625 {
4626         uint32 file_type = IVAL(pdata,56);
4627 #if defined(HAVE_MAKEDEV)
4628         uint32 dev_major = IVAL(pdata,60);
4629         uint32 dev_minor = IVAL(pdata,68);
4630 #endif
4631         SMB_DEV_T dev = (SMB_DEV_T)0;
4632         uint32 raw_unixmode = IVAL(pdata,84);
4633         NTSTATUS status;
4634         mode_t unixmode;
4635
4636         if (total_data < 100) {
4637                 return NT_STATUS_INVALID_PARAMETER;
4638         }
4639
4640         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
4641         if (!NT_STATUS_IS_OK(status)) {
4642                 return status;
4643         }
4644
4645 #if defined(HAVE_MAKEDEV)
4646         dev = makedev(dev_major, dev_minor);
4647 #endif
4648
4649         switch (file_type) {
4650 #if defined(S_IFIFO)
4651                 case UNIX_TYPE_FIFO:
4652                         unixmode |= S_IFIFO;
4653                         break;
4654 #endif
4655 #if defined(S_IFSOCK)
4656                 case UNIX_TYPE_SOCKET:
4657                         unixmode |= S_IFSOCK;
4658                         break;
4659 #endif
4660 #if defined(S_IFCHR)
4661                 case UNIX_TYPE_CHARDEV:
4662                         unixmode |= S_IFCHR;
4663                         break;
4664 #endif
4665 #if defined(S_IFBLK)
4666                 case UNIX_TYPE_BLKDEV:
4667                         unixmode |= S_IFBLK;
4668                         break;
4669 #endif
4670                 default:
4671                         return NT_STATUS_INVALID_PARAMETER;
4672         }
4673
4674         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4675 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
4676
4677         /* Ok - do the mknod. */
4678         if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
4679                 return map_nt_error_from_unix(errno);
4680         }
4681
4682         /* If any of the other "set" calls fail we
4683          * don't want to end up with a half-constructed mknod.
4684          */
4685
4686         if (lp_inherit_perms(SNUM(conn))) {
4687                 inherit_access_acl(
4688                         conn, parent_dirname(fname),
4689                         fname, unixmode);
4690         }
4691
4692         if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
4693                 status = map_nt_error_from_unix(errno);
4694                 SMB_VFS_UNLINK(conn,fname);
4695                 return status;
4696         }
4697         return NT_STATUS_OK;
4698 }
4699
4700 /****************************************************************************
4701  Deal with SMB_SET_FILE_UNIX_BASIC.
4702 ****************************************************************************/
4703
4704 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
4705                                         const char *pdata,
4706                                         int total_data,
4707                                         files_struct *fsp,
4708                                         const char *fname,
4709                                         SMB_STRUCT_STAT *psbuf)
4710 {
4711         struct utimbuf tvs;
4712         uint32 raw_unixmode;
4713         mode_t unixmode;
4714         SMB_OFF_T size = 0;
4715         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
4716         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
4717         NTSTATUS status = NT_STATUS_OK;
4718         BOOL delete_on_fail = False;
4719         enum perm_type ptype;
4720
4721         if (total_data < 100) {
4722                 return NT_STATUS_INVALID_PARAMETER;
4723         }
4724
4725         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4726            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4727                 size=IVAL(pdata,0); /* first 8 Bytes are size */
4728 #ifdef LARGE_SMB_OFF_T
4729                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4730 #else /* LARGE_SMB_OFF_T */
4731                 if (IVAL(pdata,4) != 0) {
4732                         /* more than 32 bits? */
4733                         return NT_STATUS_INVALID_PARAMETER;
4734                 }
4735 #endif /* LARGE_SMB_OFF_T */
4736         }
4737
4738         tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+24)); /* access_time */
4739         tvs.modtime = convert_timespec_to_time_t(interpret_long_date(pdata+32)); /* modification_time */
4740         set_owner = (uid_t)IVAL(pdata,40);
4741         set_grp = (gid_t)IVAL(pdata,48);
4742         raw_unixmode = IVAL(pdata,84);
4743
4744         if (VALID_STAT(*psbuf)) {
4745                 if (S_ISDIR(psbuf->st_mode)) {
4746                         ptype = PERM_EXISTING_DIR;
4747                 } else {
4748                         ptype = PERM_EXISTING_FILE;
4749                 }
4750         } else {
4751                 ptype = PERM_NEW_FILE;
4752         }
4753
4754         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
4755         if (!NT_STATUS_IS_OK(status)) {
4756                 return status;
4757         }
4758
4759         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
4760 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4761                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4762
4763         if (!VALID_STAT(*psbuf)) {
4764                 /*
4765                  * The only valid use of this is to create character and block
4766                  * devices, and named pipes. This is deprecated (IMHO) and 
4767                  * a new info level should be used for mknod. JRA.
4768                  */
4769
4770                 status = smb_unix_mknod(conn,
4771                                         pdata,
4772                                         total_data,
4773                                         fname,
4774                                         psbuf);
4775                 if (!NT_STATUS_IS_OK(status)) {
4776                         return status;
4777                 }
4778
4779                 /* Ensure we don't try and change anything else. */
4780                 raw_unixmode = SMB_MODE_NO_CHANGE;
4781                 size = get_file_size(*psbuf);
4782                 tvs.modtime = psbuf->st_mtime;
4783                 tvs.actime = psbuf->st_atime;
4784                 /* 
4785                  * We continue here as we might want to change the 
4786                  * owner uid/gid.
4787                  */
4788                 delete_on_fail = True;
4789         }
4790
4791         /*
4792          * Deal with the UNIX specific mode set.
4793          */
4794
4795         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4796                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4797                         (unsigned int)unixmode, fname ));
4798                 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
4799                         return map_nt_error_from_unix(errno);
4800                 }
4801         }
4802
4803         /*
4804          * Deal with the UNIX specific uid set.
4805          */
4806
4807         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
4808                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4809                         (unsigned int)set_owner, fname ));
4810                 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
4811                         status = map_nt_error_from_unix(errno);
4812                         if (delete_on_fail) {
4813                                 SMB_VFS_UNLINK(conn,fname);
4814                         }
4815                         return status;
4816                 }
4817         }
4818
4819         /*
4820          * Deal with the UNIX specific gid set.
4821          */
4822
4823         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
4824                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4825                         (unsigned int)set_owner, fname ));
4826                 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
4827                         status = map_nt_error_from_unix(errno);
4828                         if (delete_on_fail) {
4829                                 SMB_VFS_UNLINK(conn,fname);
4830                         }
4831                         return status;
4832                 }
4833         }
4834
4835         /* Deal with any size changes. */
4836
4837         status = smb_set_file_size(conn,
4838                                 fsp,
4839                                 fname,
4840                                 psbuf,
4841                                 size);
4842         if (!NT_STATUS_IS_OK(status)) {
4843                 return status;
4844         }
4845
4846         /* Deal with any time changes. */
4847
4848         return smb_set_file_time(conn,
4849                                 fsp,
4850                                 fname,
4851                                 psbuf,
4852                                 tvs);
4853 }
4854
4855 /****************************************************************************
4856  Create a directory with POSIX semantics.
4857 ****************************************************************************/
4858
4859 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
4860                                 char **ppdata,
4861                                 int total_data,
4862                                 const char *fname,
4863                                 SMB_STRUCT_STAT *psbuf,
4864                                 int *pdata_return_size)
4865 {
4866         NTSTATUS status;
4867         uint32 raw_unixmode;
4868         uint32 mod_unixmode;
4869         mode_t unixmode;
4870         files_struct *fsp;
4871         const char *pdata = *ppdata;
4872
4873         if (total_data < 10) {
4874                 return NT_STATUS_INVALID_PARAMETER;
4875         }
4876
4877         raw_unixmode = IVAL(pdata,8);
4878         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
4879         if (!NT_STATUS_IS_OK(status)) {
4880                 return status;
4881         }
4882
4883         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
4884
4885         status = open_directory(conn,
4886                                 fname,
4887                                 psbuf,
4888                                 FILE_READ_ATTRIBUTES, /* Just a stat open */
4889                                 FILE_SHARE_NONE, /* Ignored for stat opens */
4890                                 FILE_CREATE,
4891                                 0,
4892                                 mod_unixmode,
4893                                 NULL,
4894                                 &fsp);
4895
4896         if (NT_STATUS_IS_OK(status)) {
4897                 close_file(fsp, NORMAL_CLOSE);
4898         }
4899
4900         *pdata_return_size = 6;
4901         /* Realloc the data size */
4902         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
4903         if (*ppdata == NULL) {
4904                 return NT_STATUS_NO_MEMORY;
4905         }
4906
4907         SSVAL(pdata,0,NO_OPLOCK_RETURN);
4908         SSVAL(pdata,2,0);
4909         SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
4910
4911         return status;
4912 }
4913
4914 /****************************************************************************
4915  Open/Create a file with POSIX semantics.
4916 ****************************************************************************/
4917
4918 static NTSTATUS smb_posix_open(connection_struct *conn,
4919                                 char **ppdata,
4920                                 int total_data,
4921                                 const char *fname,
4922                                 SMB_STRUCT_STAT *psbuf,
4923                                 int *pdata_return_size)
4924 {
4925         BOOL extended_oplock_granted = False;
4926         const char *pdata = *ppdata;
4927         uint32 flags = 0;
4928         uint32 wire_open_mode = 0;
4929         uint32 raw_unixmode = 0;
4930         uint32 mod_unixmode = 0;
4931         uint32 create_disp = 0;
4932         uint32 access_mask = 0;
4933         uint32 create_options = 0;
4934         NTSTATUS status = NT_STATUS_OK;
4935         mode_t unixmode = (mode_t)0;
4936         files_struct *fsp = NULL;
4937         int oplock_request = 0;
4938         int info = 0;
4939
4940         if (total_data < 14) {
4941                 return NT_STATUS_INVALID_PARAMETER;
4942         }
4943
4944         flags = IVAL(pdata,0);
4945         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
4946         if (oplock_request) {
4947                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
4948         }
4949
4950         wire_open_mode = IVAL(pdata,4);
4951
4952         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
4953                 return smb_posix_mkdir(conn,
4954                                         ppdata,
4955                                         total_data,
4956                                         fname,
4957                                         psbuf,
4958                                         pdata_return_size);
4959         }
4960
4961         switch (wire_open_mode & SMB_ACCMODE) {
4962                 case SMB_O_RDONLY:
4963                         access_mask = FILE_READ_DATA;
4964                         break;
4965                 case SMB_O_WRONLY:
4966                         access_mask = FILE_WRITE_DATA;
4967                         break;
4968                 case SMB_O_RDWR:
4969                         access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
4970                         break;
4971                 default:
4972                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
4973                                 (unsigned int)wire_open_mode ));
4974                         return NT_STATUS_INVALID_PARAMETER;
4975         }
4976
4977         wire_open_mode &= ~SMB_ACCMODE;
4978
4979         if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
4980                 create_disp = FILE_CREATE;
4981         } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
4982                 create_disp = FILE_OVERWRITE_IF;
4983         } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
4984                 create_disp = FILE_OPEN_IF;
4985         } else {
4986                 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
4987                         (unsigned int)wire_open_mode ));
4988                 return NT_STATUS_INVALID_PARAMETER;
4989         }
4990
4991         raw_unixmode = IVAL(pdata,8);
4992         status = unix_perms_from_wire(conn,
4993                                 psbuf,
4994                                 raw_unixmode,
4995                                 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
4996                                 &unixmode);
4997
4998         if (!NT_STATUS_IS_OK(status)) {
4999                 return status;
5000         }
5001
5002         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5003
5004         if (wire_open_mode & SMB_O_SYNC) {
5005                 create_options |= FILE_WRITE_THROUGH;
5006         }
5007         if (wire_open_mode & SMB_O_APPEND) {
5008                 access_mask |= FILE_APPEND_DATA;
5009         }
5010         if (wire_open_mode & SMB_O_DIRECT) {
5011                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5012         }
5013
5014         status = open_file_ntcreate(conn,
5015                                 fname,
5016                                 psbuf,
5017                                 access_mask,
5018                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5019                                 create_disp,
5020                                 0,              /* no create options yet. */
5021                                 mod_unixmode,
5022                                 oplock_request,
5023                                 &info,
5024                                 &fsp);
5025
5026         if (!NT_STATUS_IS_OK(status)) {
5027                 return status;
5028         }
5029
5030         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5031                 extended_oplock_granted = True;
5032         }
5033
5034         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5035                 extended_oplock_granted = True;
5036         }
5037
5038         *pdata_return_size = 6;
5039         /* Realloc the data size */
5040         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5041         if (*ppdata == NULL) {
5042                 close_file(fsp,ERROR_CLOSE);
5043                 return NT_STATUS_NO_MEMORY;
5044         }
5045
5046         if (extended_oplock_granted) {
5047                 if (flags & REQUEST_BATCH_OPLOCK) {
5048                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5049                 } else {
5050                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5051                 }
5052         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5053                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5054         } else {
5055                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5056         }
5057
5058         SSVAL(pdata,2,fsp->fnum);
5059         SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
5060         return NT_STATUS_OK;
5061 }
5062
5063 /****************************************************************************
5064  Delete a file with POSIX semantics.
5065 ****************************************************************************/
5066
5067 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5068                                 const char *pdata,
5069                                 int total_data,
5070                                 const char *fname,
5071                                 SMB_STRUCT_STAT *psbuf)
5072 {
5073         NTSTATUS status = NT_STATUS_OK;
5074         files_struct *fsp = NULL;
5075         int info = 0;
5076
5077         if (!VALID_STAT(*psbuf)) {
5078                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5079         }
5080
5081         if (VALID_STAT_OF_DIR(*psbuf)) {
5082                 status = open_directory(conn,
5083                                         fname,
5084                                         psbuf,
5085                                         DELETE_ACCESS,
5086                                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5087                                         FILE_OPEN,
5088                                         FILE_DELETE_ON_CLOSE,
5089                                         FILE_FLAG_POSIX_SEMANTICS|0777,
5090                                         &info,                          
5091                                         &fsp);
5092         } else {
5093                 status = open_file_ntcreate(conn,
5094                                 fname,
5095                                 psbuf,
5096                                 DELETE_ACCESS,
5097                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5098                                 FILE_OPEN,
5099                                 FILE_DELETE_ON_CLOSE,
5100                                 FILE_FLAG_POSIX_SEMANTICS|0777,
5101                                 INTERNAL_OPEN_ONLY,
5102                                 &info,
5103                                 &fsp);
5104         }
5105
5106         if (!NT_STATUS_IS_OK(status)) {
5107                 return status;
5108         }
5109         return close_file(fsp, NORMAL_CLOSE);
5110 }
5111
5112 /****************************************************************************
5113  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5114 ****************************************************************************/
5115
5116 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5117                                         unsigned int tran_call,
5118                                         char **pparams, int total_params, char **ppdata, int total_data,
5119                                         unsigned int max_data_bytes)
5120 {
5121         char *params = *pparams;
5122         char *pdata = *ppdata;
5123         uint16 info_level;
5124         SMB_STRUCT_STAT sbuf;
5125         pstring fname;
5126         files_struct *fsp = NULL;
5127         NTSTATUS status = NT_STATUS_OK;
5128         int data_return_size = 0;
5129
5130         if (!params) {
5131                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5132         }
5133
5134         ZERO_STRUCT(sbuf);
5135
5136         if (tran_call == TRANSACT2_SETFILEINFO) {
5137                 if (total_params < 4) {
5138                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5139                 }
5140
5141                 fsp = file_fsp(params,0);
5142                 info_level = SVAL(params,2);    
5143
5144                 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5145                         /*
5146                          * This is actually a SETFILEINFO on a directory
5147                          * handle (returned from an NT SMB). NT5.0 seems
5148                          * to do this call. JRA.
5149                          */
5150                         pstrcpy(fname, fsp->fsp_name);
5151                         if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5152                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5153                                 return UNIXERROR(ERRDOS,ERRbadpath);
5154                         }
5155                 } else if (fsp && fsp->print_file) {
5156                         /*
5157                          * Doing a DELETE_ON_CLOSE should cancel a print job.
5158                          */
5159                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5160                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5161
5162                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5163         
5164                                 SSVAL(params,0,0);
5165                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5166                                 return(-1);
5167                         } else
5168                                 return (UNIXERROR(ERRDOS,ERRbadpath));
5169             } else {
5170                         /*
5171                          * Original code - this is an open file.
5172                          */
5173                         CHECK_FSP(fsp,conn);
5174
5175                         pstrcpy(fname, fsp->fsp_name);
5176
5177                         if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5178                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5179                                 return(UNIXERROR(ERRDOS,ERRbadfid));
5180                         }
5181                 }
5182         } else {
5183                 /* set path info */
5184                 if (total_params < 7) {
5185                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5186                 }
5187
5188                 info_level = SVAL(params,0);    
5189                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5190                 if (!NT_STATUS_IS_OK(status)) {
5191                         return ERROR_NT(status);
5192                 }
5193                 status = unix_convert(conn, fname, False, NULL, &sbuf);
5194                 if (!NT_STATUS_IS_OK(status)) {
5195                         return ERROR_NT(status);
5196                 }
5197
5198                 /*
5199                  * For CIFS UNIX extensions the target name may not exist.
5200                  */
5201
5202                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
5203                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
5204                         return UNIXERROR(ERRDOS,ERRbadpath);
5205                 }    
5206
5207                 status = check_name(conn, fname);
5208                 if (!NT_STATUS_IS_OK(status)) {
5209                         return ERROR_NT(status);
5210                 }
5211
5212         }
5213
5214         if (!CAN_WRITE(conn)) {
5215                 return ERROR_DOS(ERRSRV,ERRaccess);
5216         }
5217
5218         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5219                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5220         }
5221
5222         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5223                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5224
5225         /* Realloc the parameter size */
5226         *pparams = (char *)SMB_REALLOC(*pparams,2);
5227         if (*pparams == NULL) {
5228                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5229         }
5230         params = *pparams;
5231
5232         SSVAL(params,0,0);
5233
5234         if (fsp && fsp->pending_modtime) {
5235                 /* the pending modtime overrides the current modtime */
5236                 sbuf.st_mtime = fsp->pending_modtime;
5237         }
5238
5239         switch (info_level) {
5240
5241                 case SMB_INFO_STANDARD:
5242                 {
5243                         status = smb_set_info_standard(conn,
5244                                         pdata,
5245                                         total_data,
5246                                         fsp,
5247                                         fname,
5248                                         &sbuf);
5249                         break;
5250                 }
5251
5252                 case SMB_INFO_SET_EA:
5253                 {
5254                         status = smb_info_set_ea(conn,
5255                                                 pdata,
5256                                                 total_data,
5257                                                 fsp,
5258                                                 fname);
5259                         break;
5260                 }
5261
5262                 case SMB_SET_FILE_BASIC_INFO:
5263                 case SMB_FILE_BASIC_INFORMATION:
5264                 {
5265                         status = smb_set_file_basic_info(conn,
5266                                                         pdata,
5267                                                         total_data,
5268                                                         fsp,
5269                                                         fname,
5270                                                         &sbuf);
5271                         break;
5272                 }
5273
5274                 case SMB_FILE_ALLOCATION_INFORMATION:
5275                 case SMB_SET_FILE_ALLOCATION_INFO:
5276                 {
5277                         status = smb_set_file_allocation_info(conn,
5278                                                                 pdata,
5279                                                                 total_data,
5280                                                                 fsp,
5281                                                                 fname,
5282                                                                 &sbuf);
5283                         break;
5284                 }
5285
5286                 case SMB_FILE_END_OF_FILE_INFORMATION:
5287                 case SMB_SET_FILE_END_OF_FILE_INFO:
5288                 {
5289                         status = smb_set_file_end_of_file_info(conn,
5290                                                                 pdata,
5291                                                                 total_data,
5292                                                                 fsp,
5293                                                                 fname,
5294                                                                 &sbuf);
5295                         break;
5296                 }
5297
5298                 case SMB_FILE_DISPOSITION_INFORMATION:
5299                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5300                 {
5301 #if 0
5302                         /* JRA - We used to just ignore this on a path ? 
5303                          * Shouldn't this be invalid level on a pathname
5304                          * based call ?
5305                          */
5306                         if (tran_call != TRANSACT2_SETFILEINFO) {
5307                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5308                         }
5309 #endif
5310                         status = smb_set_file_disposition_info(conn,
5311                                                 pdata,
5312                                                 total_data,
5313                                                 fsp,
5314                                                 fname,
5315                                                 &sbuf);
5316                         break;
5317                 }
5318
5319                 case SMB_FILE_POSITION_INFORMATION:
5320                 {
5321                         status = smb_file_position_information(conn,
5322                                                 pdata,
5323                                                 total_data,
5324                                                 fsp);
5325                         break;
5326                 }
5327
5328                 /* From tridge Samba4 : 
5329                  * MODE_INFORMATION in setfileinfo (I have no
5330                  * idea what "mode information" on a file is - it takes a value of 0,
5331                  * 2, 4 or 6. What could it be?).
5332                  */
5333
5334                 case SMB_FILE_MODE_INFORMATION:
5335                 {
5336                         status = smb_file_mode_information(conn,
5337                                                 pdata,
5338                                                 total_data);
5339                         break;
5340                 }
5341
5342                 /*
5343                  * CIFS UNIX extensions.
5344                  */
5345
5346                 case SMB_SET_FILE_UNIX_BASIC:
5347                 {
5348                         if (tran_call == TRANSACT2_SETFILEINFO) {
5349                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5350                         }
5351
5352                         status = smb_set_file_unix_basic(conn,
5353                                                         pdata,
5354                                                         total_data,
5355                                                         fsp,
5356                                                         fname,
5357                                                         &sbuf);
5358                         break;
5359                 }
5360
5361                 case SMB_SET_FILE_UNIX_LINK:
5362                 {
5363                         if (tran_call != TRANSACT2_SETPATHINFO) {
5364                                 /* We must have a pathname for this. */
5365                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5366                         }
5367                         status = smb_set_file_unix_link(conn,
5368                                                 inbuf,
5369                                                 pdata,
5370                                                 total_data,
5371                                                 fname);
5372                         break;
5373                 }
5374
5375                 case SMB_SET_FILE_UNIX_HLINK:
5376                 {
5377                         if (tran_call != TRANSACT2_SETPATHINFO) {
5378                                 /* We must have a pathname for this. */
5379                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5380                         }
5381                         status = smb_set_file_unix_hlink(conn,
5382                                                 inbuf,
5383                                                 pdata,
5384                                                 total_data,
5385                                                 fname);
5386                         break;
5387                 }
5388
5389                 case SMB_FILE_RENAME_INFORMATION:
5390                 {
5391                         status = smb_file_rename_information(conn,
5392                                                         inbuf,
5393                                                         outbuf,
5394                                                         pdata,
5395                                                         total_data,
5396                                                         fsp,
5397                                                         fname);
5398                         break;
5399                 }
5400
5401 #if defined(HAVE_POSIX_ACLS)
5402                 case SMB_SET_POSIX_ACL:
5403                 {
5404                         status = smb_set_posix_acl(conn,
5405                                                 pdata,
5406                                                 total_data,
5407                                                 fsp,
5408                                                 fname,
5409                                                 &sbuf);
5410                         break;
5411                 }
5412 #endif
5413
5414                 case SMB_SET_POSIX_LOCK:
5415                 {
5416                         if (tran_call == TRANSACT2_SETFILEINFO) {
5417                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5418                         }
5419                         status = smb_set_posix_lock(conn,
5420                                                 inbuf,
5421                                                 length,
5422                                                 pdata,
5423                                                 total_data,
5424                                                 fsp);
5425                         break;
5426                 }
5427
5428                 case SMB_POSIX_PATH_OPEN:
5429                 {
5430                         if (tran_call != TRANSACT2_SETPATHINFO) {
5431                                 /* We must have a pathname for this. */
5432                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5433                         }
5434
5435                         status = smb_posix_open(conn,
5436                                                 ppdata,
5437                                                 total_data,
5438                                                 fname,
5439                                                 &sbuf,
5440                                                 &data_return_size);
5441                         break;
5442                 }
5443
5444                 case SMB_POSIX_PATH_UNLINK:
5445                 {
5446                         if (tran_call != TRANSACT2_SETPATHINFO) {
5447                                 /* We must have a pathname for this. */
5448                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5449                         }
5450
5451                         status = smb_posix_unlink(conn,
5452                                                 pdata,
5453                                                 total_data,
5454                                                 fname,
5455                                                 &sbuf);
5456                         break;
5457                 }
5458
5459                 default:
5460                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5461         }
5462
5463         
5464         if (!NT_STATUS_IS_OK(status)) {
5465                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
5466                         /* We have re-scheduled this call. */
5467                         return -1;
5468                 }
5469                 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
5470                         /* We have re-scheduled this call. */
5471                         return -1;
5472                 }
5473                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5474                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5475                 }
5476                 return ERROR_NT(status);
5477         }
5478
5479         SSVAL(params,0,0);
5480         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
5481   
5482         return -1;
5483 }
5484
5485 /****************************************************************************
5486  Reply to a TRANS2_MKDIR (make directory with extended attributes).
5487 ****************************************************************************/
5488
5489 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5490                                         char **pparams, int total_params, char **ppdata, int total_data,
5491                                         unsigned int max_data_bytes)
5492 {
5493         char *params = *pparams;
5494         char *pdata = *ppdata;
5495         pstring directory;
5496         SMB_STRUCT_STAT sbuf;
5497         NTSTATUS status = NT_STATUS_OK;
5498         struct ea_list *ea_list = NULL;
5499
5500         if (!CAN_WRITE(conn))
5501                 return ERROR_DOS(ERRSRV,ERRaccess);
5502
5503         if (total_params < 5) {
5504                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5505         }
5506
5507         srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
5508         if (!NT_STATUS_IS_OK(status)) {
5509                 return ERROR_NT(status);
5510         }
5511
5512         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
5513
5514         status = unix_convert(conn, directory, False, NULL, &sbuf);
5515         if (!NT_STATUS_IS_OK(status)) {
5516                 return ERROR_NT(status);
5517         }
5518
5519         /* Any data in this call is an EA list. */
5520         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
5521                 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
5522         }
5523
5524         /*
5525          * OS/2 workplace shell seems to send SET_EA requests of "null"
5526          * length (4 bytes containing IVAL 4).
5527          * They seem to have no effect. Bug #3212. JRA.
5528          */
5529
5530         if (total_data != 4) {
5531                 if (total_data < 10) {
5532                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5533                 }
5534
5535                 if (IVAL(pdata,0) > total_data) {
5536                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
5537                                 IVAL(pdata,0), (unsigned int)total_data));
5538                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5539                 }
5540
5541                 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
5542                                        total_data - 4);
5543                 if (!ea_list) {
5544                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5545                 }
5546         } else if (IVAL(pdata,0) != 4) {
5547                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5548         }
5549
5550         status = check_name(conn, directory);
5551         if (!NT_STATUS_IS_OK(status)) {
5552                 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
5553                 return ERROR_NT(status);
5554         }
5555
5556         status = create_directory(conn, directory);
5557
5558         if (!NT_STATUS_IS_OK(status)) {
5559                 return ERROR_NT(status);
5560         }
5561   
5562         /* Try and set any given EA. */
5563         if (ea_list) {
5564                 status = set_ea(conn, NULL, directory, ea_list);
5565                 if (!NT_STATUS_IS_OK(status)) {
5566                         return ERROR_NT(status);
5567                 }
5568         }
5569
5570         /* Realloc the parameter and data sizes */
5571         *pparams = (char *)SMB_REALLOC(*pparams,2);
5572         if(*pparams == NULL) {
5573                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5574         }
5575         params = *pparams;
5576
5577         SSVAL(params,0,0);
5578
5579         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5580   
5581         return(-1);
5582 }
5583
5584 /****************************************************************************
5585  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
5586  We don't actually do this - we just send a null response.
5587 ****************************************************************************/
5588
5589 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5590                                         char **pparams, int total_params, char **ppdata, int total_data,
5591                                         unsigned int max_data_bytes)
5592 {
5593         static uint16 fnf_handle = 257;
5594         char *params = *pparams;
5595         uint16 info_level;
5596
5597         if (total_params < 6) {
5598                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5599         }
5600
5601         info_level = SVAL(params,4);
5602         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
5603
5604         switch (info_level) {
5605                 case 1:
5606                 case 2:
5607                         break;
5608                 default:
5609                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5610         }
5611
5612         /* Realloc the parameter and data sizes */
5613         *pparams = (char *)SMB_REALLOC(*pparams,6);
5614         if (*pparams == NULL) {
5615                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5616         }
5617         params = *pparams;
5618
5619         SSVAL(params,0,fnf_handle);
5620         SSVAL(params,2,0); /* No changes */
5621         SSVAL(params,4,0); /* No EA errors */
5622
5623         fnf_handle++;
5624
5625         if(fnf_handle == 0)
5626                 fnf_handle = 257;
5627
5628         send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
5629   
5630         return(-1);
5631 }
5632
5633 /****************************************************************************
5634  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
5635  changes). Currently this does nothing.
5636 ****************************************************************************/
5637
5638 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5639                                         char **pparams, int total_params, char **ppdata, int total_data,
5640                                         unsigned int max_data_bytes)
5641 {
5642         char *params = *pparams;
5643
5644         DEBUG(3,("call_trans2findnotifynext\n"));
5645
5646         /* Realloc the parameter and data sizes */
5647         *pparams = (char *)SMB_REALLOC(*pparams,4);
5648         if (*pparams == NULL) {
5649                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5650         }
5651         params = *pparams;
5652
5653         SSVAL(params,0,0); /* No changes */
5654         SSVAL(params,2,0); /* No EA errors */
5655
5656         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
5657   
5658         return(-1);
5659 }
5660
5661 /****************************************************************************
5662  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
5663 ****************************************************************************/
5664
5665 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
5666                                         char **pparams, int total_params, char **ppdata, int total_data,
5667                                         unsigned int max_data_bytes)
5668 {
5669         char *params = *pparams;
5670         pstring pathname;
5671         int reply_size = 0;
5672         int max_referral_level;
5673
5674         DEBUG(10,("call_trans2getdfsreferral\n"));
5675
5676         if (total_params < 3) {
5677                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5678         }
5679
5680         max_referral_level = SVAL(params,0);
5681
5682         if(!lp_host_msdfs())
5683                 return ERROR_DOS(ERRDOS,ERRbadfunc);
5684
5685         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
5686         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
5687                 return UNIXERROR(ERRDOS,ERRbadfile);
5688     
5689         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
5690         send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
5691
5692         return(-1);
5693 }
5694
5695 #define LMCAT_SPL       0x53
5696 #define LMFUNC_GETJOBID 0x60
5697
5698 /****************************************************************************
5699  Reply to a TRANS2_IOCTL - used for OS/2 printing.
5700 ****************************************************************************/
5701
5702 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
5703                                         char **pparams, int total_params, char **ppdata, int total_data,
5704                                         unsigned int max_data_bytes)
5705 {
5706         char *pdata = *ppdata;
5707         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
5708
5709         /* check for an invalid fid before proceeding */
5710         
5711         if (!fsp)                                
5712                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
5713
5714         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5715                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5716                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
5717                 if (*ppdata == NULL) {
5718                         return ERROR_NT(NT_STATUS_NO_MEMORY);
5719                 }
5720                 pdata = *ppdata;
5721
5722                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5723                         CAN ACCEPT THIS IN UNICODE. JRA. */
5724
5725                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
5726                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
5727                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
5728                 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
5729                 return(-1);
5730         } else {
5731                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5732                 return ERROR_DOS(ERRSRV,ERRerror);
5733         }
5734 }
5735
5736 /****************************************************************************
5737  Reply to a SMBfindclose (stop trans2 directory search).
5738 ****************************************************************************/
5739
5740 int reply_findclose(connection_struct *conn,
5741                     char *inbuf,char *outbuf,int length,int bufsize)
5742 {
5743         int outsize = 0;
5744         int dptr_num=SVALS(inbuf,smb_vwv0);
5745         START_PROFILE(SMBfindclose);
5746
5747         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
5748
5749         dptr_close(&dptr_num);
5750
5751         outsize = set_message(outbuf,0,0,False);
5752
5753         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
5754
5755         END_PROFILE(SMBfindclose);
5756         return(outsize);
5757 }
5758
5759 /****************************************************************************
5760  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
5761 ****************************************************************************/
5762
5763 int reply_findnclose(connection_struct *conn, 
5764                      char *inbuf,char *outbuf,int length,int bufsize)
5765 {
5766         int outsize = 0;
5767         int dptr_num= -1;
5768         START_PROFILE(SMBfindnclose);
5769         
5770         dptr_num = SVAL(inbuf,smb_vwv0);
5771
5772         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
5773
5774         /* We never give out valid handles for a 
5775            findnotifyfirst - so any dptr_num is ok here. 
5776            Just ignore it. */
5777
5778         outsize = set_message(outbuf,0,0,False);
5779
5780         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
5781
5782         END_PROFILE(SMBfindnclose);
5783         return(outsize);
5784 }
5785
5786 int handle_trans2(connection_struct *conn,
5787                   struct trans_state *state,
5788                   char *inbuf, char *outbuf, int size, int bufsize)
5789 {
5790         int outsize;
5791
5792         if (Protocol >= PROTOCOL_NT1) {
5793                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5794         }
5795
5796         /* Now we must call the relevant TRANS2 function */
5797         switch(state->call)  {
5798         case TRANSACT2_OPEN:
5799         {
5800                 START_PROFILE(Trans2_open);
5801                 outsize = call_trans2open(
5802                         conn, inbuf, outbuf, bufsize, 
5803                         &state->param, state->total_param,
5804                         &state->data, state->total_data,
5805                         state->max_data_return);
5806                 END_PROFILE(Trans2_open);
5807                 break;
5808         }
5809
5810         case TRANSACT2_FINDFIRST:
5811         {
5812                 START_PROFILE(Trans2_findfirst);
5813                 outsize = call_trans2findfirst(
5814                         conn, inbuf, outbuf, bufsize,
5815                         &state->param, state->total_param,
5816                         &state->data, state->total_data,
5817                         state->max_data_return);
5818                 END_PROFILE(Trans2_findfirst);
5819                 break;
5820         }
5821
5822         case TRANSACT2_FINDNEXT:
5823         {
5824                 START_PROFILE(Trans2_findnext);
5825                 outsize = call_trans2findnext(
5826                         conn, inbuf, outbuf, size, bufsize, 
5827                         &state->param, state->total_param,
5828                         &state->data, state->total_data,
5829                         state->max_data_return);
5830                 END_PROFILE(Trans2_findnext);
5831                 break;
5832         }
5833
5834         case TRANSACT2_QFSINFO:
5835         {
5836                 START_PROFILE(Trans2_qfsinfo);
5837                 outsize = call_trans2qfsinfo(
5838                         conn, inbuf, outbuf, size, bufsize,
5839                         &state->param, state->total_param,
5840                         &state->data, state->total_data,
5841                         state->max_data_return);
5842                 END_PROFILE(Trans2_qfsinfo);
5843             break;
5844         }
5845
5846         case TRANSACT2_SETFSINFO:
5847         {
5848                 START_PROFILE(Trans2_setfsinfo);
5849                 outsize = call_trans2setfsinfo(
5850                         conn, inbuf, outbuf, size, bufsize, 
5851                         &state->param, state->total_param,
5852                         &state->data, state->total_data,
5853                         state->max_data_return);
5854                 END_PROFILE(Trans2_setfsinfo);
5855                 break;
5856         }
5857
5858         case TRANSACT2_QPATHINFO:
5859         case TRANSACT2_QFILEINFO:
5860         {
5861                 START_PROFILE(Trans2_qpathinfo);
5862                 outsize = call_trans2qfilepathinfo(
5863                         conn, inbuf, outbuf, size, bufsize, state->call,
5864                         &state->param, state->total_param,
5865                         &state->data, state->total_data,
5866                         state->max_data_return);
5867                 END_PROFILE(Trans2_qpathinfo);
5868                 break;
5869         }
5870
5871         case TRANSACT2_SETPATHINFO:
5872         case TRANSACT2_SETFILEINFO:
5873         {
5874                 START_PROFILE(Trans2_setpathinfo);
5875                 outsize = call_trans2setfilepathinfo(
5876                         conn, inbuf, outbuf, size, bufsize, state->call,
5877                         &state->param, state->total_param,
5878                         &state->data, state->total_data,
5879                         state->max_data_return);
5880                 END_PROFILE(Trans2_setpathinfo);
5881                 break;
5882         }
5883
5884         case TRANSACT2_FINDNOTIFYFIRST:
5885         {
5886                 START_PROFILE(Trans2_findnotifyfirst);
5887                 outsize = call_trans2findnotifyfirst(
5888                         conn, inbuf, outbuf, size, bufsize, 
5889                         &state->param, state->total_param,
5890                         &state->data, state->total_data,
5891                         state->max_data_return);
5892                 END_PROFILE(Trans2_findnotifyfirst);
5893                 break;
5894         }
5895
5896         case TRANSACT2_FINDNOTIFYNEXT:
5897         {
5898                 START_PROFILE(Trans2_findnotifynext);
5899                 outsize = call_trans2findnotifynext(
5900                         conn, inbuf, outbuf, size, bufsize, 
5901                         &state->param, state->total_param,
5902                         &state->data, state->total_data,
5903                         state->max_data_return);
5904                 END_PROFILE(Trans2_findnotifynext);
5905                 break;
5906         }
5907
5908         case TRANSACT2_MKDIR:
5909         {
5910                 START_PROFILE(Trans2_mkdir);
5911                 outsize = call_trans2mkdir(
5912                         conn, inbuf, outbuf, size, bufsize,
5913                         &state->param, state->total_param,
5914                         &state->data, state->total_data,
5915                         state->max_data_return);
5916                 END_PROFILE(Trans2_mkdir);
5917                 break;
5918         }
5919
5920         case TRANSACT2_GET_DFS_REFERRAL:
5921         {
5922                 START_PROFILE(Trans2_get_dfs_referral);
5923                 outsize = call_trans2getdfsreferral(
5924                         conn, inbuf, outbuf, size, bufsize,
5925                         &state->param, state->total_param,
5926                         &state->data, state->total_data,
5927                         state->max_data_return);
5928                 END_PROFILE(Trans2_get_dfs_referral);
5929                 break;
5930         }
5931
5932         case TRANSACT2_IOCTL:
5933         {
5934                 START_PROFILE(Trans2_ioctl);
5935                 outsize = call_trans2ioctl(
5936                         conn, inbuf, outbuf, size, bufsize,
5937                         &state->param, state->total_param,
5938                         &state->data, state->total_data,
5939                         state->max_data_return);
5940                 END_PROFILE(Trans2_ioctl);
5941                 break;
5942         }
5943
5944         default:
5945                 /* Error in request */
5946                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5947                 outsize = ERROR_DOS(ERRSRV,ERRerror);
5948         }
5949
5950         return outsize;
5951 }
5952
5953 /****************************************************************************
5954  Reply to a SMBtrans2.
5955  ****************************************************************************/
5956
5957 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
5958                  int size, int bufsize)
5959 {
5960         int outsize = 0;
5961         unsigned int dsoff = SVAL(inbuf, smb_dsoff);
5962         unsigned int dscnt = SVAL(inbuf, smb_dscnt);
5963         unsigned int psoff = SVAL(inbuf, smb_psoff);
5964         unsigned int pscnt = SVAL(inbuf, smb_pscnt);
5965         unsigned int tran_call = SVAL(inbuf, smb_setup0);
5966         struct trans_state *state;
5967         NTSTATUS result;
5968
5969         START_PROFILE(SMBtrans2);
5970
5971         result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
5972         if (!NT_STATUS_IS_OK(result)) {
5973                 DEBUG(2, ("Got invalid trans2 request: %s\n",
5974                           nt_errstr(result)));
5975                 END_PROFILE(SMBtrans2);
5976                 return ERROR_NT(result);
5977         }
5978
5979         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
5980             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
5981                 END_PROFILE(SMBtrans2);
5982                 return ERROR_DOS(ERRSRV,ERRaccess);
5983         }
5984
5985         if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
5986                 DEBUG(0, ("talloc failed\n"));
5987                 END_PROFILE(SMBtrans2);
5988                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5989         }
5990
5991         state->cmd = SMBtrans2;
5992
5993         state->mid = SVAL(inbuf, smb_mid);
5994         state->vuid = SVAL(inbuf, smb_uid);
5995         state->setup_count = SVAL(inbuf, smb_suwcnt);
5996         state->setup = NULL;
5997         state->total_param = SVAL(inbuf, smb_tpscnt);
5998         state->param = NULL;
5999         state->total_data =  SVAL(inbuf, smb_tdscnt);
6000         state->data = NULL;
6001         state->max_param_return = SVAL(inbuf, smb_mprcnt);
6002         state->max_data_return  = SVAL(inbuf, smb_mdrcnt);
6003         state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6004         state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6005         state->one_way = BITSETW(inbuf+smb_vwv5,1);
6006
6007         state->call = tran_call;
6008
6009         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6010            is so as a sanity check */
6011         if (state->setup_count != 1) {
6012                 /*
6013                  * Need to have rc=0 for ioctl to get job id for OS/2.
6014                  *  Network printing will fail if function is not successful.
6015                  *  Similar function in reply.c will be used if protocol
6016                  *  is LANMAN1.0 instead of LM1.2X002.
6017                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
6018                  *  outbuf doesn't have to be set(only job id is used).
6019                  */
6020                 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6021                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6022                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6023                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6024                 } else {
6025                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6026                         DEBUG(2,("Transaction is %d\n",tran_call));
6027                         TALLOC_FREE(state);
6028                         END_PROFILE(SMBtrans2);
6029                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6030                 }
6031         }
6032
6033         if ((dscnt > state->total_data) || (pscnt > state->total_param))
6034                 goto bad_param;
6035
6036         if (state->total_data) {
6037                 /* Can't use talloc here, the core routines do realloc on the
6038                  * params and data. */
6039                 state->data = (char *)SMB_MALLOC(state->total_data);
6040                 if (state->data == NULL) {
6041                         DEBUG(0,("reply_trans2: data malloc fail for %u "
6042                                  "bytes !\n", (unsigned int)state->total_data));
6043                         TALLOC_FREE(state);
6044                         END_PROFILE(SMBtrans2);
6045                         return(ERROR_DOS(ERRDOS,ERRnomem));
6046                 }
6047                 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6048                         goto bad_param;
6049                 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6050                     (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6051                         goto bad_param;
6052
6053                 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6054         }
6055
6056         if (state->total_param) {
6057                 /* Can't use talloc here, the core routines do realloc on the
6058                  * params and data. */
6059                 state->param = (char *)SMB_MALLOC(state->total_param);
6060                 if (state->param == NULL) {
6061                         DEBUG(0,("reply_trans: param malloc fail for %u "
6062                                  "bytes !\n", (unsigned int)state->total_param));
6063                         SAFE_FREE(state->data);
6064                         TALLOC_FREE(state);
6065                         END_PROFILE(SMBtrans2);
6066                         return(ERROR_DOS(ERRDOS,ERRnomem));
6067                 } 
6068                 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6069                         goto bad_param;
6070                 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6071                     (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6072                         goto bad_param;
6073
6074                 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6075         }
6076
6077         state->received_data  = dscnt;
6078         state->received_param = pscnt;
6079
6080         if ((state->received_param == state->total_param) &&
6081             (state->received_data == state->total_data)) {
6082
6083                 outsize = handle_trans2(conn, state, inbuf, outbuf,
6084                                         size, bufsize);
6085                 SAFE_FREE(state->data);
6086                 SAFE_FREE(state->param);
6087                 TALLOC_FREE(state);
6088                 END_PROFILE(SMBtrans2);
6089                 return outsize;
6090         }
6091
6092         DLIST_ADD(conn->pending_trans, state);
6093
6094         /* We need to send an interim response then receive the rest
6095            of the parameter/data bytes */
6096         outsize = set_message(outbuf,0,0,False);
6097         show_msg(outbuf);
6098         END_PROFILE(SMBtrans2);
6099         return outsize;
6100
6101   bad_param:
6102
6103         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6104         SAFE_FREE(state->data);
6105         SAFE_FREE(state->param);
6106         TALLOC_FREE(state);
6107         END_PROFILE(SMBtrans2);
6108         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6109 }
6110
6111
6112 /****************************************************************************
6113  Reply to a SMBtranss2
6114  ****************************************************************************/
6115
6116 int reply_transs2(connection_struct *conn,
6117                   char *inbuf,char *outbuf,int size,int bufsize)
6118 {
6119         int outsize = 0;
6120         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6121         struct trans_state *state;
6122
6123         START_PROFILE(SMBtranss2);
6124
6125         show_msg(inbuf);
6126
6127         for (state = conn->pending_trans; state != NULL;
6128              state = state->next) {
6129                 if (state->mid == SVAL(inbuf,smb_mid)) {
6130                         break;
6131                 }
6132         }
6133
6134         if ((state == NULL) || (state->cmd != SMBtrans2)) {
6135                 END_PROFILE(SMBtranss2);
6136                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6137         }
6138
6139         /* Revise state->total_param and state->total_data in case they have
6140            changed downwards */
6141
6142         if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6143                 state->total_param = SVAL(inbuf, smb_tpscnt);
6144         if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6145                 state->total_data = SVAL(inbuf, smb_tdscnt);
6146
6147         pcnt = SVAL(inbuf, smb_spscnt);
6148         poff = SVAL(inbuf, smb_spsoff);
6149         pdisp = SVAL(inbuf, smb_spsdisp);
6150
6151         dcnt = SVAL(inbuf, smb_sdscnt);
6152         doff = SVAL(inbuf, smb_sdsoff);
6153         ddisp = SVAL(inbuf, smb_sdsdisp);
6154
6155         state->received_param += pcnt;
6156         state->received_data += dcnt;
6157                 
6158         if ((state->received_data > state->total_data) ||
6159             (state->received_param > state->total_param))
6160                 goto bad_param;
6161
6162         if (pcnt) {
6163                 if (pdisp+pcnt > state->total_param)
6164                         goto bad_param;
6165                 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6166                         goto bad_param;
6167                 if (pdisp > state->total_param)
6168                         goto bad_param;
6169                 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6170                     (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6171                         goto bad_param;
6172                 if (state->param + pdisp < state->param)
6173                         goto bad_param;
6174
6175                 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6176                        pcnt);
6177         }
6178
6179         if (dcnt) {
6180                 if (ddisp+dcnt > state->total_data)
6181                         goto bad_param;
6182                 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6183                         goto bad_param;
6184                 if (ddisp > state->total_data)
6185                         goto bad_param;
6186                 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6187                     (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6188                         goto bad_param;
6189                 if (state->data + ddisp < state->data)
6190                         goto bad_param;
6191
6192                 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6193                        dcnt);      
6194         }
6195
6196         if ((state->received_param < state->total_param) ||
6197             (state->received_data < state->total_data)) {
6198                 END_PROFILE(SMBtranss2);
6199                 return -1;
6200         }
6201
6202         /* construct_reply_common has done us the favor to pre-fill the
6203          * command field with SMBtranss2 which is wrong :-)
6204          */
6205         SCVAL(outbuf,smb_com,SMBtrans2);
6206
6207         outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6208
6209         DLIST_REMOVE(conn->pending_trans, state);
6210         SAFE_FREE(state->data);
6211         SAFE_FREE(state->param);
6212         TALLOC_FREE(state);
6213
6214         if (outsize == 0) {
6215                 END_PROFILE(SMBtranss2);
6216                 return(ERROR_DOS(ERRSRV,ERRnosupport));
6217         }
6218         
6219         END_PROFILE(SMBtranss2);
6220         return(outsize);
6221
6222   bad_param:
6223
6224         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6225         DLIST_REMOVE(conn->pending_trans, state);
6226         SAFE_FREE(state->data);
6227         SAFE_FREE(state->param);
6228         TALLOC_FREE(state);
6229         END_PROFILE(SMBtranss2);
6230         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6231 }