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