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