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