512b3162fadf4fd975d7d98fee5a9f2dfda365b9
[tprouty/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(fsp,
4809                                 lock_pid,
4810                                 count,
4811                                 offset,
4812                                 POSIX_LOCK);
4813         } else {
4814                 struct byte_range_lock *br_lck = do_lock(fsp,
4815                                                         lock_pid,
4816                                                         count,
4817                                                         offset,
4818                                                         lock_type,
4819                                                         POSIX_LOCK,
4820                                                         blocking_lock,
4821                                                         &status);
4822
4823                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4824                         /*
4825                          * A blocking lock was requested. Package up
4826                          * this smb into a queued request and push it
4827                          * onto the blocking lock queue.
4828                          */
4829                         if(push_blocking_lock_request(br_lck,
4830                                                 inbuf, length,
4831                                                 fsp,
4832                                                 -1, /* infinite timeout. */
4833                                                 0,
4834                                                 lock_pid,
4835                                                 lock_type,
4836                                                 POSIX_LOCK,
4837                                                 offset,
4838                                                 count)) {
4839                                 TALLOC_FREE(br_lck);
4840                                 return status;
4841                         }
4842                 }
4843                 TALLOC_FREE(br_lck);
4844         }
4845
4846         return status;
4847 }
4848
4849 /****************************************************************************
4850  Deal with SMB_INFO_STANDARD.
4851 ****************************************************************************/
4852
4853 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4854                                         const char *pdata,
4855                                         int total_data,
4856                                         files_struct *fsp,
4857                                         const char *fname,
4858                                         const SMB_STRUCT_STAT *psbuf)
4859 {
4860         struct timespec ts[2];
4861
4862         if (total_data < 12) {
4863                 return NT_STATUS_INVALID_PARAMETER;
4864         }
4865
4866         /* access time */
4867         ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4868         /* write time */
4869         ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4870
4871         DEBUG(10,("smb_set_info_standard: file %s\n",
4872                 fname ? fname : fsp->fsp_name ));
4873
4874         return smb_set_file_time(conn,
4875                                 fsp,
4876                                 fname,
4877                                 psbuf,
4878                                 ts);
4879 }
4880
4881 /****************************************************************************
4882  Deal with SMB_SET_FILE_BASIC_INFO.
4883 ****************************************************************************/
4884
4885 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4886                                         const char *pdata,
4887                                         int total_data,
4888                                         files_struct *fsp,
4889                                         const char *fname,
4890                                         SMB_STRUCT_STAT *psbuf)
4891 {
4892         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4893         struct timespec write_time;
4894         struct timespec changed_time;
4895         uint32 dosmode = 0;
4896         struct timespec ts[2];
4897         NTSTATUS status = NT_STATUS_OK;
4898
4899         if (total_data < 36) {
4900                 return NT_STATUS_INVALID_PARAMETER;
4901         }
4902
4903         /* Set the attributes */
4904         dosmode = IVAL(pdata,32);
4905         status = smb_set_file_dosmode(conn,
4906                                         fname,
4907                                         psbuf,
4908                                         dosmode);
4909         if (!NT_STATUS_IS_OK(status)) {
4910                 return status;
4911         }
4912
4913         /* Ignore create time at offset pdata. */
4914
4915         /* access time */
4916         ts[0] = interpret_long_date(pdata+8);
4917
4918         write_time = interpret_long_date(pdata+16);
4919         changed_time = interpret_long_date(pdata+24);
4920
4921         /* mtime */
4922         ts[1] = timespec_min(&write_time, &changed_time);
4923
4924         if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4925                 ts[1] = write_time;
4926         }
4927
4928         /* Prefer a defined time to an undefined one. */
4929         if (null_timespec(ts[1])) {
4930                 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4931         }
4932
4933         DEBUG(10,("smb_set_file_basic_info: file %s\n",
4934                 fname ? fname : fsp->fsp_name ));
4935
4936         return smb_set_file_time(conn,
4937                                 fsp,
4938                                 fname,
4939                                 psbuf,
4940                                 ts);
4941 }
4942
4943 /****************************************************************************
4944  Deal with SMB_SET_FILE_ALLOCATION_INFO.
4945 ****************************************************************************/
4946
4947 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4948                                         const char *pdata,
4949                                         int total_data,
4950                                         files_struct *fsp,
4951                                         const char *fname,
4952                                         SMB_STRUCT_STAT *psbuf)
4953 {
4954         SMB_BIG_UINT allocation_size = 0;
4955         NTSTATUS status = NT_STATUS_OK;
4956         files_struct *new_fsp = NULL;
4957
4958         if (!VALID_STAT(*psbuf)) {
4959                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4960         }
4961
4962         if (total_data < 8) {
4963                 return NT_STATUS_INVALID_PARAMETER;
4964         }
4965
4966         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4967 #ifdef LARGE_SMB_OFF_T
4968         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4969 #else /* LARGE_SMB_OFF_T */
4970         if (IVAL(pdata,4) != 0) {
4971                 /* more than 32 bits? */
4972                 return NT_STATUS_INVALID_PARAMETER;
4973         }
4974 #endif /* LARGE_SMB_OFF_T */
4975
4976         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4977                         fname, (double)allocation_size ));
4978
4979         if (allocation_size) {
4980                 allocation_size = smb_roundup(conn, allocation_size);
4981         }
4982
4983         if(allocation_size == get_file_size(*psbuf)) {
4984                 return NT_STATUS_OK;
4985         }
4986  
4987         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4988                         fname, (double)allocation_size ));
4989  
4990         if (fsp && fsp->fh->fd != -1) {
4991                 /* Open file handle. */
4992                 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4993                         return map_nt_error_from_unix(errno);
4994                 }
4995                 return NT_STATUS_OK;
4996         }
4997
4998         /* Pathname or stat or directory file. */
4999
5000         status = open_file_ntcreate(conn, fname, psbuf,
5001                                 FILE_WRITE_DATA,
5002                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5003                                 FILE_OPEN,
5004                                 0,
5005                                 FILE_ATTRIBUTE_NORMAL,
5006                                 FORCE_OPLOCK_BREAK_TO_NONE,
5007                                 NULL, &new_fsp);
5008  
5009         if (!NT_STATUS_IS_OK(status)) {
5010                 /* NB. We check for open_was_deferred in the caller. */
5011                 return status;
5012         }
5013         if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5014                 status = map_nt_error_from_unix(errno);
5015                 close_file(new_fsp,NORMAL_CLOSE);
5016                 return status;
5017         }
5018
5019         close_file(new_fsp,NORMAL_CLOSE);
5020         return NT_STATUS_OK;
5021 }
5022
5023 /****************************************************************************
5024  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5025 ****************************************************************************/
5026
5027 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5028                                         const char *pdata,
5029                                         int total_data,
5030                                         files_struct *fsp,
5031                                         const char *fname,
5032                                         SMB_STRUCT_STAT *psbuf)
5033 {
5034         SMB_OFF_T size;
5035
5036         if (total_data < 8) {
5037                 return NT_STATUS_INVALID_PARAMETER;
5038         }
5039
5040         size = IVAL(pdata,0);
5041 #ifdef LARGE_SMB_OFF_T
5042         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5043 #else /* LARGE_SMB_OFF_T */
5044         if (IVAL(pdata,4) != 0) {
5045                 /* more than 32 bits? */
5046                 return NT_STATUS_INVALID_PARAMETER;
5047         }
5048 #endif /* LARGE_SMB_OFF_T */
5049         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5050                 "file %s to %.0f\n", fname, (double)size ));
5051
5052         return smb_set_file_size(conn,
5053                                 fsp,
5054                                 fname,
5055                                 psbuf,
5056                                 size);
5057 }
5058
5059 /****************************************************************************
5060  Allow a UNIX info mknod.
5061 ****************************************************************************/
5062
5063 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5064                                         const char *pdata,
5065                                         int total_data,
5066                                         const char *fname,
5067                                         SMB_STRUCT_STAT *psbuf)
5068 {
5069         uint32 file_type = IVAL(pdata,56);
5070 #if defined(HAVE_MAKEDEV)
5071         uint32 dev_major = IVAL(pdata,60);
5072         uint32 dev_minor = IVAL(pdata,68);
5073 #endif
5074         SMB_DEV_T dev = (SMB_DEV_T)0;
5075         uint32 raw_unixmode = IVAL(pdata,84);
5076         NTSTATUS status;
5077         mode_t unixmode;
5078
5079         if (total_data < 100) {
5080                 return NT_STATUS_INVALID_PARAMETER;
5081         }
5082
5083         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5084         if (!NT_STATUS_IS_OK(status)) {
5085                 return status;
5086         }
5087
5088 #if defined(HAVE_MAKEDEV)
5089         dev = makedev(dev_major, dev_minor);
5090 #endif
5091
5092         switch (file_type) {
5093 #if defined(S_IFIFO)
5094                 case UNIX_TYPE_FIFO:
5095                         unixmode |= S_IFIFO;
5096                         break;
5097 #endif
5098 #if defined(S_IFSOCK)
5099                 case UNIX_TYPE_SOCKET:
5100                         unixmode |= S_IFSOCK;
5101                         break;
5102 #endif
5103 #if defined(S_IFCHR)
5104                 case UNIX_TYPE_CHARDEV:
5105                         unixmode |= S_IFCHR;
5106                         break;
5107 #endif
5108 #if defined(S_IFBLK)
5109                 case UNIX_TYPE_BLKDEV:
5110                         unixmode |= S_IFBLK;
5111                         break;
5112 #endif
5113                 default:
5114                         return NT_STATUS_INVALID_PARAMETER;
5115         }
5116
5117         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5118 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5119
5120         /* Ok - do the mknod. */
5121         if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5122                 return map_nt_error_from_unix(errno);
5123         }
5124
5125         /* If any of the other "set" calls fail we
5126          * don't want to end up with a half-constructed mknod.
5127          */
5128
5129         if (lp_inherit_perms(SNUM(conn))) {
5130                 inherit_access_acl(
5131                         conn, parent_dirname(fname),
5132                         fname, unixmode);
5133         }
5134
5135         if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5136                 status = map_nt_error_from_unix(errno);
5137                 SMB_VFS_UNLINK(conn,fname);
5138                 return status;
5139         }
5140         return NT_STATUS_OK;
5141 }
5142
5143 /****************************************************************************
5144  Deal with SMB_SET_FILE_UNIX_BASIC.
5145 ****************************************************************************/
5146
5147 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5148                                         const char *pdata,
5149                                         int total_data,
5150                                         files_struct *fsp,
5151                                         const char *fname,
5152                                         SMB_STRUCT_STAT *psbuf)
5153 {
5154         struct timespec ts[2];
5155         uint32 raw_unixmode;
5156         mode_t unixmode;
5157         SMB_OFF_T size = 0;
5158         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5159         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5160         NTSTATUS status = NT_STATUS_OK;
5161         BOOL delete_on_fail = False;
5162         enum perm_type ptype;
5163
5164         if (total_data < 100) {
5165                 return NT_STATUS_INVALID_PARAMETER;
5166         }
5167
5168         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5169            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5170                 size=IVAL(pdata,0); /* first 8 Bytes are size */
5171 #ifdef LARGE_SMB_OFF_T
5172                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5173 #else /* LARGE_SMB_OFF_T */
5174                 if (IVAL(pdata,4) != 0) {
5175                         /* more than 32 bits? */
5176                         return NT_STATUS_INVALID_PARAMETER;
5177                 }
5178 #endif /* LARGE_SMB_OFF_T */
5179         }
5180
5181         ts[0] = interpret_long_date(pdata+24); /* access_time */
5182         ts[1] = interpret_long_date(pdata+32); /* modification_time */
5183         set_owner = (uid_t)IVAL(pdata,40);
5184         set_grp = (gid_t)IVAL(pdata,48);
5185         raw_unixmode = IVAL(pdata,84);
5186
5187         if (VALID_STAT(*psbuf)) {
5188                 if (S_ISDIR(psbuf->st_mode)) {
5189                         ptype = PERM_EXISTING_DIR;
5190                 } else {
5191                         ptype = PERM_EXISTING_FILE;
5192                 }
5193         } else {
5194                 ptype = PERM_NEW_FILE;
5195         }
5196
5197         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5198         if (!NT_STATUS_IS_OK(status)) {
5199                 return status;
5200         }
5201
5202         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5203 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5204                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5205
5206         if (!VALID_STAT(*psbuf)) {
5207                 /*
5208                  * The only valid use of this is to create character and block
5209                  * devices, and named pipes. This is deprecated (IMHO) and 
5210                  * a new info level should be used for mknod. JRA.
5211                  */
5212
5213                 status = smb_unix_mknod(conn,
5214                                         pdata,
5215                                         total_data,
5216                                         fname,
5217                                         psbuf);
5218                 if (!NT_STATUS_IS_OK(status)) {
5219                         return status;
5220                 }
5221
5222                 /* Ensure we don't try and change anything else. */
5223                 raw_unixmode = SMB_MODE_NO_CHANGE;
5224                 size = get_file_size(*psbuf);
5225                 ts[0] = get_atimespec(psbuf);
5226                 ts[1] = get_mtimespec(psbuf);
5227                 /* 
5228                  * We continue here as we might want to change the 
5229                  * owner uid/gid.
5230                  */
5231                 delete_on_fail = True;
5232         }
5233
5234 #if 1
5235         /* Horrible backwards compatibility hack as an old server bug
5236          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5237          * */
5238
5239         if (!size) {
5240                 size = get_file_size(*psbuf);
5241         }
5242 #endif
5243
5244         /*
5245          * Deal with the UNIX specific mode set.
5246          */
5247
5248         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5249                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5250                         (unsigned int)unixmode, fname ));
5251                 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5252                         return map_nt_error_from_unix(errno);
5253                 }
5254         }
5255
5256         /*
5257          * Deal with the UNIX specific uid set.
5258          */
5259
5260         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5261                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
5262                         (unsigned int)set_owner, fname ));
5263                 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
5264                         status = map_nt_error_from_unix(errno);
5265                         if (delete_on_fail) {
5266                                 SMB_VFS_UNLINK(conn,fname);
5267                         }
5268                         return status;
5269                 }
5270         }
5271
5272         /*
5273          * Deal with the UNIX specific gid set.
5274          */
5275
5276         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5277                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5278                         (unsigned int)set_owner, fname ));
5279                 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5280                         status = map_nt_error_from_unix(errno);
5281                         if (delete_on_fail) {
5282                                 SMB_VFS_UNLINK(conn,fname);
5283                         }
5284                         return status;
5285                 }
5286         }
5287
5288         /* Deal with any size changes. */
5289
5290         status = smb_set_file_size(conn,
5291                                 fsp,
5292                                 fname,
5293                                 psbuf,
5294                                 size);
5295         if (!NT_STATUS_IS_OK(status)) {
5296                 return status;
5297         }
5298
5299         /* Deal with any time changes. */
5300
5301         return smb_set_file_time(conn,
5302                                 fsp,
5303                                 fname,
5304                                 psbuf,
5305                                 ts);
5306 }
5307
5308 /****************************************************************************
5309  Deal with SMB_SET_FILE_UNIX_INFO2.
5310 ****************************************************************************/
5311
5312 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5313                                         const char *pdata,
5314                                         int total_data,
5315                                         files_struct *fsp,
5316                                         const char *fname,
5317                                         SMB_STRUCT_STAT *psbuf)
5318 {
5319         NTSTATUS status;
5320         uint32 smb_fflags;
5321         uint32 smb_fmask;
5322
5323         if (total_data < 116) {
5324                 return NT_STATUS_INVALID_PARAMETER;
5325         }
5326
5327         /* Start by setting all the fields that are common between UNIX_BASIC
5328          * and UNIX_INFO2.
5329          */
5330         status = smb_set_file_unix_basic(conn, pdata, total_data,
5331                                 fsp, fname, psbuf);
5332         if (!NT_STATUS_IS_OK(status)) {
5333                 return status;
5334         }
5335
5336         smb_fflags = IVAL(pdata, 108);
5337         smb_fmask = IVAL(pdata, 112);
5338
5339         /* NB: We should only attempt to alter the file flags if the client
5340          * sends a non-zero mask.
5341          */
5342         if (smb_fmask != 0) {
5343                 int stat_fflags = 0;
5344
5345                 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5346                             &stat_fflags)) {
5347                         /* Client asked to alter a flag we don't understand. */
5348                         return NT_STATUS_INVALID_PARAMETER;
5349                 }
5350
5351                 if (fsp && fsp->fh->fd != -1) {
5352                         /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
5353                         return NT_STATUS_NOT_SUPPORTED;
5354                 } else {
5355                         if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5356                                 return map_nt_error_from_unix(errno);
5357                         }
5358                 }
5359         }
5360
5361         /* XXX: need to add support for changing the create_time here. You
5362          * can do this for paths on Darwin with setattrlist(2). The right way
5363          * to hook this up is probably by extending the VFS utimes interface.
5364          */
5365
5366         return NT_STATUS_OK;
5367 }
5368
5369 /****************************************************************************
5370  Create a directory with POSIX semantics.
5371 ****************************************************************************/
5372
5373 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5374                                 char **ppdata,
5375                                 int total_data,
5376                                 const char *fname,
5377                                 SMB_STRUCT_STAT *psbuf,
5378                                 int *pdata_return_size)
5379 {
5380         NTSTATUS status = NT_STATUS_OK;
5381         uint32 raw_unixmode = 0;
5382         uint32 mod_unixmode = 0;
5383         mode_t unixmode = (mode_t)0;
5384         files_struct *fsp = NULL;
5385         uint16 info_level_return = 0;
5386         int info;
5387         char *pdata = *ppdata;
5388
5389         if (total_data < 18) {
5390                 return NT_STATUS_INVALID_PARAMETER;
5391         }
5392
5393         raw_unixmode = IVAL(pdata,8);
5394         /* Next 4 bytes are not yet defined. */
5395
5396         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5397         if (!NT_STATUS_IS_OK(status)) {
5398                 return status;
5399         }
5400
5401         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5402
5403         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5404                 fname, (unsigned int)unixmode ));
5405
5406         status = open_directory(conn,
5407                                 fname,
5408                                 psbuf,
5409                                 FILE_READ_ATTRIBUTES, /* Just a stat open */
5410                                 FILE_SHARE_NONE, /* Ignored for stat opens */
5411                                 FILE_CREATE,
5412                                 0,
5413                                 mod_unixmode,
5414                                 &info,
5415                                 &fsp);
5416
5417         if (NT_STATUS_IS_OK(status)) {
5418                 close_file(fsp, NORMAL_CLOSE);
5419         }
5420
5421         info_level_return = SVAL(pdata,16);
5422  
5423         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5424                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5425         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5426                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5427         } else {
5428                 *pdata_return_size = 12;
5429         }
5430
5431         /* Realloc the data size */
5432         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5433         if (*ppdata == NULL) {
5434                 *pdata_return_size = 0;
5435                 return NT_STATUS_NO_MEMORY;
5436         }
5437         pdata = *ppdata;
5438
5439         SSVAL(pdata,0,NO_OPLOCK_RETURN);
5440         SSVAL(pdata,2,0); /* No fnum. */
5441         SIVAL(pdata,4,info); /* Was directory created. */
5442
5443         switch (info_level_return) {
5444                 case SMB_QUERY_FILE_UNIX_BASIC:
5445                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5446                         SSVAL(pdata,10,0); /* Padding. */
5447                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5448                         break;
5449                 case SMB_QUERY_FILE_UNIX_INFO2:
5450                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5451                         SSVAL(pdata,10,0); /* Padding. */
5452                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5453                         break;
5454                 default:
5455                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5456                         SSVAL(pdata,10,0); /* Padding. */
5457                         break;
5458         }
5459
5460         return status;
5461 }
5462
5463 /****************************************************************************
5464  Open/Create a file with POSIX semantics.
5465 ****************************************************************************/
5466
5467 static NTSTATUS smb_posix_open(connection_struct *conn,
5468                                 char **ppdata,
5469                                 int total_data,
5470                                 const char *fname,
5471                                 SMB_STRUCT_STAT *psbuf,
5472                                 int *pdata_return_size)
5473 {
5474         BOOL extended_oplock_granted = False;
5475         char *pdata = *ppdata;
5476         uint32 flags = 0;
5477         uint32 wire_open_mode = 0;
5478         uint32 raw_unixmode = 0;
5479         uint32 mod_unixmode = 0;
5480         uint32 create_disp = 0;
5481         uint32 access_mask = 0;
5482         uint32 create_options = 0;
5483         NTSTATUS status = NT_STATUS_OK;
5484         mode_t unixmode = (mode_t)0;
5485         files_struct *fsp = NULL;
5486         int oplock_request = 0;
5487         int info = 0;
5488         uint16 info_level_return = 0;
5489
5490         if (total_data < 18) {
5491                 return NT_STATUS_INVALID_PARAMETER;
5492         }
5493
5494         flags = IVAL(pdata,0);
5495         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5496         if (oplock_request) {
5497                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5498         }
5499
5500         wire_open_mode = IVAL(pdata,4);
5501
5502         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5503                 return smb_posix_mkdir(conn,
5504                                         ppdata,
5505                                         total_data,
5506                                         fname,
5507                                         psbuf,
5508                                         pdata_return_size);
5509         }
5510
5511         switch (wire_open_mode & SMB_ACCMODE) {
5512                 case SMB_O_RDONLY:
5513                         access_mask = FILE_READ_DATA;
5514                         break;
5515                 case SMB_O_WRONLY:
5516                         access_mask = FILE_WRITE_DATA;
5517                         break;
5518                 case SMB_O_RDWR:
5519                         access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5520                         break;
5521                 default:
5522                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5523                                 (unsigned int)wire_open_mode ));
5524                         return NT_STATUS_INVALID_PARAMETER;
5525         }
5526
5527         wire_open_mode &= ~SMB_ACCMODE;
5528
5529         if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5530                 create_disp = FILE_CREATE;
5531         } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5532                 create_disp = FILE_OVERWRITE_IF;
5533         } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5534                 create_disp = FILE_OPEN_IF;
5535         } else {
5536                 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5537                         (unsigned int)wire_open_mode ));
5538                 return NT_STATUS_INVALID_PARAMETER;
5539         }
5540
5541         raw_unixmode = IVAL(pdata,8);
5542         /* Next 4 bytes are not yet defined. */
5543
5544         status = unix_perms_from_wire(conn,
5545                                 psbuf,
5546                                 raw_unixmode,
5547                                 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5548                                 &unixmode);
5549
5550         if (!NT_STATUS_IS_OK(status)) {
5551                 return status;
5552         }
5553
5554         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5555
5556         if (wire_open_mode & SMB_O_SYNC) {
5557                 create_options |= FILE_WRITE_THROUGH;
5558         }
5559         if (wire_open_mode & SMB_O_APPEND) {
5560                 access_mask |= FILE_APPEND_DATA;
5561         }
5562         if (wire_open_mode & SMB_O_DIRECT) {
5563                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5564         }
5565
5566         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5567                 fname,
5568                 (unsigned int)wire_open_mode,
5569                 (unsigned int)unixmode ));
5570
5571         status = open_file_ntcreate(conn,
5572                                 fname,
5573                                 psbuf,
5574                                 access_mask,
5575                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5576                                 create_disp,
5577                                 0,              /* no create options yet. */
5578                                 mod_unixmode,
5579                                 oplock_request,
5580                                 &info,
5581                                 &fsp);
5582
5583         if (!NT_STATUS_IS_OK(status)) {
5584                 return status;
5585         }
5586
5587         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5588                 extended_oplock_granted = True;
5589         }
5590
5591         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5592                 extended_oplock_granted = True;
5593         }
5594
5595         info_level_return = SVAL(pdata,16);
5596  
5597         /* Allocate the correct return size. */
5598
5599         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5600                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5601         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5602                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5603         } else {
5604                 *pdata_return_size = 12;
5605         }
5606
5607         /* Realloc the data size */
5608         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5609         if (*ppdata == NULL) {
5610                 close_file(fsp,ERROR_CLOSE);
5611                 *pdata_return_size = 0;
5612                 return NT_STATUS_NO_MEMORY;
5613         }
5614         pdata = *ppdata;
5615
5616         if (extended_oplock_granted) {
5617                 if (flags & REQUEST_BATCH_OPLOCK) {
5618                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5619                 } else {
5620                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5621                 }
5622         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5623                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5624         } else {
5625                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5626         }
5627
5628         SSVAL(pdata,2,fsp->fnum);
5629         SIVAL(pdata,4,info); /* Was file created etc. */
5630
5631         switch (info_level_return) {
5632                 case SMB_QUERY_FILE_UNIX_BASIC:
5633                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5634                         SSVAL(pdata,10,0); /* padding. */
5635                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5636                         break;
5637                 case SMB_QUERY_FILE_UNIX_INFO2:
5638                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5639                         SSVAL(pdata,10,0); /* padding. */
5640                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5641                         break;
5642                 default:
5643                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5644                         SSVAL(pdata,10,0); /* padding. */
5645                         break;
5646         }
5647         return NT_STATUS_OK;
5648 }
5649
5650 /****************************************************************************
5651  Delete a file with POSIX semantics.
5652 ****************************************************************************/
5653
5654 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5655                                 const char *pdata,
5656                                 int total_data,
5657                                 const char *fname,
5658                                 SMB_STRUCT_STAT *psbuf)
5659 {
5660         NTSTATUS status = NT_STATUS_OK;
5661         files_struct *fsp = NULL;
5662         uint16 flags = 0;
5663         int info = 0;
5664
5665         if (total_data < 2) {
5666                 return NT_STATUS_INVALID_PARAMETER;
5667         }
5668
5669         flags = SVAL(pdata,0);
5670
5671         if (!VALID_STAT(*psbuf)) {
5672                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5673         }
5674
5675         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5676                         !VALID_STAT_OF_DIR(*psbuf)) {
5677                 return NT_STATUS_NOT_A_DIRECTORY;
5678         }
5679
5680         DEBUG(10,("smb_posix_unlink: %s %s\n",
5681                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5682                 fname));
5683
5684         if (VALID_STAT_OF_DIR(*psbuf)) {
5685                 status = open_directory(conn,
5686                                         fname,
5687                                         psbuf,
5688                                         DELETE_ACCESS,
5689                                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5690                                         FILE_OPEN,
5691                                         FILE_DELETE_ON_CLOSE,
5692                                         FILE_FLAG_POSIX_SEMANTICS|0777,
5693                                         &info,                          
5694                                         &fsp);
5695         } else {
5696                 char del = 1;
5697
5698                 status = open_file_ntcreate(conn,
5699                                 fname,
5700                                 psbuf,
5701                                 DELETE_ACCESS,
5702                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5703                                 FILE_OPEN,
5704                                 0,
5705                                 FILE_FLAG_POSIX_SEMANTICS|0777,
5706                                 0, /* No oplock, but break existing ones. */
5707                                 &info,
5708                                 &fsp);
5709                 /* 
5710                  * For file opens we must set the delete on close
5711                  * after the open.
5712                  */
5713
5714                 if (!NT_STATUS_IS_OK(status)) {
5715                         return status;
5716                 }
5717
5718                 status = smb_set_file_disposition_info(conn,
5719                                                         &del,
5720                                                         1,
5721                                                         fsp,
5722                                                         fname,
5723                                                         psbuf);
5724         }
5725
5726         if (!NT_STATUS_IS_OK(status)) {
5727                 return status;
5728         }
5729         return close_file(fsp, NORMAL_CLOSE);
5730 }
5731
5732 /****************************************************************************
5733  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5734 ****************************************************************************/
5735
5736 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5737                                         unsigned int tran_call,
5738                                         char **pparams, int total_params, char **ppdata, int total_data,
5739                                         unsigned int max_data_bytes)
5740 {
5741         char *params = *pparams;
5742         char *pdata = *ppdata;
5743         uint16 info_level;
5744         SMB_STRUCT_STAT sbuf;
5745         pstring fname;
5746         files_struct *fsp = NULL;
5747         NTSTATUS status = NT_STATUS_OK;
5748         int data_return_size = 0;
5749
5750         if (!params) {
5751                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5752         }
5753
5754         ZERO_STRUCT(sbuf);
5755
5756         if (tran_call == TRANSACT2_SETFILEINFO) {
5757                 if (total_params < 4) {
5758                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5759                 }
5760
5761                 fsp = file_fsp(params,0);
5762                 info_level = SVAL(params,2);    
5763
5764                 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5765                         /*
5766                          * This is actually a SETFILEINFO on a directory
5767                          * handle (returned from an NT SMB). NT5.0 seems
5768                          * to do this call. JRA.
5769                          */
5770                         pstrcpy(fname, fsp->fsp_name);
5771                         if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5772                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5773                                 return UNIXERROR(ERRDOS,ERRbadpath);
5774                         }
5775                 } else if (fsp && fsp->print_file) {
5776                         /*
5777                          * Doing a DELETE_ON_CLOSE should cancel a print job.
5778                          */
5779                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5780                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5781
5782                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5783         
5784                                 SSVAL(params,0,0);
5785                                 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5786                                 return(-1);
5787                         } else
5788                                 return (UNIXERROR(ERRDOS,ERRbadpath));
5789             } else {
5790                         /*
5791                          * Original code - this is an open file.
5792                          */
5793                         CHECK_FSP(fsp,conn);
5794
5795                         pstrcpy(fname, fsp->fsp_name);
5796
5797                         if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5798                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5799                                 return(UNIXERROR(ERRDOS,ERRbadfid));
5800                         }
5801                 }
5802         } else {
5803                 /* set path info */
5804                 if (total_params < 7) {
5805                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5806                 }
5807
5808                 info_level = SVAL(params,0);    
5809                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5810                 if (!NT_STATUS_IS_OK(status)) {
5811                         return ERROR_NT(status);
5812                 }
5813
5814                 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5815                 if (!NT_STATUS_IS_OK(status)) {
5816                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5817                                 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5818                         }
5819                         return ERROR_NT(status);
5820                 }
5821
5822                 status = unix_convert(conn, fname, False, NULL, &sbuf);
5823                 if (!NT_STATUS_IS_OK(status)) {
5824                         return ERROR_NT(status);
5825                 }
5826
5827                 status = check_name(conn, fname);
5828                 if (!NT_STATUS_IS_OK(status)) {
5829                         return ERROR_NT(status);
5830                 }
5831
5832                 /*
5833                  * For CIFS UNIX extensions the target name may not exist.
5834                  */
5835
5836                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
5837                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
5838                         return UNIXERROR(ERRDOS,ERRbadpath);
5839                 }    
5840         }
5841
5842         if (!CAN_WRITE(conn)) {
5843                 return ERROR_DOS(ERRSRV,ERRaccess);
5844         }
5845
5846         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5847                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5848         }
5849
5850         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5851                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5852
5853         /* Realloc the parameter size */
5854         *pparams = (char *)SMB_REALLOC(*pparams,2);
5855         if (*pparams == NULL) {
5856                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5857         }
5858         params = *pparams;
5859
5860         SSVAL(params,0,0);
5861
5862         if (fsp && !null_timespec(fsp->pending_modtime)) {
5863                 /* the pending modtime overrides the current modtime */
5864                 set_mtimespec(&sbuf, fsp->pending_modtime);
5865         }
5866
5867         switch (info_level) {
5868
5869                 case SMB_INFO_STANDARD:
5870                 {
5871                         status = smb_set_info_standard(conn,
5872                                         pdata,
5873                                         total_data,
5874                                         fsp,
5875                                         fname,
5876                                         &sbuf);
5877                         break;
5878                 }
5879
5880                 case SMB_INFO_SET_EA:
5881                 {
5882                         status = smb_info_set_ea(conn,
5883                                                 pdata,
5884                                                 total_data,
5885                                                 fsp,
5886                                                 fname);
5887                         break;
5888                 }
5889
5890                 case SMB_SET_FILE_BASIC_INFO:
5891                 case SMB_FILE_BASIC_INFORMATION:
5892                 {
5893                         status = smb_set_file_basic_info(conn,
5894                                                         pdata,
5895                                                         total_data,
5896                                                         fsp,
5897                                                         fname,
5898                                                         &sbuf);
5899                         break;
5900                 }
5901
5902                 case SMB_FILE_ALLOCATION_INFORMATION:
5903                 case SMB_SET_FILE_ALLOCATION_INFO:
5904                 {
5905                         status = smb_set_file_allocation_info(conn,
5906                                                                 pdata,
5907                                                                 total_data,
5908                                                                 fsp,
5909                                                                 fname,
5910                                                                 &sbuf);
5911                         break;
5912                 }
5913
5914                 case SMB_FILE_END_OF_FILE_INFORMATION:
5915                 case SMB_SET_FILE_END_OF_FILE_INFO:
5916                 {
5917                         status = smb_set_file_end_of_file_info(conn,
5918                                                                 pdata,
5919                                                                 total_data,
5920                                                                 fsp,
5921                                                                 fname,
5922                                                                 &sbuf);
5923                         break;
5924                 }
5925
5926                 case SMB_FILE_DISPOSITION_INFORMATION:
5927                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5928                 {
5929 #if 0
5930                         /* JRA - We used to just ignore this on a path ? 
5931                          * Shouldn't this be invalid level on a pathname
5932                          * based call ?
5933                          */
5934                         if (tran_call != TRANSACT2_SETFILEINFO) {
5935                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5936                         }
5937 #endif
5938                         status = smb_set_file_disposition_info(conn,
5939                                                 pdata,
5940                                                 total_data,
5941                                                 fsp,
5942                                                 fname,
5943                                                 &sbuf);
5944                         break;
5945                 }
5946
5947                 case SMB_FILE_POSITION_INFORMATION:
5948                 {
5949                         status = smb_file_position_information(conn,
5950                                                 pdata,
5951                                                 total_data,
5952                                                 fsp);
5953                         break;
5954                 }
5955
5956                 /* From tridge Samba4 : 
5957                  * MODE_INFORMATION in setfileinfo (I have no
5958                  * idea what "mode information" on a file is - it takes a value of 0,
5959                  * 2, 4 or 6. What could it be?).
5960                  */
5961
5962                 case SMB_FILE_MODE_INFORMATION:
5963                 {
5964                         status = smb_file_mode_information(conn,
5965                                                 pdata,
5966                                                 total_data);
5967                         break;
5968                 }
5969
5970                 /*
5971                  * CIFS UNIX extensions.
5972                  */
5973
5974                 case SMB_SET_FILE_UNIX_BASIC:
5975                 {
5976                         status = smb_set_file_unix_basic(conn,
5977                                                         pdata,
5978                                                         total_data,
5979                                                         fsp,
5980                                                         fname,
5981                                                         &sbuf);
5982                         break;
5983                 }
5984
5985                 case SMB_SET_FILE_UNIX_INFO2:
5986                 {
5987                         status = smb_set_file_unix_info2(conn,
5988                                                         pdata,
5989                                                         total_data,
5990                                                         fsp,
5991                                                         fname,
5992                                                         &sbuf);
5993                         break;
5994                 }
5995
5996                 case SMB_SET_FILE_UNIX_LINK:
5997                 {
5998                         if (tran_call != TRANSACT2_SETPATHINFO) {
5999                                 /* We must have a pathname for this. */
6000                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6001                         }
6002                         status = smb_set_file_unix_link(conn,
6003                                                 inbuf,
6004                                                 pdata,
6005                                                 total_data,
6006                                                 fname);
6007                         break;
6008                 }
6009
6010                 case SMB_SET_FILE_UNIX_HLINK:
6011                 {
6012                         if (tran_call != TRANSACT2_SETPATHINFO) {
6013                                 /* We must have a pathname for this. */
6014                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6015                         }
6016                         status = smb_set_file_unix_hlink(conn,
6017                                                 inbuf,
6018                                                 outbuf,
6019                                                 pdata,
6020                                                 total_data,
6021                                                 fname);
6022                         break;
6023                 }
6024
6025                 case SMB_FILE_RENAME_INFORMATION:
6026                 {
6027                         status = smb_file_rename_information(conn,
6028                                                         inbuf,
6029                                                         outbuf,
6030                                                         pdata,
6031                                                         total_data,
6032                                                         fsp,
6033                                                         fname);
6034                         break;
6035                 }
6036
6037 #if defined(HAVE_POSIX_ACLS)
6038                 case SMB_SET_POSIX_ACL:
6039                 {
6040                         status = smb_set_posix_acl(conn,
6041                                                 pdata,
6042                                                 total_data,
6043                                                 fsp,
6044                                                 fname,
6045                                                 &sbuf);
6046                         break;
6047                 }
6048 #endif
6049
6050                 case SMB_SET_POSIX_LOCK:
6051                 {
6052                         if (tran_call != TRANSACT2_SETFILEINFO) {
6053                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6054                         }
6055                         status = smb_set_posix_lock(conn,
6056                                                 inbuf,
6057                                                 length,
6058                                                 pdata,
6059                                                 total_data,
6060                                                 fsp);
6061                         break;
6062                 }
6063
6064                 case SMB_POSIX_PATH_OPEN:
6065                 {
6066                         if (tran_call != TRANSACT2_SETPATHINFO) {
6067                                 /* We must have a pathname for this. */
6068                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6069                         }
6070
6071                         status = smb_posix_open(conn,
6072                                                 ppdata,
6073                                                 total_data,
6074                                                 fname,
6075                                                 &sbuf,
6076                                                 &data_return_size);
6077                         break;
6078                 }
6079
6080                 case SMB_POSIX_PATH_UNLINK:
6081                 {
6082                         if (tran_call != TRANSACT2_SETPATHINFO) {
6083                                 /* We must have a pathname for this. */
6084                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6085                         }
6086
6087                         status = smb_posix_unlink(conn,
6088                                                 pdata,
6089                                                 total_data,
6090                                                 fname,
6091                                                 &sbuf);
6092                         break;
6093                 }
6094
6095                 default:
6096                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6097         }
6098
6099         
6100         if (!NT_STATUS_IS_OK(status)) {
6101                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6102                         /* We have re-scheduled this call. */
6103                         return -1;
6104                 }
6105                 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6106                         /* We have re-scheduled this call. */
6107                         return -1;
6108                 }
6109                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6110                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6111                 }
6112                 return ERROR_NT(status);
6113         }
6114
6115         SSVAL(params,0,0);
6116         send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6117   
6118         return -1;
6119 }
6120
6121 /****************************************************************************
6122  Reply to a TRANS2_MKDIR (make directory with extended attributes).
6123 ****************************************************************************/
6124
6125 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6126                                         char **pparams, int total_params, char **ppdata, int total_data,
6127                                         unsigned int max_data_bytes)
6128 {
6129         char *params = *pparams;
6130         char *pdata = *ppdata;
6131         pstring directory;
6132         SMB_STRUCT_STAT sbuf;
6133         NTSTATUS status = NT_STATUS_OK;
6134         struct ea_list *ea_list = NULL;
6135
6136         if (!CAN_WRITE(conn))
6137                 return ERROR_DOS(ERRSRV,ERRaccess);
6138
6139         if (total_params < 5) {
6140                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6141         }
6142
6143         srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6144         if (!NT_STATUS_IS_OK(status)) {
6145                 return ERROR_NT(status);
6146         }
6147
6148         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6149
6150         status = unix_convert(conn, directory, False, NULL, &sbuf);
6151         if (!NT_STATUS_IS_OK(status)) {
6152                 return ERROR_NT(status);
6153         }
6154
6155         status = check_name(conn, directory);
6156         if (!NT_STATUS_IS_OK(status)) {
6157                 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6158                 return ERROR_NT(status);
6159         }
6160
6161         /* Any data in this call is an EA list. */
6162         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6163                 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6164         }
6165
6166         /*
6167          * OS/2 workplace shell seems to send SET_EA requests of "null"
6168          * length (4 bytes containing IVAL 4).
6169          * They seem to have no effect. Bug #3212. JRA.
6170          */
6171
6172         if (total_data != 4) {
6173                 if (total_data < 10) {
6174                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6175                 }
6176
6177                 if (IVAL(pdata,0) > total_data) {
6178                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6179                                 IVAL(pdata,0), (unsigned int)total_data));
6180                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6181                 }
6182
6183                 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6184                                        total_data - 4);
6185                 if (!ea_list) {
6186                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6187                 }
6188         } else if (IVAL(pdata,0) != 4) {
6189                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6190         }
6191
6192         status = create_directory(conn, directory);
6193
6194         if (!NT_STATUS_IS_OK(status)) {
6195                 return ERROR_NT(status);
6196         }
6197   
6198         /* Try and set any given EA. */
6199         if (ea_list) {
6200                 status = set_ea(conn, NULL, directory, ea_list);
6201                 if (!NT_STATUS_IS_OK(status)) {
6202                         return ERROR_NT(status);
6203                 }
6204         }
6205
6206         /* Realloc the parameter and data sizes */
6207         *pparams = (char *)SMB_REALLOC(*pparams,2);
6208         if(*pparams == NULL) {
6209                 return ERROR_NT(NT_STATUS_NO_MEMORY);
6210         }
6211         params = *pparams;
6212
6213         SSVAL(params,0,0);
6214
6215         send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6216   
6217         return(-1);
6218 }
6219
6220 /****************************************************************************
6221  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6222  We don't actually do this - we just send a null response.
6223 ****************************************************************************/
6224
6225 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6226                                         char **pparams, int total_params, char **ppdata, int total_data,
6227                                         unsigned int max_data_bytes)
6228 {
6229         static uint16 fnf_handle = 257;
6230         char *params = *pparams;
6231         uint16 info_level;
6232
6233         if (total_params < 6) {
6234                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6235         }
6236
6237         info_level = SVAL(params,4);
6238         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6239
6240         switch (info_level) {
6241                 case 1:
6242                 case 2:
6243                         break;
6244                 default:
6245                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6246         }
6247
6248         /* Realloc the parameter and data sizes */
6249         *pparams = (char *)SMB_REALLOC(*pparams,6);
6250         if (*pparams == NULL) {
6251                 return ERROR_NT(NT_STATUS_NO_MEMORY);
6252         }
6253         params = *pparams;
6254
6255         SSVAL(params,0,fnf_handle);
6256         SSVAL(params,2,0); /* No changes */
6257         SSVAL(params,4,0); /* No EA errors */
6258
6259         fnf_handle++;
6260
6261         if(fnf_handle == 0)
6262                 fnf_handle = 257;
6263
6264         send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6265   
6266         return(-1);
6267 }
6268
6269 /****************************************************************************
6270  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
6271  changes). Currently this does nothing.
6272 ****************************************************************************/
6273
6274 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6275                                         char **pparams, int total_params, char **ppdata, int total_data,
6276                                         unsigned int max_data_bytes)
6277 {
6278         char *params = *pparams;
6279
6280         DEBUG(3,("call_trans2findnotifynext\n"));
6281
6282         /* Realloc the parameter and data sizes */
6283         *pparams = (char *)SMB_REALLOC(*pparams,4);
6284         if (*pparams == NULL) {
6285                 return ERROR_NT(NT_STATUS_NO_MEMORY);
6286         }
6287         params = *pparams;
6288
6289         SSVAL(params,0,0); /* No changes */
6290         SSVAL(params,2,0); /* No EA errors */
6291
6292         send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6293   
6294         return(-1);
6295 }
6296
6297 /****************************************************************************
6298  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6299 ****************************************************************************/
6300
6301 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6302                                         char **pparams, int total_params, char **ppdata, int total_data,
6303                                         unsigned int max_data_bytes)
6304 {
6305         char *params = *pparams;
6306         pstring pathname;
6307         int reply_size = 0;
6308         int max_referral_level;
6309         NTSTATUS status = NT_STATUS_OK;
6310
6311         DEBUG(10,("call_trans2getdfsreferral\n"));
6312
6313         if (total_params < 3) {
6314                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6315         }
6316
6317         max_referral_level = SVAL(params,0);
6318
6319         if(!lp_host_msdfs())
6320                 return ERROR_DOS(ERRDOS,ERRbadfunc);
6321
6322         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6323         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6324                 return ERROR_NT(status);
6325     
6326         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6327         send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6328
6329         return(-1);
6330 }
6331
6332 #define LMCAT_SPL       0x53
6333 #define LMFUNC_GETJOBID 0x60
6334
6335 /****************************************************************************
6336  Reply to a TRANS2_IOCTL - used for OS/2 printing.
6337 ****************************************************************************/
6338
6339 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6340                                         char **pparams, int total_params, char **ppdata, int total_data,
6341                                         unsigned int max_data_bytes)
6342 {
6343         char *pdata = *ppdata;
6344         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6345
6346         /* check for an invalid fid before proceeding */
6347         
6348         if (!fsp)                                
6349                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
6350
6351         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6352                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6353                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6354                 if (*ppdata == NULL) {
6355                         return ERROR_NT(NT_STATUS_NO_MEMORY);
6356                 }
6357                 pdata = *ppdata;
6358
6359                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6360                         CAN ACCEPT THIS IN UNICODE. JRA. */
6361
6362                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
6363                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6364                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6365                 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6366                 return(-1);
6367         } else {
6368                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6369                 return ERROR_DOS(ERRSRV,ERRerror);
6370         }
6371 }
6372
6373 /****************************************************************************
6374  Reply to a SMBfindclose (stop trans2 directory search).
6375 ****************************************************************************/
6376
6377 int reply_findclose(connection_struct *conn,
6378                     char *inbuf,char *outbuf,int length,int bufsize)
6379 {
6380         int outsize = 0;
6381         int dptr_num=SVALS(inbuf,smb_vwv0);
6382         START_PROFILE(SMBfindclose);
6383
6384         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6385
6386         dptr_close(&dptr_num);
6387
6388         outsize = set_message(inbuf, outbuf,0,0,False);
6389
6390         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6391
6392         END_PROFILE(SMBfindclose);
6393         return(outsize);
6394 }
6395
6396 /****************************************************************************
6397  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6398 ****************************************************************************/
6399
6400 int reply_findnclose(connection_struct *conn, 
6401                      char *inbuf,char *outbuf,int length,int bufsize)
6402 {
6403         int outsize = 0;
6404         int dptr_num= -1;
6405         START_PROFILE(SMBfindnclose);
6406         
6407         dptr_num = SVAL(inbuf,smb_vwv0);
6408
6409         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6410
6411         /* We never give out valid handles for a 
6412            findnotifyfirst - so any dptr_num is ok here. 
6413            Just ignore it. */
6414
6415         outsize = set_message(inbuf, outbuf,0,0,False);
6416
6417         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6418
6419         END_PROFILE(SMBfindnclose);
6420         return(outsize);
6421 }
6422
6423 int handle_trans2(connection_struct *conn,
6424                   struct trans_state *state,
6425                   char *inbuf, char *outbuf, int size, int bufsize)
6426 {
6427         int outsize;
6428
6429         if (Protocol >= PROTOCOL_NT1) {
6430                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6431         }
6432
6433         /* Now we must call the relevant TRANS2 function */
6434         switch(state->call)  {
6435         case TRANSACT2_OPEN:
6436         {
6437                 START_PROFILE(Trans2_open);
6438                 outsize = call_trans2open(
6439                         conn, inbuf, outbuf, bufsize, 
6440                         &state->param, state->total_param,
6441                         &state->data, state->total_data,
6442                         state->max_data_return);
6443                 END_PROFILE(Trans2_open);
6444                 break;
6445         }
6446
6447         case TRANSACT2_FINDFIRST:
6448         {
6449                 START_PROFILE(Trans2_findfirst);
6450                 outsize = call_trans2findfirst(
6451                         conn, inbuf, outbuf, bufsize,
6452                         &state->param, state->total_param,
6453                         &state->data, state->total_data,
6454                         state->max_data_return);
6455                 END_PROFILE(Trans2_findfirst);
6456                 break;
6457         }
6458
6459         case TRANSACT2_FINDNEXT:
6460         {
6461                 START_PROFILE(Trans2_findnext);
6462                 outsize = call_trans2findnext(
6463                         conn, inbuf, outbuf, size, bufsize, 
6464                         &state->param, state->total_param,
6465                         &state->data, state->total_data,
6466                         state->max_data_return);
6467                 END_PROFILE(Trans2_findnext);
6468                 break;
6469         }
6470
6471         case TRANSACT2_QFSINFO:
6472         {
6473                 START_PROFILE(Trans2_qfsinfo);
6474                 outsize = call_trans2qfsinfo(
6475                         conn, inbuf, outbuf, size, bufsize,
6476                         &state->param, state->total_param,
6477                         &state->data, state->total_data,
6478                         state->max_data_return);
6479                 END_PROFILE(Trans2_qfsinfo);
6480             break;
6481         }
6482
6483         case TRANSACT2_SETFSINFO:
6484         {
6485                 START_PROFILE(Trans2_setfsinfo);
6486                 outsize = call_trans2setfsinfo(
6487                         conn, inbuf, outbuf, size, bufsize, 
6488                         &state->param, state->total_param,
6489                         &state->data, state->total_data,
6490                         state->max_data_return);
6491                 END_PROFILE(Trans2_setfsinfo);
6492                 break;
6493         }
6494
6495         case TRANSACT2_QPATHINFO:
6496         case TRANSACT2_QFILEINFO:
6497         {
6498                 START_PROFILE(Trans2_qpathinfo);
6499                 outsize = call_trans2qfilepathinfo(
6500                         conn, inbuf, outbuf, size, bufsize, state->call,
6501                         &state->param, state->total_param,
6502                         &state->data, state->total_data,
6503                         state->max_data_return);
6504                 END_PROFILE(Trans2_qpathinfo);
6505                 break;
6506         }
6507
6508         case TRANSACT2_SETPATHINFO:
6509         case TRANSACT2_SETFILEINFO:
6510         {
6511                 START_PROFILE(Trans2_setpathinfo);
6512                 outsize = call_trans2setfilepathinfo(
6513                         conn, inbuf, outbuf, size, bufsize, state->call,
6514                         &state->param, state->total_param,
6515                         &state->data, state->total_data,
6516                         state->max_data_return);
6517                 END_PROFILE(Trans2_setpathinfo);
6518                 break;
6519         }
6520
6521         case TRANSACT2_FINDNOTIFYFIRST:
6522         {
6523                 START_PROFILE(Trans2_findnotifyfirst);
6524                 outsize = call_trans2findnotifyfirst(
6525                         conn, inbuf, outbuf, size, bufsize, 
6526                         &state->param, state->total_param,
6527                         &state->data, state->total_data,
6528                         state->max_data_return);
6529                 END_PROFILE(Trans2_findnotifyfirst);
6530                 break;
6531         }
6532
6533         case TRANSACT2_FINDNOTIFYNEXT:
6534         {
6535                 START_PROFILE(Trans2_findnotifynext);
6536                 outsize = call_trans2findnotifynext(
6537                         conn, inbuf, outbuf, size, bufsize, 
6538                         &state->param, state->total_param,
6539                         &state->data, state->total_data,
6540                         state->max_data_return);
6541                 END_PROFILE(Trans2_findnotifynext);
6542                 break;
6543         }
6544
6545         case TRANSACT2_MKDIR:
6546         {
6547                 START_PROFILE(Trans2_mkdir);
6548                 outsize = call_trans2mkdir(
6549                         conn, inbuf, outbuf, size, bufsize,
6550                         &state->param, state->total_param,
6551                         &state->data, state->total_data,
6552                         state->max_data_return);
6553                 END_PROFILE(Trans2_mkdir);
6554                 break;
6555         }
6556
6557         case TRANSACT2_GET_DFS_REFERRAL:
6558         {
6559                 START_PROFILE(Trans2_get_dfs_referral);
6560                 outsize = call_trans2getdfsreferral(
6561                         conn, inbuf, outbuf, size, bufsize,
6562                         &state->param, state->total_param,
6563                         &state->data, state->total_data,
6564                         state->max_data_return);
6565                 END_PROFILE(Trans2_get_dfs_referral);
6566                 break;
6567         }
6568
6569         case TRANSACT2_IOCTL:
6570         {
6571                 START_PROFILE(Trans2_ioctl);
6572                 outsize = call_trans2ioctl(
6573                         conn, inbuf, outbuf, size, bufsize,
6574                         &state->param, state->total_param,
6575                         &state->data, state->total_data,
6576                         state->max_data_return);
6577                 END_PROFILE(Trans2_ioctl);
6578                 break;
6579         }
6580
6581         default:
6582                 /* Error in request */
6583                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6584                 outsize = ERROR_DOS(ERRSRV,ERRerror);
6585         }
6586
6587         return outsize;
6588 }
6589
6590 /****************************************************************************
6591  Reply to a SMBtrans2.
6592  ****************************************************************************/
6593
6594 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6595                  int size, int bufsize)
6596 {
6597         int outsize = 0;
6598         unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6599         unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6600         unsigned int psoff = SVAL(inbuf, smb_psoff);
6601         unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6602         unsigned int tran_call = SVAL(inbuf, smb_setup0);
6603         struct trans_state *state;
6604         NTSTATUS result;
6605
6606         START_PROFILE(SMBtrans2);
6607
6608         result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6609         if (!NT_STATUS_IS_OK(result)) {
6610                 DEBUG(2, ("Got invalid trans2 request: %s\n",
6611                           nt_errstr(result)));
6612                 END_PROFILE(SMBtrans2);
6613                 return ERROR_NT(result);
6614         }
6615
6616         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6617             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
6618             && (tran_call != TRANSACT2_QFILEINFO)) {
6619                 END_PROFILE(SMBtrans2);
6620                 return ERROR_DOS(ERRSRV,ERRaccess);
6621         }
6622
6623         if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6624                 DEBUG(0, ("talloc failed\n"));
6625                 END_PROFILE(SMBtrans2);
6626                 return ERROR_NT(NT_STATUS_NO_MEMORY);
6627         }
6628
6629         state->cmd = SMBtrans2;
6630
6631         state->mid = SVAL(inbuf, smb_mid);
6632         state->vuid = SVAL(inbuf, smb_uid);
6633         state->setup_count = SVAL(inbuf, smb_suwcnt);
6634         state->setup = NULL;
6635         state->total_param = SVAL(inbuf, smb_tpscnt);
6636         state->param = NULL;
6637         state->total_data =  SVAL(inbuf, smb_tdscnt);
6638         state->data = NULL;
6639         state->max_param_return = SVAL(inbuf, smb_mprcnt);
6640         state->max_data_return  = SVAL(inbuf, smb_mdrcnt);
6641         state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6642         state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6643         state->one_way = BITSETW(inbuf+smb_vwv5,1);
6644
6645         state->call = tran_call;
6646
6647         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6648            is so as a sanity check */
6649         if (state->setup_count != 1) {
6650                 /*
6651                  * Need to have rc=0 for ioctl to get job id for OS/2.
6652                  *  Network printing will fail if function is not successful.
6653                  *  Similar function in reply.c will be used if protocol
6654                  *  is LANMAN1.0 instead of LM1.2X002.
6655                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
6656                  *  outbuf doesn't have to be set(only job id is used).
6657                  */
6658                 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6659                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6660                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6661                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6662                 } else {
6663                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6664                         DEBUG(2,("Transaction is %d\n",tran_call));
6665                         TALLOC_FREE(state);
6666                         END_PROFILE(SMBtrans2);
6667                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6668                 }
6669         }
6670
6671         if ((dscnt > state->total_data) || (pscnt > state->total_param))
6672                 goto bad_param;
6673
6674         if (state->total_data) {
6675                 /* Can't use talloc here, the core routines do realloc on the
6676                  * params and data. */
6677                 state->data = (char *)SMB_MALLOC(state->total_data);
6678                 if (state->data == NULL) {
6679                         DEBUG(0,("reply_trans2: data malloc fail for %u "
6680                                  "bytes !\n", (unsigned int)state->total_data));
6681                         TALLOC_FREE(state);
6682                         END_PROFILE(SMBtrans2);
6683                         return(ERROR_DOS(ERRDOS,ERRnomem));
6684                 }
6685                 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6686                         goto bad_param;
6687                 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6688                     (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6689                         goto bad_param;
6690
6691                 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6692         }
6693
6694         if (state->total_param) {
6695                 /* Can't use talloc here, the core routines do realloc on the
6696                  * params and data. */
6697                 state->param = (char *)SMB_MALLOC(state->total_param);
6698                 if (state->param == NULL) {
6699                         DEBUG(0,("reply_trans: param malloc fail for %u "
6700                                  "bytes !\n", (unsigned int)state->total_param));
6701                         SAFE_FREE(state->data);
6702                         TALLOC_FREE(state);
6703                         END_PROFILE(SMBtrans2);
6704                         return(ERROR_DOS(ERRDOS,ERRnomem));
6705                 } 
6706                 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6707                         goto bad_param;
6708                 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6709                     (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6710                         goto bad_param;
6711
6712                 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6713         }
6714
6715         state->received_data  = dscnt;
6716         state->received_param = pscnt;
6717
6718         if ((state->received_param == state->total_param) &&
6719             (state->received_data == state->total_data)) {
6720
6721                 outsize = handle_trans2(conn, state, inbuf, outbuf,
6722                                         size, bufsize);
6723                 SAFE_FREE(state->data);
6724                 SAFE_FREE(state->param);
6725                 TALLOC_FREE(state);
6726                 END_PROFILE(SMBtrans2);
6727                 return outsize;
6728         }
6729
6730         DLIST_ADD(conn->pending_trans, state);
6731
6732         /* We need to send an interim response then receive the rest
6733            of the parameter/data bytes */
6734         outsize = set_message(inbuf, outbuf,0,0,False);
6735         show_msg(outbuf);
6736         END_PROFILE(SMBtrans2);
6737         return outsize;
6738
6739   bad_param:
6740
6741         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6742         SAFE_FREE(state->data);
6743         SAFE_FREE(state->param);
6744         TALLOC_FREE(state);
6745         END_PROFILE(SMBtrans2);
6746         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6747 }
6748
6749
6750 /****************************************************************************
6751  Reply to a SMBtranss2
6752  ****************************************************************************/
6753
6754 int reply_transs2(connection_struct *conn,
6755                   char *inbuf,char *outbuf,int size,int bufsize)
6756 {
6757         int outsize = 0;
6758         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6759         struct trans_state *state;
6760
6761         START_PROFILE(SMBtranss2);
6762
6763         show_msg(inbuf);
6764
6765         for (state = conn->pending_trans; state != NULL;
6766              state = state->next) {
6767                 if (state->mid == SVAL(inbuf,smb_mid)) {
6768                         break;
6769                 }
6770         }
6771
6772         if ((state == NULL) || (state->cmd != SMBtrans2)) {
6773                 END_PROFILE(SMBtranss2);
6774                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6775         }
6776
6777         /* Revise state->total_param and state->total_data in case they have
6778            changed downwards */
6779
6780         if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6781                 state->total_param = SVAL(inbuf, smb_tpscnt);
6782         if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6783                 state->total_data = SVAL(inbuf, smb_tdscnt);
6784
6785         pcnt = SVAL(inbuf, smb_spscnt);
6786         poff = SVAL(inbuf, smb_spsoff);
6787         pdisp = SVAL(inbuf, smb_spsdisp);
6788
6789         dcnt = SVAL(inbuf, smb_sdscnt);
6790         doff = SVAL(inbuf, smb_sdsoff);
6791         ddisp = SVAL(inbuf, smb_sdsdisp);
6792
6793         state->received_param += pcnt;
6794         state->received_data += dcnt;
6795                 
6796         if ((state->received_data > state->total_data) ||
6797             (state->received_param > state->total_param))
6798                 goto bad_param;
6799
6800         if (pcnt) {
6801                 if (pdisp+pcnt > state->total_param)
6802                         goto bad_param;
6803                 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6804                         goto bad_param;
6805                 if (pdisp > state->total_param)
6806                         goto bad_param;
6807                 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6808                     (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6809                         goto bad_param;
6810                 if (state->param + pdisp < state->param)
6811                         goto bad_param;
6812
6813                 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6814                        pcnt);
6815         }
6816
6817         if (dcnt) {
6818                 if (ddisp+dcnt > state->total_data)
6819                         goto bad_param;
6820                 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6821                         goto bad_param;
6822                 if (ddisp > state->total_data)
6823                         goto bad_param;
6824                 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6825                     (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6826                         goto bad_param;
6827                 if (state->data + ddisp < state->data)
6828                         goto bad_param;
6829
6830                 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6831                        dcnt);      
6832         }
6833
6834         if ((state->received_param < state->total_param) ||
6835             (state->received_data < state->total_data)) {
6836                 END_PROFILE(SMBtranss2);
6837                 return -1;
6838         }
6839
6840         /* construct_reply_common has done us the favor to pre-fill the
6841          * command field with SMBtranss2 which is wrong :-)
6842          */
6843         SCVAL(outbuf,smb_com,SMBtrans2);
6844
6845         outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6846
6847         DLIST_REMOVE(conn->pending_trans, state);
6848         SAFE_FREE(state->data);
6849         SAFE_FREE(state->param);
6850         TALLOC_FREE(state);
6851
6852         if (outsize == 0) {
6853                 END_PROFILE(SMBtranss2);
6854                 return(ERROR_DOS(ERRSRV,ERRnosupport));
6855         }
6856         
6857         END_PROFILE(SMBtranss2);
6858         return(outsize);
6859
6860   bad_param:
6861
6862         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6863         DLIST_REMOVE(conn->pending_trans, state);
6864         SAFE_FREE(state->data);
6865         SAFE_FREE(state->param);
6866         TALLOC_FREE(state);
6867         END_PROFILE(SMBtranss2);
6868         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6869 }