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