r21247: In the refactoring I dropped a RESOLVE_DFSPATH call
[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));       /* Creation 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 ERROR_NT(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         /*
4809          * Deal with the UNIX specific mode set.
4810          */
4811
4812         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4813                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4814                         (unsigned int)unixmode, fname ));
4815                 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
4816                         return map_nt_error_from_unix(errno);
4817                 }
4818         }
4819
4820         /*
4821          * Deal with the UNIX specific uid set.
4822          */
4823
4824         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
4825                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4826                         (unsigned int)set_owner, fname ));
4827                 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
4828                         status = map_nt_error_from_unix(errno);
4829                         if (delete_on_fail) {
4830                                 SMB_VFS_UNLINK(conn,fname);
4831                         }
4832                         return status;
4833                 }
4834         }
4835
4836         /*
4837          * Deal with the UNIX specific gid set.
4838          */
4839
4840         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
4841                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4842                         (unsigned int)set_owner, fname ));
4843                 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
4844                         status = map_nt_error_from_unix(errno);
4845                         if (delete_on_fail) {
4846                                 SMB_VFS_UNLINK(conn,fname);
4847                         }
4848                         return status;
4849                 }
4850         }
4851
4852         /* Deal with any size changes. */
4853
4854         status = smb_set_file_size(conn,
4855                                 fsp,
4856                                 fname,
4857                                 psbuf,
4858                                 size);
4859         if (!NT_STATUS_IS_OK(status)) {
4860                 return status;
4861         }
4862
4863         /* Deal with any time changes. */
4864
4865         return smb_set_file_time(conn,
4866                                 fsp,
4867                                 fname,
4868                                 psbuf,
4869                                 tvs);
4870 }
4871
4872 /****************************************************************************
4873  Create a directory with POSIX semantics.
4874 ****************************************************************************/
4875
4876 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
4877                                 char **ppdata,
4878                                 int total_data,
4879                                 const char *fname,
4880                                 SMB_STRUCT_STAT *psbuf,
4881                                 int *pdata_return_size)
4882 {
4883         NTSTATUS status = NT_STATUS_OK;
4884         uint32 raw_unixmode = 0;
4885         uint32 mod_unixmode = 0;
4886         mode_t unixmode = (mode_t)0;
4887         files_struct *fsp = NULL;
4888         uint16 info_level_return = 0;
4889         char *pdata = *ppdata;
4890
4891         if (total_data < 10) {
4892                 return NT_STATUS_INVALID_PARAMETER;
4893         }
4894
4895         raw_unixmode = IVAL(pdata,8);
4896         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
4897         if (!NT_STATUS_IS_OK(status)) {
4898                 return status;
4899         }
4900
4901         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
4902
4903         status = open_directory(conn,
4904                                 fname,
4905                                 psbuf,
4906                                 FILE_READ_ATTRIBUTES, /* Just a stat open */
4907                                 FILE_SHARE_NONE, /* Ignored for stat opens */
4908                                 FILE_CREATE,
4909                                 0,
4910                                 mod_unixmode,
4911                                 NULL,
4912                                 &fsp);
4913
4914         if (NT_STATUS_IS_OK(status)) {
4915                 close_file(fsp, NORMAL_CLOSE);
4916         }
4917
4918         info_level_return = SVAL(pdata,12);
4919  
4920         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
4921                 *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
4922         } else {
4923                 *pdata_return_size = 8;
4924         }
4925
4926         /* Realloc the data size */
4927         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
4928         if (*ppdata == NULL) {
4929                 *pdata_return_size = 0;
4930                 return NT_STATUS_NO_MEMORY;
4931         }
4932
4933         SSVAL(pdata,0,NO_OPLOCK_RETURN);
4934         SSVAL(pdata,2,0);
4935
4936         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
4937                 SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
4938                 SSVAL(pdata,6,0); /* Padding. */
4939                 store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
4940         } else {
4941                 SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
4942                 SSVAL(pdata,6,0); /* Padding. */
4943         }
4944
4945         return status;
4946 }
4947
4948 /****************************************************************************
4949  Open/Create a file with POSIX semantics.
4950 ****************************************************************************/
4951
4952 static NTSTATUS smb_posix_open(connection_struct *conn,
4953                                 char **ppdata,
4954                                 int total_data,
4955                                 const char *fname,
4956                                 SMB_STRUCT_STAT *psbuf,
4957                                 int *pdata_return_size)
4958 {
4959         BOOL extended_oplock_granted = False;
4960         char *pdata = *ppdata;
4961         uint32 flags = 0;
4962         uint32 wire_open_mode = 0;
4963         uint32 raw_unixmode = 0;
4964         uint32 mod_unixmode = 0;
4965         uint32 create_disp = 0;
4966         uint32 access_mask = 0;
4967         uint32 create_options = 0;
4968         NTSTATUS status = NT_STATUS_OK;
4969         mode_t unixmode = (mode_t)0;
4970         files_struct *fsp = NULL;
4971         int oplock_request = 0;
4972         int info = 0;
4973         uint16 info_level_return = 0;
4974
4975         if (total_data < 14) {
4976                 return NT_STATUS_INVALID_PARAMETER;
4977         }
4978
4979         flags = IVAL(pdata,0);
4980         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
4981         if (oplock_request) {
4982                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
4983         }
4984
4985         wire_open_mode = IVAL(pdata,4);
4986
4987         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
4988                 return smb_posix_mkdir(conn,
4989                                         ppdata,
4990                                         total_data,
4991                                         fname,
4992                                         psbuf,
4993                                         pdata_return_size);
4994         }
4995
4996         switch (wire_open_mode & SMB_ACCMODE) {
4997                 case SMB_O_RDONLY:
4998                         access_mask = FILE_READ_DATA;
4999                         break;
5000                 case SMB_O_WRONLY:
5001                         access_mask = FILE_WRITE_DATA;
5002                         break;
5003                 case SMB_O_RDWR:
5004                         access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5005                         break;
5006                 default:
5007                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5008                                 (unsigned int)wire_open_mode ));
5009                         return NT_STATUS_INVALID_PARAMETER;
5010         }
5011
5012         wire_open_mode &= ~SMB_ACCMODE;
5013
5014         if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5015                 create_disp = FILE_CREATE;
5016         } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5017                 create_disp = FILE_OVERWRITE_IF;
5018         } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5019                 create_disp = FILE_OPEN_IF;
5020         } else {
5021                 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5022                         (unsigned int)wire_open_mode ));
5023                 return NT_STATUS_INVALID_PARAMETER;
5024         }
5025
5026         raw_unixmode = IVAL(pdata,8);
5027         status = unix_perms_from_wire(conn,
5028                                 psbuf,
5029                                 raw_unixmode,
5030                                 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5031                                 &unixmode);
5032
5033         if (!NT_STATUS_IS_OK(status)) {
5034                 return status;
5035         }
5036
5037         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5038
5039         if (wire_open_mode & SMB_O_SYNC) {
5040                 create_options |= FILE_WRITE_THROUGH;
5041         }
5042         if (wire_open_mode & SMB_O_APPEND) {
5043                 access_mask |= FILE_APPEND_DATA;
5044         }
5045         if (wire_open_mode & SMB_O_DIRECT) {
5046                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5047         }
5048
5049         status = open_file_ntcreate(conn,
5050                                 fname,
5051                                 psbuf,
5052                                 access_mask,
5053                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5054                                 create_disp,
5055                                 0,              /* no create options yet. */
5056                                 mod_unixmode,
5057                                 oplock_request,
5058                                 &info,
5059                                 &fsp);
5060
5061         if (!NT_STATUS_IS_OK(status)) {
5062                 return status;
5063         }
5064
5065         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5066                 extended_oplock_granted = True;
5067         }
5068
5069         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5070                 extended_oplock_granted = True;
5071         }
5072
5073         info_level_return = SVAL(pdata,12);
5074  
5075         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5076                 *pdata_return_size = 8 + SMB_FILE_UNIX_BASIC_SIZE;
5077         } else {
5078                 *pdata_return_size = 8;
5079         }
5080
5081         /* Realloc the data size */
5082         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5083         if (*ppdata == NULL) {
5084                 close_file(fsp,ERROR_CLOSE);
5085                 *pdata_return_size = 0;
5086                 return NT_STATUS_NO_MEMORY;
5087         }
5088
5089         if (extended_oplock_granted) {
5090                 if (flags & REQUEST_BATCH_OPLOCK) {
5091                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5092                 } else {
5093                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5094                 }
5095         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5096                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5097         } else {
5098                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5099         }
5100
5101         SSVAL(pdata,2,fsp->fnum);
5102         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5103                 SSVAL(pdata,4,SMB_QUERY_FILE_UNIX_BASIC);
5104                 SSVAL(pdata,6,0); /* padding. */
5105                 store_file_unix_basic(conn, pdata + 8, fsp, psbuf);
5106         } else {
5107                 SSVAL(pdata,4,SMB_NO_INFO_LEVEL_RETURNED);
5108                 SSVAL(pdata,6,0); /* padding. */
5109         }
5110         return NT_STATUS_OK;
5111 }
5112
5113 /****************************************************************************
5114  Delete a file with POSIX semantics.
5115 ****************************************************************************/
5116
5117 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5118                                 const char *pdata,
5119                                 int total_data,
5120                                 const char *fname,
5121                                 SMB_STRUCT_STAT *psbuf)
5122 {
5123         NTSTATUS status = NT_STATUS_OK;
5124         files_struct *fsp = NULL;
5125         int info = 0;
5126
5127         if (!VALID_STAT(*psbuf)) {
5128                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5129         }
5130
5131         if (VALID_STAT_OF_DIR(*psbuf)) {
5132                 status = open_directory(conn,
5133                                         fname,
5134                                         psbuf,
5135                                         DELETE_ACCESS,
5136                                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5137                                         FILE_OPEN,
5138                                         FILE_DELETE_ON_CLOSE,
5139                                         FILE_FLAG_POSIX_SEMANTICS|0777,
5140                                         &info,                          
5141                                         &fsp);
5142         } else {
5143                 status = open_file_ntcreate(conn,
5144                                 fname,
5145                                 psbuf,
5146                                 DELETE_ACCESS,
5147                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5148                                 FILE_OPEN,
5149                                 FILE_DELETE_ON_CLOSE,
5150                                 FILE_FLAG_POSIX_SEMANTICS|0777,
5151                                 INTERNAL_OPEN_ONLY,
5152                                 &info,
5153                                 &fsp);
5154         }
5155
5156         if (!NT_STATUS_IS_OK(status)) {
5157                 return status;
5158         }
5159         return close_file(fsp, NORMAL_CLOSE);
5160 }
5161
5162 /****************************************************************************
5163  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5164 ****************************************************************************/
5165
5166 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5167                                         unsigned int tran_call,
5168                                         char **pparams, int total_params, char **ppdata, int total_data,
5169                                         unsigned int max_data_bytes)
5170 {
5171         char *params = *pparams;
5172         char *pdata = *ppdata;
5173         uint16 info_level;
5174         SMB_STRUCT_STAT sbuf;
5175         pstring fname;
5176         files_struct *fsp = NULL;
5177         NTSTATUS status = NT_STATUS_OK;
5178         int data_return_size = 0;
5179
5180         if (!params) {
5181                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5182         }
5183
5184         ZERO_STRUCT(sbuf);
5185
5186         if (tran_call == TRANSACT2_SETFILEINFO) {
5187                 if (total_params < 4) {
5188                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5189                 }
5190
5191                 fsp = file_fsp(params,0);
5192                 info_level = SVAL(params,2);    
5193
5194                 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5195                         /*
5196                          * This is actually a SETFILEINFO on a directory
5197                          * handle (returned from an NT SMB). NT5.0 seems
5198                          * to do this call. JRA.
5199                          */
5200                         pstrcpy(fname, fsp->fsp_name);
5201                         if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5202                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5203                                 return UNIXERROR(ERRDOS,ERRbadpath);
5204                         }
5205                 } else if (fsp && fsp->print_file) {
5206                         /*
5207                          * Doing a DELETE_ON_CLOSE should cancel a print job.
5208                          */
5209                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5210                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5211
5212                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5213         
5214                                 SSVAL(params,0,0);
5215                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5216                                 return(-1);
5217                         } else
5218                                 return (UNIXERROR(ERRDOS,ERRbadpath));
5219             } else {
5220                         /*
5221                          * Original code - this is an open file.
5222                          */
5223                         CHECK_FSP(fsp,conn);
5224
5225                         pstrcpy(fname, fsp->fsp_name);
5226
5227                         if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5228                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5229                                 return(UNIXERROR(ERRDOS,ERRbadfid));
5230                         }
5231                 }
5232         } else {
5233                 /* set path info */
5234                 if (total_params < 7) {
5235                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5236                 }
5237
5238                 info_level = SVAL(params,0);    
5239                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5240                 if (!NT_STATUS_IS_OK(status)) {
5241                         return ERROR_NT(status);
5242                 }
5243
5244                 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
5245
5246                 status = unix_convert(conn, fname, False, NULL, &sbuf);
5247                 if (!NT_STATUS_IS_OK(status)) {
5248                         return ERROR_NT(status);
5249                 }
5250
5251                 /*
5252                  * For CIFS UNIX extensions the target name may not exist.
5253                  */
5254
5255                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
5256                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
5257                         return UNIXERROR(ERRDOS,ERRbadpath);
5258                 }    
5259
5260                 status = check_name(conn, fname);
5261                 if (!NT_STATUS_IS_OK(status)) {
5262                         return ERROR_NT(status);
5263                 }
5264
5265         }
5266
5267         if (!CAN_WRITE(conn)) {
5268                 return ERROR_DOS(ERRSRV,ERRaccess);
5269         }
5270
5271         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5272                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5273         }
5274
5275         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5276                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5277
5278         /* Realloc the parameter size */
5279         *pparams = (char *)SMB_REALLOC(*pparams,2);
5280         if (*pparams == NULL) {
5281                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5282         }
5283         params = *pparams;
5284
5285         SSVAL(params,0,0);
5286
5287         if (fsp && fsp->pending_modtime) {
5288                 /* the pending modtime overrides the current modtime */
5289                 sbuf.st_mtime = fsp->pending_modtime;
5290         }
5291
5292         switch (info_level) {
5293
5294                 case SMB_INFO_STANDARD:
5295                 {
5296                         status = smb_set_info_standard(conn,
5297                                         pdata,
5298                                         total_data,
5299                                         fsp,
5300                                         fname,
5301                                         &sbuf);
5302                         break;
5303                 }
5304
5305                 case SMB_INFO_SET_EA:
5306                 {
5307                         status = smb_info_set_ea(conn,
5308                                                 pdata,
5309                                                 total_data,
5310                                                 fsp,
5311                                                 fname);
5312                         break;
5313                 }
5314
5315                 case SMB_SET_FILE_BASIC_INFO:
5316                 case SMB_FILE_BASIC_INFORMATION:
5317                 {
5318                         status = smb_set_file_basic_info(conn,
5319                                                         pdata,
5320                                                         total_data,
5321                                                         fsp,
5322                                                         fname,
5323                                                         &sbuf);
5324                         break;
5325                 }
5326
5327                 case SMB_FILE_ALLOCATION_INFORMATION:
5328                 case SMB_SET_FILE_ALLOCATION_INFO:
5329                 {
5330                         status = smb_set_file_allocation_info(conn,
5331                                                                 pdata,
5332                                                                 total_data,
5333                                                                 fsp,
5334                                                                 fname,
5335                                                                 &sbuf);
5336                         break;
5337                 }
5338
5339                 case SMB_FILE_END_OF_FILE_INFORMATION:
5340                 case SMB_SET_FILE_END_OF_FILE_INFO:
5341                 {
5342                         status = smb_set_file_end_of_file_info(conn,
5343                                                                 pdata,
5344                                                                 total_data,
5345                                                                 fsp,
5346                                                                 fname,
5347                                                                 &sbuf);
5348                         break;
5349                 }
5350
5351                 case SMB_FILE_DISPOSITION_INFORMATION:
5352                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5353                 {
5354 #if 0
5355                         /* JRA - We used to just ignore this on a path ? 
5356                          * Shouldn't this be invalid level on a pathname
5357                          * based call ?
5358                          */
5359                         if (tran_call != TRANSACT2_SETFILEINFO) {
5360                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5361                         }
5362 #endif
5363                         status = smb_set_file_disposition_info(conn,
5364                                                 pdata,
5365                                                 total_data,
5366                                                 fsp,
5367                                                 fname,
5368                                                 &sbuf);
5369                         break;
5370                 }
5371
5372                 case SMB_FILE_POSITION_INFORMATION:
5373                 {
5374                         status = smb_file_position_information(conn,
5375                                                 pdata,
5376                                                 total_data,
5377                                                 fsp);
5378                         break;
5379                 }
5380
5381                 /* From tridge Samba4 : 
5382                  * MODE_INFORMATION in setfileinfo (I have no
5383                  * idea what "mode information" on a file is - it takes a value of 0,
5384                  * 2, 4 or 6. What could it be?).
5385                  */
5386
5387                 case SMB_FILE_MODE_INFORMATION:
5388                 {
5389                         status = smb_file_mode_information(conn,
5390                                                 pdata,
5391                                                 total_data);
5392                         break;
5393                 }
5394
5395                 /*
5396                  * CIFS UNIX extensions.
5397                  */
5398
5399                 case SMB_SET_FILE_UNIX_BASIC:
5400                 {
5401                         status = smb_set_file_unix_basic(conn,
5402                                                         pdata,
5403                                                         total_data,
5404                                                         fsp,
5405                                                         fname,
5406                                                         &sbuf);
5407                         break;
5408                 }
5409
5410                 case SMB_SET_FILE_UNIX_LINK:
5411                 {
5412                         if (tran_call != TRANSACT2_SETPATHINFO) {
5413                                 /* We must have a pathname for this. */
5414                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5415                         }
5416                         status = smb_set_file_unix_link(conn,
5417                                                 inbuf,
5418                                                 pdata,
5419                                                 total_data,
5420                                                 fname);
5421                         break;
5422                 }
5423
5424                 case SMB_SET_FILE_UNIX_HLINK:
5425                 {
5426                         if (tran_call != TRANSACT2_SETPATHINFO) {
5427                                 /* We must have a pathname for this. */
5428                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5429                         }
5430                         status = smb_set_file_unix_hlink(conn,
5431                                                 inbuf,
5432                                                 outbuf,
5433                                                 pdata,
5434                                                 total_data,
5435                                                 fname);
5436                         break;
5437                 }
5438
5439                 case SMB_FILE_RENAME_INFORMATION:
5440                 {
5441                         status = smb_file_rename_information(conn,
5442                                                         inbuf,
5443                                                         outbuf,
5444                                                         pdata,
5445                                                         total_data,
5446                                                         fsp,
5447                                                         fname);
5448                         break;
5449                 }
5450
5451 #if defined(HAVE_POSIX_ACLS)
5452                 case SMB_SET_POSIX_ACL:
5453                 {
5454                         status = smb_set_posix_acl(conn,
5455                                                 pdata,
5456                                                 total_data,
5457                                                 fsp,
5458                                                 fname,
5459                                                 &sbuf);
5460                         break;
5461                 }
5462 #endif
5463
5464                 case SMB_SET_POSIX_LOCK:
5465                 {
5466                         if (tran_call != TRANSACT2_SETFILEINFO) {
5467                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5468                         }
5469                         status = smb_set_posix_lock(conn,
5470                                                 inbuf,
5471                                                 length,
5472                                                 pdata,
5473                                                 total_data,
5474                                                 fsp);
5475                         break;
5476                 }
5477
5478                 case SMB_POSIX_PATH_OPEN:
5479                 {
5480                         if (tran_call != TRANSACT2_SETPATHINFO) {
5481                                 /* We must have a pathname for this. */
5482                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5483                         }
5484
5485                         status = smb_posix_open(conn,
5486                                                 ppdata,
5487                                                 total_data,
5488                                                 fname,
5489                                                 &sbuf,
5490                                                 &data_return_size);
5491                         break;
5492                 }
5493
5494                 case SMB_POSIX_PATH_UNLINK:
5495                 {
5496                         if (tran_call != TRANSACT2_SETPATHINFO) {
5497                                 /* We must have a pathname for this. */
5498                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5499                         }
5500
5501                         status = smb_posix_unlink(conn,
5502                                                 pdata,
5503                                                 total_data,
5504                                                 fname,
5505                                                 &sbuf);
5506                         break;
5507                 }
5508
5509                 default:
5510                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5511         }
5512
5513         
5514         if (!NT_STATUS_IS_OK(status)) {
5515                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
5516                         /* We have re-scheduled this call. */
5517                         return -1;
5518                 }
5519                 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
5520                         /* We have re-scheduled this call. */
5521                         return -1;
5522                 }
5523                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5524                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5525                 }
5526                 return ERROR_NT(status);
5527         }
5528
5529         SSVAL(params,0,0);
5530         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
5531   
5532         return -1;
5533 }
5534
5535 /****************************************************************************
5536  Reply to a TRANS2_MKDIR (make directory with extended attributes).
5537 ****************************************************************************/
5538
5539 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5540                                         char **pparams, int total_params, char **ppdata, int total_data,
5541                                         unsigned int max_data_bytes)
5542 {
5543         char *params = *pparams;
5544         char *pdata = *ppdata;
5545         pstring directory;
5546         SMB_STRUCT_STAT sbuf;
5547         NTSTATUS status = NT_STATUS_OK;
5548         struct ea_list *ea_list = NULL;
5549
5550         if (!CAN_WRITE(conn))
5551                 return ERROR_DOS(ERRSRV,ERRaccess);
5552
5553         if (total_params < 5) {
5554                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5555         }
5556
5557         srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
5558         if (!NT_STATUS_IS_OK(status)) {
5559                 return ERROR_NT(status);
5560         }
5561
5562         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
5563
5564         status = unix_convert(conn, directory, False, NULL, &sbuf);
5565         if (!NT_STATUS_IS_OK(status)) {
5566                 return ERROR_NT(status);
5567         }
5568
5569         /* Any data in this call is an EA list. */
5570         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
5571                 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
5572         }
5573
5574         /*
5575          * OS/2 workplace shell seems to send SET_EA requests of "null"
5576          * length (4 bytes containing IVAL 4).
5577          * They seem to have no effect. Bug #3212. JRA.
5578          */
5579
5580         if (total_data != 4) {
5581                 if (total_data < 10) {
5582                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5583                 }
5584
5585                 if (IVAL(pdata,0) > total_data) {
5586                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
5587                                 IVAL(pdata,0), (unsigned int)total_data));
5588                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5589                 }
5590
5591                 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
5592                                        total_data - 4);
5593                 if (!ea_list) {
5594                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5595                 }
5596         } else if (IVAL(pdata,0) != 4) {
5597                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5598         }
5599
5600         status = check_name(conn, directory);
5601         if (!NT_STATUS_IS_OK(status)) {
5602                 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
5603                 return ERROR_NT(status);
5604         }
5605
5606         status = create_directory(conn, directory);
5607
5608         if (!NT_STATUS_IS_OK(status)) {
5609                 return ERROR_NT(status);
5610         }
5611   
5612         /* Try and set any given EA. */
5613         if (ea_list) {
5614                 status = set_ea(conn, NULL, directory, ea_list);
5615                 if (!NT_STATUS_IS_OK(status)) {
5616                         return ERROR_NT(status);
5617                 }
5618         }
5619
5620         /* Realloc the parameter and data sizes */
5621         *pparams = (char *)SMB_REALLOC(*pparams,2);
5622         if(*pparams == NULL) {
5623                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5624         }
5625         params = *pparams;
5626
5627         SSVAL(params,0,0);
5628
5629         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5630   
5631         return(-1);
5632 }
5633
5634 /****************************************************************************
5635  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
5636  We don't actually do this - we just send a null response.
5637 ****************************************************************************/
5638
5639 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5640                                         char **pparams, int total_params, char **ppdata, int total_data,
5641                                         unsigned int max_data_bytes)
5642 {
5643         static uint16 fnf_handle = 257;
5644         char *params = *pparams;
5645         uint16 info_level;
5646
5647         if (total_params < 6) {
5648                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5649         }
5650
5651         info_level = SVAL(params,4);
5652         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
5653
5654         switch (info_level) {
5655                 case 1:
5656                 case 2:
5657                         break;
5658                 default:
5659                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5660         }
5661
5662         /* Realloc the parameter and data sizes */
5663         *pparams = (char *)SMB_REALLOC(*pparams,6);
5664         if (*pparams == NULL) {
5665                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5666         }
5667         params = *pparams;
5668
5669         SSVAL(params,0,fnf_handle);
5670         SSVAL(params,2,0); /* No changes */
5671         SSVAL(params,4,0); /* No EA errors */
5672
5673         fnf_handle++;
5674
5675         if(fnf_handle == 0)
5676                 fnf_handle = 257;
5677
5678         send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
5679   
5680         return(-1);
5681 }
5682
5683 /****************************************************************************
5684  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
5685  changes). Currently this does nothing.
5686 ****************************************************************************/
5687
5688 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5689                                         char **pparams, int total_params, char **ppdata, int total_data,
5690                                         unsigned int max_data_bytes)
5691 {
5692         char *params = *pparams;
5693
5694         DEBUG(3,("call_trans2findnotifynext\n"));
5695
5696         /* Realloc the parameter and data sizes */
5697         *pparams = (char *)SMB_REALLOC(*pparams,4);
5698         if (*pparams == NULL) {
5699                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5700         }
5701         params = *pparams;
5702
5703         SSVAL(params,0,0); /* No changes */
5704         SSVAL(params,2,0); /* No EA errors */
5705
5706         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
5707   
5708         return(-1);
5709 }
5710
5711 /****************************************************************************
5712  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
5713 ****************************************************************************/
5714
5715 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
5716                                         char **pparams, int total_params, char **ppdata, int total_data,
5717                                         unsigned int max_data_bytes)
5718 {
5719         char *params = *pparams;
5720         pstring pathname;
5721         int reply_size = 0;
5722         int max_referral_level;
5723
5724         DEBUG(10,("call_trans2getdfsreferral\n"));
5725
5726         if (total_params < 3) {
5727                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5728         }
5729
5730         max_referral_level = SVAL(params,0);
5731
5732         if(!lp_host_msdfs())
5733                 return ERROR_DOS(ERRDOS,ERRbadfunc);
5734
5735         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
5736         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
5737                 return UNIXERROR(ERRDOS,ERRbadfile);
5738     
5739         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
5740         send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
5741
5742         return(-1);
5743 }
5744
5745 #define LMCAT_SPL       0x53
5746 #define LMFUNC_GETJOBID 0x60
5747
5748 /****************************************************************************
5749  Reply to a TRANS2_IOCTL - used for OS/2 printing.
5750 ****************************************************************************/
5751
5752 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
5753                                         char **pparams, int total_params, char **ppdata, int total_data,
5754                                         unsigned int max_data_bytes)
5755 {
5756         char *pdata = *ppdata;
5757         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
5758
5759         /* check for an invalid fid before proceeding */
5760         
5761         if (!fsp)                                
5762                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
5763
5764         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5765                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5766                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
5767                 if (*ppdata == NULL) {
5768                         return ERROR_NT(NT_STATUS_NO_MEMORY);
5769                 }
5770                 pdata = *ppdata;
5771
5772                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5773                         CAN ACCEPT THIS IN UNICODE. JRA. */
5774
5775                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
5776                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
5777                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
5778                 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
5779                 return(-1);
5780         } else {
5781                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5782                 return ERROR_DOS(ERRSRV,ERRerror);
5783         }
5784 }
5785
5786 /****************************************************************************
5787  Reply to a SMBfindclose (stop trans2 directory search).
5788 ****************************************************************************/
5789
5790 int reply_findclose(connection_struct *conn,
5791                     char *inbuf,char *outbuf,int length,int bufsize)
5792 {
5793         int outsize = 0;
5794         int dptr_num=SVALS(inbuf,smb_vwv0);
5795         START_PROFILE(SMBfindclose);
5796
5797         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
5798
5799         dptr_close(&dptr_num);
5800
5801         outsize = set_message(outbuf,0,0,False);
5802
5803         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
5804
5805         END_PROFILE(SMBfindclose);
5806         return(outsize);
5807 }
5808
5809 /****************************************************************************
5810  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
5811 ****************************************************************************/
5812
5813 int reply_findnclose(connection_struct *conn, 
5814                      char *inbuf,char *outbuf,int length,int bufsize)
5815 {
5816         int outsize = 0;
5817         int dptr_num= -1;
5818         START_PROFILE(SMBfindnclose);
5819         
5820         dptr_num = SVAL(inbuf,smb_vwv0);
5821
5822         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
5823
5824         /* We never give out valid handles for a 
5825            findnotifyfirst - so any dptr_num is ok here. 
5826            Just ignore it. */
5827
5828         outsize = set_message(outbuf,0,0,False);
5829
5830         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
5831
5832         END_PROFILE(SMBfindnclose);
5833         return(outsize);
5834 }
5835
5836 int handle_trans2(connection_struct *conn,
5837                   struct trans_state *state,
5838                   char *inbuf, char *outbuf, int size, int bufsize)
5839 {
5840         int outsize;
5841
5842         if (Protocol >= PROTOCOL_NT1) {
5843                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5844         }
5845
5846         /* Now we must call the relevant TRANS2 function */
5847         switch(state->call)  {
5848         case TRANSACT2_OPEN:
5849         {
5850                 START_PROFILE(Trans2_open);
5851                 outsize = call_trans2open(
5852                         conn, inbuf, outbuf, bufsize, 
5853                         &state->param, state->total_param,
5854                         &state->data, state->total_data,
5855                         state->max_data_return);
5856                 END_PROFILE(Trans2_open);
5857                 break;
5858         }
5859
5860         case TRANSACT2_FINDFIRST:
5861         {
5862                 START_PROFILE(Trans2_findfirst);
5863                 outsize = call_trans2findfirst(
5864                         conn, inbuf, outbuf, bufsize,
5865                         &state->param, state->total_param,
5866                         &state->data, state->total_data,
5867                         state->max_data_return);
5868                 END_PROFILE(Trans2_findfirst);
5869                 break;
5870         }
5871
5872         case TRANSACT2_FINDNEXT:
5873         {
5874                 START_PROFILE(Trans2_findnext);
5875                 outsize = call_trans2findnext(
5876                         conn, inbuf, outbuf, size, bufsize, 
5877                         &state->param, state->total_param,
5878                         &state->data, state->total_data,
5879                         state->max_data_return);
5880                 END_PROFILE(Trans2_findnext);
5881                 break;
5882         }
5883
5884         case TRANSACT2_QFSINFO:
5885         {
5886                 START_PROFILE(Trans2_qfsinfo);
5887                 outsize = call_trans2qfsinfo(
5888                         conn, inbuf, outbuf, size, bufsize,
5889                         &state->param, state->total_param,
5890                         &state->data, state->total_data,
5891                         state->max_data_return);
5892                 END_PROFILE(Trans2_qfsinfo);
5893             break;
5894         }
5895
5896         case TRANSACT2_SETFSINFO:
5897         {
5898                 START_PROFILE(Trans2_setfsinfo);
5899                 outsize = call_trans2setfsinfo(
5900                         conn, inbuf, outbuf, size, bufsize, 
5901                         &state->param, state->total_param,
5902                         &state->data, state->total_data,
5903                         state->max_data_return);
5904                 END_PROFILE(Trans2_setfsinfo);
5905                 break;
5906         }
5907
5908         case TRANSACT2_QPATHINFO:
5909         case TRANSACT2_QFILEINFO:
5910         {
5911                 START_PROFILE(Trans2_qpathinfo);
5912                 outsize = call_trans2qfilepathinfo(
5913                         conn, inbuf, outbuf, size, bufsize, state->call,
5914                         &state->param, state->total_param,
5915                         &state->data, state->total_data,
5916                         state->max_data_return);
5917                 END_PROFILE(Trans2_qpathinfo);
5918                 break;
5919         }
5920
5921         case TRANSACT2_SETPATHINFO:
5922         case TRANSACT2_SETFILEINFO:
5923         {
5924                 START_PROFILE(Trans2_setpathinfo);
5925                 outsize = call_trans2setfilepathinfo(
5926                         conn, inbuf, outbuf, size, bufsize, state->call,
5927                         &state->param, state->total_param,
5928                         &state->data, state->total_data,
5929                         state->max_data_return);
5930                 END_PROFILE(Trans2_setpathinfo);
5931                 break;
5932         }
5933
5934         case TRANSACT2_FINDNOTIFYFIRST:
5935         {
5936                 START_PROFILE(Trans2_findnotifyfirst);
5937                 outsize = call_trans2findnotifyfirst(
5938                         conn, inbuf, outbuf, size, bufsize, 
5939                         &state->param, state->total_param,
5940                         &state->data, state->total_data,
5941                         state->max_data_return);
5942                 END_PROFILE(Trans2_findnotifyfirst);
5943                 break;
5944         }
5945
5946         case TRANSACT2_FINDNOTIFYNEXT:
5947         {
5948                 START_PROFILE(Trans2_findnotifynext);
5949                 outsize = call_trans2findnotifynext(
5950                         conn, inbuf, outbuf, size, bufsize, 
5951                         &state->param, state->total_param,
5952                         &state->data, state->total_data,
5953                         state->max_data_return);
5954                 END_PROFILE(Trans2_findnotifynext);
5955                 break;
5956         }
5957
5958         case TRANSACT2_MKDIR:
5959         {
5960                 START_PROFILE(Trans2_mkdir);
5961                 outsize = call_trans2mkdir(
5962                         conn, inbuf, outbuf, size, bufsize,
5963                         &state->param, state->total_param,
5964                         &state->data, state->total_data,
5965                         state->max_data_return);
5966                 END_PROFILE(Trans2_mkdir);
5967                 break;
5968         }
5969
5970         case TRANSACT2_GET_DFS_REFERRAL:
5971         {
5972                 START_PROFILE(Trans2_get_dfs_referral);
5973                 outsize = call_trans2getdfsreferral(
5974                         conn, inbuf, outbuf, size, bufsize,
5975                         &state->param, state->total_param,
5976                         &state->data, state->total_data,
5977                         state->max_data_return);
5978                 END_PROFILE(Trans2_get_dfs_referral);
5979                 break;
5980         }
5981
5982         case TRANSACT2_IOCTL:
5983         {
5984                 START_PROFILE(Trans2_ioctl);
5985                 outsize = call_trans2ioctl(
5986                         conn, inbuf, outbuf, size, bufsize,
5987                         &state->param, state->total_param,
5988                         &state->data, state->total_data,
5989                         state->max_data_return);
5990                 END_PROFILE(Trans2_ioctl);
5991                 break;
5992         }
5993
5994         default:
5995                 /* Error in request */
5996                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5997                 outsize = ERROR_DOS(ERRSRV,ERRerror);
5998         }
5999
6000         return outsize;
6001 }
6002
6003 /****************************************************************************
6004  Reply to a SMBtrans2.
6005  ****************************************************************************/
6006
6007 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6008                  int size, int bufsize)
6009 {
6010         int outsize = 0;
6011         unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6012         unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6013         unsigned int psoff = SVAL(inbuf, smb_psoff);
6014         unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6015         unsigned int tran_call = SVAL(inbuf, smb_setup0);
6016         struct trans_state *state;
6017         NTSTATUS result;
6018
6019         START_PROFILE(SMBtrans2);
6020
6021         result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6022         if (!NT_STATUS_IS_OK(result)) {
6023                 DEBUG(2, ("Got invalid trans2 request: %s\n",
6024                           nt_errstr(result)));
6025                 END_PROFILE(SMBtrans2);
6026                 return ERROR_NT(result);
6027         }
6028
6029         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6030             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
6031                 END_PROFILE(SMBtrans2);
6032                 return ERROR_DOS(ERRSRV,ERRaccess);
6033         }
6034
6035         if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6036                 DEBUG(0, ("talloc failed\n"));
6037                 END_PROFILE(SMBtrans2);
6038                 return ERROR_NT(NT_STATUS_NO_MEMORY);
6039         }
6040
6041         state->cmd = SMBtrans2;
6042
6043         state->mid = SVAL(inbuf, smb_mid);
6044         state->vuid = SVAL(inbuf, smb_uid);
6045         state->setup_count = SVAL(inbuf, smb_suwcnt);
6046         state->setup = NULL;
6047         state->total_param = SVAL(inbuf, smb_tpscnt);
6048         state->param = NULL;
6049         state->total_data =  SVAL(inbuf, smb_tdscnt);
6050         state->data = NULL;
6051         state->max_param_return = SVAL(inbuf, smb_mprcnt);
6052         state->max_data_return  = SVAL(inbuf, smb_mdrcnt);
6053         state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6054         state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6055         state->one_way = BITSETW(inbuf+smb_vwv5,1);
6056
6057         state->call = tran_call;
6058
6059         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6060            is so as a sanity check */
6061         if (state->setup_count != 1) {
6062                 /*
6063                  * Need to have rc=0 for ioctl to get job id for OS/2.
6064                  *  Network printing will fail if function is not successful.
6065                  *  Similar function in reply.c will be used if protocol
6066                  *  is LANMAN1.0 instead of LM1.2X002.
6067                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
6068                  *  outbuf doesn't have to be set(only job id is used).
6069                  */
6070                 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6071                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6072                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6073                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6074                 } else {
6075                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6076                         DEBUG(2,("Transaction is %d\n",tran_call));
6077                         TALLOC_FREE(state);
6078                         END_PROFILE(SMBtrans2);
6079                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6080                 }
6081         }
6082
6083         if ((dscnt > state->total_data) || (pscnt > state->total_param))
6084                 goto bad_param;
6085
6086         if (state->total_data) {
6087                 /* Can't use talloc here, the core routines do realloc on the
6088                  * params and data. */
6089                 state->data = (char *)SMB_MALLOC(state->total_data);
6090                 if (state->data == NULL) {
6091                         DEBUG(0,("reply_trans2: data malloc fail for %u "
6092                                  "bytes !\n", (unsigned int)state->total_data));
6093                         TALLOC_FREE(state);
6094                         END_PROFILE(SMBtrans2);
6095                         return(ERROR_DOS(ERRDOS,ERRnomem));
6096                 }
6097                 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6098                         goto bad_param;
6099                 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6100                     (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6101                         goto bad_param;
6102
6103                 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6104         }
6105
6106         if (state->total_param) {
6107                 /* Can't use talloc here, the core routines do realloc on the
6108                  * params and data. */
6109                 state->param = (char *)SMB_MALLOC(state->total_param);
6110                 if (state->param == NULL) {
6111                         DEBUG(0,("reply_trans: param malloc fail for %u "
6112                                  "bytes !\n", (unsigned int)state->total_param));
6113                         SAFE_FREE(state->data);
6114                         TALLOC_FREE(state);
6115                         END_PROFILE(SMBtrans2);
6116                         return(ERROR_DOS(ERRDOS,ERRnomem));
6117                 } 
6118                 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6119                         goto bad_param;
6120                 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6121                     (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6122                         goto bad_param;
6123
6124                 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6125         }
6126
6127         state->received_data  = dscnt;
6128         state->received_param = pscnt;
6129
6130         if ((state->received_param == state->total_param) &&
6131             (state->received_data == state->total_data)) {
6132
6133                 outsize = handle_trans2(conn, state, inbuf, outbuf,
6134                                         size, bufsize);
6135                 SAFE_FREE(state->data);
6136                 SAFE_FREE(state->param);
6137                 TALLOC_FREE(state);
6138                 END_PROFILE(SMBtrans2);
6139                 return outsize;
6140         }
6141
6142         DLIST_ADD(conn->pending_trans, state);
6143
6144         /* We need to send an interim response then receive the rest
6145            of the parameter/data bytes */
6146         outsize = set_message(outbuf,0,0,False);
6147         show_msg(outbuf);
6148         END_PROFILE(SMBtrans2);
6149         return outsize;
6150
6151   bad_param:
6152
6153         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6154         SAFE_FREE(state->data);
6155         SAFE_FREE(state->param);
6156         TALLOC_FREE(state);
6157         END_PROFILE(SMBtrans2);
6158         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6159 }
6160
6161
6162 /****************************************************************************
6163  Reply to a SMBtranss2
6164  ****************************************************************************/
6165
6166 int reply_transs2(connection_struct *conn,
6167                   char *inbuf,char *outbuf,int size,int bufsize)
6168 {
6169         int outsize = 0;
6170         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6171         struct trans_state *state;
6172
6173         START_PROFILE(SMBtranss2);
6174
6175         show_msg(inbuf);
6176
6177         for (state = conn->pending_trans; state != NULL;
6178              state = state->next) {
6179                 if (state->mid == SVAL(inbuf,smb_mid)) {
6180                         break;
6181                 }
6182         }
6183
6184         if ((state == NULL) || (state->cmd != SMBtrans2)) {
6185                 END_PROFILE(SMBtranss2);
6186                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6187         }
6188
6189         /* Revise state->total_param and state->total_data in case they have
6190            changed downwards */
6191
6192         if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6193                 state->total_param = SVAL(inbuf, smb_tpscnt);
6194         if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6195                 state->total_data = SVAL(inbuf, smb_tdscnt);
6196
6197         pcnt = SVAL(inbuf, smb_spscnt);
6198         poff = SVAL(inbuf, smb_spsoff);
6199         pdisp = SVAL(inbuf, smb_spsdisp);
6200
6201         dcnt = SVAL(inbuf, smb_sdscnt);
6202         doff = SVAL(inbuf, smb_sdsoff);
6203         ddisp = SVAL(inbuf, smb_sdsdisp);
6204
6205         state->received_param += pcnt;
6206         state->received_data += dcnt;
6207                 
6208         if ((state->received_data > state->total_data) ||
6209             (state->received_param > state->total_param))
6210                 goto bad_param;
6211
6212         if (pcnt) {
6213                 if (pdisp+pcnt > state->total_param)
6214                         goto bad_param;
6215                 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6216                         goto bad_param;
6217                 if (pdisp > state->total_param)
6218                         goto bad_param;
6219                 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6220                     (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6221                         goto bad_param;
6222                 if (state->param + pdisp < state->param)
6223                         goto bad_param;
6224
6225                 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6226                        pcnt);
6227         }
6228
6229         if (dcnt) {
6230                 if (ddisp+dcnt > state->total_data)
6231                         goto bad_param;
6232                 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6233                         goto bad_param;
6234                 if (ddisp > state->total_data)
6235                         goto bad_param;
6236                 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6237                     (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6238                         goto bad_param;
6239                 if (state->data + ddisp < state->data)
6240                         goto bad_param;
6241
6242                 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6243                        dcnt);      
6244         }
6245
6246         if ((state->received_param < state->total_param) ||
6247             (state->received_data < state->total_data)) {
6248                 END_PROFILE(SMBtranss2);
6249                 return -1;
6250         }
6251
6252         /* construct_reply_common has done us the favor to pre-fill the
6253          * command field with SMBtranss2 which is wrong :-)
6254          */
6255         SCVAL(outbuf,smb_com,SMBtrans2);
6256
6257         outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6258
6259         DLIST_REMOVE(conn->pending_trans, state);
6260         SAFE_FREE(state->data);
6261         SAFE_FREE(state->param);
6262         TALLOC_FREE(state);
6263
6264         if (outsize == 0) {
6265                 END_PROFILE(SMBtranss2);
6266                 return(ERROR_DOS(ERRSRV,ERRnosupport));
6267         }
6268         
6269         END_PROFILE(SMBtranss2);
6270         return(outsize);
6271
6272   bad_param:
6273
6274         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6275         DLIST_REMOVE(conn->pending_trans, state);
6276         SAFE_FREE(state->data);
6277         SAFE_FREE(state->param);
6278         TALLOC_FREE(state);
6279         END_PROFILE(SMBtranss2);
6280         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6281 }