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