r23106: Use lchown for symlinks.
[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                                         /* Ensure we don't do this on signed or sealed data. */
2561                                         (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2562                                         )));
2563                         break;
2564
2565                 case SMB_QUERY_POSIX_FS_INFO:
2566                 {
2567                         int rc;
2568                         vfs_statvfs_struct svfs;
2569
2570                         if (!lp_unix_extensions()) {
2571                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2572                         }
2573
2574                         rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2575
2576                         if (!rc) {
2577                                 data_len = 56;
2578                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
2579                                 SIVAL(pdata,4,svfs.BlockSize);
2580                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2581                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2582                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2583                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2584                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2585                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2586                                 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2587 #ifdef EOPNOTSUPP
2588                         } else if (rc == EOPNOTSUPP) {
2589                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2590 #endif /* EOPNOTSUPP */
2591                         } else {
2592                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2593                                 return ERROR_DOS(ERRSRV,ERRerror);
2594                         }
2595                         break;
2596                 }
2597
2598                 case SMB_QUERY_POSIX_WHOAMI:
2599                 {
2600                         uint32_t flags = 0;
2601                         uint32_t sid_bytes;
2602                         int i;
2603
2604                         if (!lp_unix_extensions()) {
2605                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2606                         }
2607
2608                         if (max_data_bytes < 40) {
2609                                 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2610                         }
2611
2612                         /* We ARE guest if global_sid_Builtin_Guests is
2613                          * in our list of SIDs.
2614                          */
2615                         if (nt_token_check_sid(&global_sid_Builtin_Guests,
2616                                     current_user.nt_user_token)) {
2617                                 flags |= SMB_WHOAMI_GUEST;
2618                         }
2619
2620                         /* We are NOT guest if global_sid_Authenticated_Users
2621                          * is in our list of SIDs.
2622                          */
2623                         if (nt_token_check_sid(&global_sid_Authenticated_Users,
2624                                     current_user.nt_user_token)) {
2625                                 flags &= ~SMB_WHOAMI_GUEST;
2626                         }
2627
2628                         /* NOTE: 8 bytes for UID/GID, irrespective of native
2629                          * platform size. This matches
2630                          * SMB_QUERY_FILE_UNIX_BASIC and friends.
2631                          */
2632                         data_len = 4 /* flags */
2633                             + 4 /* flag mask */
2634                             + 8 /* uid */
2635                             + 8 /* gid */
2636                             + 4 /* ngroups */
2637                             + 4 /* num_sids */
2638                             + 4 /* SID bytes */
2639                             + 4 /* pad/reserved */
2640                             + (current_user.ut.ngroups * 8)
2641                                 /* groups list */
2642                             + (current_user.nt_user_token->num_sids *
2643                                     SID_MAX_SIZE)
2644                                 /* SID list */;
2645
2646                         SIVAL(pdata, 0, flags);
2647                         SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2648                         SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2649                         SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2650
2651
2652                         if (data_len >= max_data_bytes) {
2653                                 /* Potential overflow, skip the GIDs and SIDs. */
2654
2655                                 SIVAL(pdata, 24, 0); /* num_groups */
2656                                 SIVAL(pdata, 28, 0); /* num_sids */
2657                                 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2658                                 SIVAL(pdata, 36, 0); /* reserved */
2659
2660                                 data_len = 40;
2661                                 break;
2662                         }
2663
2664                         SIVAL(pdata, 24, current_user.ut.ngroups);
2665                         SIVAL(pdata, 28,
2666                                 current_user.nt_user_token->num_sids);
2667
2668                         /* We walk the SID list twice, but this call is fairly
2669                          * infrequent, and I don't expect that it's performance
2670                          * sensitive -- jpeach
2671                          */
2672                         for (i = 0, sid_bytes = 0;
2673                             i < current_user.nt_user_token->num_sids; ++i) {
2674                                 sid_bytes +=
2675                                     sid_size(&current_user.nt_user_token->user_sids[i]);
2676                         }
2677
2678                         /* SID list byte count */
2679                         SIVAL(pdata, 32, sid_bytes);
2680
2681                         /* 4 bytes pad/reserved - must be zero */
2682                         SIVAL(pdata, 36, 0);
2683                         data_len = 40;
2684
2685                         /* GID list */
2686                         for (i = 0; i < current_user.ut.ngroups; ++i) {
2687                                 SBIG_UINT(pdata, data_len,
2688                                         (SMB_BIG_UINT)current_user.ut.groups[i]);
2689                                 data_len += 8;
2690                         }
2691
2692                         /* SID list */
2693                         for (i = 0;
2694                             i < current_user.nt_user_token->num_sids; ++i) {
2695                                 int sid_len =
2696                                     sid_size(&current_user.nt_user_token->user_sids[i]);
2697
2698                                 sid_linearize(pdata + data_len, sid_len,
2699                                     &current_user.nt_user_token->user_sids[i]);
2700                                 data_len += sid_len;
2701                         }
2702
2703                         break;
2704                 }
2705
2706                 case SMB_MAC_QUERY_FS_INFO:
2707                         /*
2708                          * Thursby MAC extension... ONLY on NTFS filesystems
2709                          * once we do streams then we don't need this
2710                          */
2711                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2712                                 data_len = 88;
2713                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2714                                 break;
2715                         }
2716                         /* drop through */
2717                 default:
2718                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2719         }
2720
2721
2722         send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2723
2724         DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2725
2726         return -1;
2727 }
2728
2729 /****************************************************************************
2730  Reply to a TRANS2_SETFSINFO (set filesystem info).
2731 ****************************************************************************/
2732
2733 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2734                                         char **pparams, int total_params, char **ppdata, int total_data,
2735                                         unsigned int max_data_bytes)
2736 {
2737         char *pdata = *ppdata;
2738         char *params = *pparams;
2739         uint16 info_level;
2740         int outsize;
2741
2742         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2743
2744         /*  */
2745         if (total_params < 4) {
2746                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2747                         total_params));
2748                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2749         }
2750
2751         info_level = SVAL(params,2);
2752
2753         switch(info_level) {
2754                 case SMB_SET_CIFS_UNIX_INFO:
2755                         {
2756                                 uint16 client_unix_major;
2757                                 uint16 client_unix_minor;
2758                                 uint32 client_unix_cap_low;
2759                                 uint32 client_unix_cap_high;
2760
2761                                 if (!lp_unix_extensions()) {
2762                                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2763                                 }
2764
2765                                 /* There should be 12 bytes of capabilities set. */
2766                                 if (total_data < 8) {
2767                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2768                                 }
2769                                 client_unix_major = SVAL(pdata,0);
2770                                 client_unix_minor = SVAL(pdata,2);
2771                                 client_unix_cap_low = IVAL(pdata,4);
2772                                 client_unix_cap_high = IVAL(pdata,8);
2773                                 /* Just print these values for now. */
2774                                 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2775 cap_low = 0x%x, cap_high = 0x%x\n",
2776                                         (unsigned int)client_unix_major,
2777                                         (unsigned int)client_unix_minor,
2778                                         (unsigned int)client_unix_cap_low,
2779                                         (unsigned int)client_unix_cap_high ));
2780
2781                                 /* Here is where we must switch to posix pathname processing... */
2782                                 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2783                                         lp_set_posix_pathnames();
2784                                         mangle_change_to_posix();
2785                                 }
2786
2787                                 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2788                                     !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2789                                         /* Client that knows how to do posix locks,
2790                                          * but not posix open/mkdir operations. Set a
2791                                          * default type for read/write checks. */
2792
2793                                         lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2794
2795                                 }
2796                                 break;
2797                         }
2798                 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2799                         {
2800                                 NTSTATUS status;
2801                                 size_t param_len = 0;
2802                                 size_t data_len = total_data;
2803
2804                                 if (!lp_unix_extensions()) {
2805                                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2806                                 }
2807
2808                                 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2809
2810                                 status = srv_request_encryption_setup(conn,
2811                                                                         (unsigned char **)ppdata,
2812                                                                         &data_len,
2813                                                                         (unsigned char **)pparams,
2814                                                                         &param_len
2815                                                                         );
2816
2817                                 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2818                                         error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2819                                 } else if (!NT_STATUS_IS_OK(status)) {
2820                                         return ERROR_NT(status);
2821                                 }
2822
2823                                 send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2824
2825                                 if (NT_STATUS_IS_OK(status)) {
2826                                         /* Server-side transport encryption is now *on*. */
2827                                         status = srv_encryption_start(conn);
2828                                         if (!NT_STATUS_IS_OK(status)) {
2829                                                 exit_server_cleanly("Failure in setting up encrypted transport");
2830                                         }
2831                                 }
2832                                 return -1;
2833                         }
2834                 case SMB_FS_QUOTA_INFORMATION:
2835                         {
2836                                 files_struct *fsp = NULL;
2837                                 SMB_NTQUOTA_STRUCT quotas;
2838         
2839                                 ZERO_STRUCT(quotas);
2840
2841                                 /* access check */
2842                                 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2843                                         DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2844                                                 lp_servicename(SNUM(conn)),conn->user));
2845                                         return ERROR_DOS(ERRSRV,ERRaccess);
2846                                 }
2847
2848                                 /* note: normaly there're 48 bytes,
2849                                  * but we didn't use the last 6 bytes for now 
2850                                  * --metze 
2851                                  */
2852                                 fsp = file_fsp(params,0);
2853                                 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2854                                         DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2855                                         return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2856                                 }
2857
2858                                 if (total_data < 42) {
2859                                         DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2860                                                 total_data));
2861                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2862                                 }
2863                         
2864                                 /* unknown_1 24 NULL bytes in pdata*/
2865                 
2866                                 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2867                                 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2868 #ifdef LARGE_SMB_OFF_T
2869                                 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2870 #else /* LARGE_SMB_OFF_T */
2871                                 if ((IVAL(pdata,28) != 0)&&
2872                                         ((quotas.softlim != 0xFFFFFFFF)||
2873                                         (IVAL(pdata,28)!=0xFFFFFFFF))) {
2874                                         /* more than 32 bits? */
2875                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2876                                 }
2877 #endif /* LARGE_SMB_OFF_T */
2878                 
2879                                 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2880                                 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2881 #ifdef LARGE_SMB_OFF_T
2882                                 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2883 #else /* LARGE_SMB_OFF_T */
2884                                 if ((IVAL(pdata,36) != 0)&&
2885                                         ((quotas.hardlim != 0xFFFFFFFF)||
2886                                         (IVAL(pdata,36)!=0xFFFFFFFF))) {
2887                                         /* more than 32 bits? */
2888                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2889                                 }
2890 #endif /* LARGE_SMB_OFF_T */
2891                 
2892                                 /* quota_flags 2 bytes **/
2893                                 quotas.qflags = SVAL(pdata,40);
2894                 
2895                                 /* unknown_2 6 NULL bytes follow*/
2896                 
2897                                 /* now set the quotas */
2898                                 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2899                                         DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2900                                         return ERROR_DOS(ERRSRV,ERRerror);
2901                                 }
2902                         
2903                                 break;
2904                         }
2905                 default:
2906                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2907                                 info_level));
2908                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2909                         break;
2910         }
2911
2912         /* 
2913          * sending this reply works fine, 
2914          * but I'm not sure it's the same 
2915          * like windows do...
2916          * --metze
2917          */ 
2918         outsize = set_message(inbuf, outbuf,10,0,True);
2919
2920         return outsize;
2921 }
2922
2923 #if defined(HAVE_POSIX_ACLS)
2924 /****************************************************************************
2925  Utility function to count the number of entries in a POSIX acl.
2926 ****************************************************************************/
2927
2928 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2929 {
2930         unsigned int ace_count = 0;
2931         int entry_id = SMB_ACL_FIRST_ENTRY;
2932         SMB_ACL_ENTRY_T entry;
2933
2934         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2935                 /* get_next... */
2936                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2937                         entry_id = SMB_ACL_NEXT_ENTRY;
2938                 }
2939                 ace_count++;
2940         }
2941         return ace_count;
2942 }
2943
2944 /****************************************************************************
2945  Utility function to marshall a POSIX acl into wire format.
2946 ****************************************************************************/
2947
2948 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2949 {
2950         int entry_id = SMB_ACL_FIRST_ENTRY;
2951         SMB_ACL_ENTRY_T entry;
2952
2953         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2954                 SMB_ACL_TAG_T tagtype;
2955                 SMB_ACL_PERMSET_T permset;
2956                 unsigned char perms = 0;
2957                 unsigned int own_grp;
2958
2959                 /* get_next... */
2960                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2961                         entry_id = SMB_ACL_NEXT_ENTRY;
2962                 }
2963
2964                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2965                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2966                         return False;
2967                 }
2968
2969                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2970                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2971                         return False;
2972                 }
2973
2974                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2975                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2976                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2977
2978                 SCVAL(pdata,1,perms);
2979
2980                 switch (tagtype) {
2981                         case SMB_ACL_USER_OBJ:
2982                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2983                                 own_grp = (unsigned int)pst->st_uid;
2984                                 SIVAL(pdata,2,own_grp);
2985                                 SIVAL(pdata,6,0);
2986                                 break;
2987                         case SMB_ACL_USER:
2988                                 {
2989                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2990                                         if (!puid) {
2991                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2992                                         }
2993                                         own_grp = (unsigned int)*puid;
2994                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2995                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2996                                         SIVAL(pdata,2,own_grp);
2997                                         SIVAL(pdata,6,0);
2998                                         break;
2999                                 }
3000                         case SMB_ACL_GROUP_OBJ:
3001                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3002                                 own_grp = (unsigned int)pst->st_gid;
3003                                 SIVAL(pdata,2,own_grp);
3004                                 SIVAL(pdata,6,0);
3005                                 break;
3006                         case SMB_ACL_GROUP:
3007                                 {
3008                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3009                                         if (!pgid) {
3010                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3011                                         }
3012                                         own_grp = (unsigned int)*pgid;
3013                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3014                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3015                                         SIVAL(pdata,2,own_grp);
3016                                         SIVAL(pdata,6,0);
3017                                         break;
3018                                 }
3019                         case SMB_ACL_MASK:
3020                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3021                                 SIVAL(pdata,2,0xFFFFFFFF);
3022                                 SIVAL(pdata,6,0xFFFFFFFF);
3023                                 break;
3024                         case SMB_ACL_OTHER:
3025                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3026                                 SIVAL(pdata,2,0xFFFFFFFF);
3027                                 SIVAL(pdata,6,0xFFFFFFFF);
3028                                 break;
3029                         default:
3030                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3031                                 return False;
3032                 }
3033                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3034         }
3035
3036         return True;
3037 }
3038 #endif
3039
3040 /****************************************************************************
3041  Store the FILE_UNIX_BASIC info.
3042 ****************************************************************************/
3043
3044 static char *store_file_unix_basic(connection_struct *conn,
3045                                 char *pdata,
3046                                 files_struct *fsp,
3047                                 const SMB_STRUCT_STAT *psbuf)
3048 {
3049         DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3050         DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3051
3052         SOFF_T(pdata,0,get_file_size(*psbuf));             /* File size 64 Bit */
3053         pdata += 8;
3054
3055         SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3056         pdata += 8;
3057
3058         put_long_date_timespec(pdata,get_ctimespec(psbuf));       /* Change Time 64 Bit */
3059         put_long_date_timespec(pdata+8,get_atimespec(psbuf));     /* Last access time 64 Bit */
3060         put_long_date_timespec(pdata+16,get_mtimespec(psbuf));    /* Last modification time 64 Bit */
3061         pdata += 24;
3062
3063         SIVAL(pdata,0,psbuf->st_uid);               /* user id for the owner */
3064         SIVAL(pdata,4,0);
3065         pdata += 8;
3066
3067         SIVAL(pdata,0,psbuf->st_gid);               /* group id of owner */
3068         SIVAL(pdata,4,0);
3069         pdata += 8;
3070
3071         SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3072         pdata += 4;
3073
3074         SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev));   /* Major device number if type is device */
3075         SIVAL(pdata,4,0);
3076         pdata += 8;
3077
3078         SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev));   /* Minor device number if type is device */
3079         SIVAL(pdata,4,0);
3080         pdata += 8;
3081
3082         SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino);   /* inode number */
3083         pdata += 8;
3084                                 
3085         SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode));     /* Standard UNIX file permissions */
3086         SIVAL(pdata,4,0);
3087         pdata += 8;
3088
3089         SIVAL(pdata,0,psbuf->st_nlink);             /* number of hard links */
3090         SIVAL(pdata,4,0);
3091         pdata += 8;
3092
3093         return pdata;
3094 }
3095
3096 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3097  * the chflags(2) (or equivalent) flags.
3098  *
3099  * XXX: this really should be behind the VFS interface. To do this, we would
3100  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3101  * Each VFS module could then implement it's own mapping as appropriate for the
3102  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3103  */
3104 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3105         info2_flags_map[] =
3106 {
3107 #ifdef UF_NODUMP
3108     { UF_NODUMP, EXT_DO_NOT_BACKUP },
3109 #endif
3110
3111 #ifdef UF_IMMUTABLE
3112     { UF_IMMUTABLE, EXT_IMMUTABLE },
3113 #endif
3114
3115 #ifdef UF_APPEND
3116     { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3117 #endif
3118
3119 #ifdef UF_HIDDEN
3120     { UF_HIDDEN, EXT_HIDDEN },
3121 #endif
3122
3123     /* Do not remove. We need to guarantee that this array has at least one
3124      * entry to build on HP-UX.
3125      */
3126     { 0, 0 }
3127
3128 };
3129
3130 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3131                                 uint32 *smb_fflags, uint32 *smb_fmask)
3132 {
3133 #ifdef HAVE_STAT_ST_FLAGS
3134         int i;
3135
3136         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3137             *smb_fmask |= info2_flags_map[i].smb_fflag;
3138             if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3139                     *smb_fflags |= info2_flags_map[i].smb_fflag;
3140             }
3141         }
3142 #endif /* HAVE_STAT_ST_FLAGS */
3143 }
3144
3145 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3146                                 const uint32 smb_fflags,
3147                                 const uint32 smb_fmask,
3148                                 int *stat_fflags)
3149 {
3150 #ifdef HAVE_STAT_ST_FLAGS
3151         uint32 max_fmask = 0;
3152         int i;
3153
3154         *stat_fflags = psbuf->st_flags;
3155
3156         /* For each flags requested in smb_fmask, check the state of the
3157          * corresponding flag in smb_fflags and set or clear the matching
3158          * stat flag.
3159          */
3160
3161         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3162             max_fmask |= info2_flags_map[i].smb_fflag;
3163             if (smb_fmask & info2_flags_map[i].smb_fflag) {
3164                     if (smb_fflags & info2_flags_map[i].smb_fflag) {
3165                             *stat_fflags |= info2_flags_map[i].stat_fflag;
3166                     } else {
3167                             *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3168                     }
3169             }
3170         }
3171
3172         /* If smb_fmask is asking to set any bits that are not supported by
3173          * our flag mappings, we should fail.
3174          */
3175         if ((smb_fmask & max_fmask) != smb_fmask) {
3176                 return False;
3177         }
3178
3179         return True;
3180 #else
3181         return False;
3182 #endif /* HAVE_STAT_ST_FLAGS */
3183 }
3184
3185
3186 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3187  * of file flags and birth (create) time.
3188  */
3189 static char *store_file_unix_basic_info2(connection_struct *conn,
3190                                 char *pdata,
3191                                 files_struct *fsp,
3192                                 const SMB_STRUCT_STAT *psbuf)
3193 {
3194         uint32 file_flags = 0;
3195         uint32 flags_mask = 0;
3196
3197         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3198
3199         /* Create (birth) time 64 bit */
3200         put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3201         pdata += 8;
3202
3203         map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3204         SIVAL(pdata, 0, file_flags); /* flags */
3205         SIVAL(pdata, 4, flags_mask); /* mask */
3206         pdata += 8;
3207
3208         return pdata;
3209 }
3210
3211 /****************************************************************************
3212  Reply to a TRANSACT2_QFILEINFO on a PIPE !
3213 ****************************************************************************/
3214
3215 static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3216                                         unsigned int tran_call,
3217                                         char **pparams, int total_params, char **ppdata, int total_data,
3218                                         unsigned int max_data_bytes)
3219 {
3220         char *params = *pparams;
3221         char *pdata = *ppdata;
3222         unsigned int data_size = 0;
3223         unsigned int param_size = 2;
3224         uint16 info_level;
3225         smb_np_struct *p_pipe = NULL;
3226
3227         if (!params) {
3228                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3229         }
3230
3231         if (total_params < 4) {
3232                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3233         }
3234
3235         p_pipe = get_rpc_pipe_p(params,0);
3236         if (p_pipe == NULL) {
3237                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3238         }
3239
3240         info_level = SVAL(params,2);
3241
3242         *pparams = (char *)SMB_REALLOC(*pparams,2);
3243         if (*pparams == NULL) {
3244                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3245         }
3246         params = *pparams;
3247         SSVAL(params,0,0);
3248         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3249         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3250         if (*ppdata == NULL ) {
3251                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3252         }
3253         pdata = *ppdata;
3254
3255         switch (info_level) {
3256                 case SMB_FILE_STANDARD_INFORMATION:
3257                         memset(pdata,24,0);
3258                         SOFF_T(pdata,0,4096LL);
3259                         SIVAL(pdata,16,1);
3260                         SIVAL(pdata,20,1);
3261                         data_size = 24;
3262                         break;
3263
3264                 default:
3265                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3266         }
3267
3268         send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3269
3270         return(-1);
3271 }
3272
3273 /****************************************************************************
3274  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3275  file name or file id).
3276 ****************************************************************************/
3277
3278 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3279                                         unsigned int tran_call,
3280                                         char **pparams, int total_params, char **ppdata, int total_data,
3281                                         unsigned int max_data_bytes)
3282 {
3283         char *params = *pparams;
3284         char *pdata = *ppdata;
3285         uint16 info_level;
3286         int mode=0;
3287         int nlink;
3288         SMB_OFF_T file_size=0;
3289         SMB_BIG_UINT allocation_size=0;
3290         unsigned int data_size = 0;
3291         unsigned int param_size = 2;
3292         SMB_STRUCT_STAT sbuf;
3293         pstring fname, dos_fname;
3294         char *fullpathname;
3295         char *base_name;
3296         char *p;
3297         SMB_OFF_T pos = 0;
3298         BOOL delete_pending = False;
3299         int len;
3300         time_t create_time, mtime, atime;
3301         struct timespec create_time_ts, mtime_ts, atime_ts;
3302         files_struct *fsp = NULL;
3303         TALLOC_CTX *data_ctx = NULL;
3304         struct ea_list *ea_list = NULL;
3305         uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3306         char *lock_data = NULL;
3307
3308         if (!params)
3309                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3310
3311         ZERO_STRUCT(sbuf);
3312
3313         if (tran_call == TRANSACT2_QFILEINFO) {
3314                 if (total_params < 4) {
3315                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3316                 }
3317
3318                 if (IS_IPC(conn)) {
3319                         return call_trans2qpipeinfo(conn,
3320                                                         inbuf,
3321                                                         outbuf,
3322                                                         length,
3323                                                         bufsize,
3324                                                         tran_call,
3325                                                         pparams,
3326                                                         total_params,
3327                                                         ppdata,
3328                                                         total_data,
3329                                                         max_data_bytes);
3330                 }
3331
3332                 fsp = file_fsp(params,0);
3333                 info_level = SVAL(params,2);
3334
3335                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3336
3337                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3338                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3339                 }
3340
3341                 if(fsp && (fsp->fake_file_handle)) {
3342                         /*
3343                          * This is actually for the QUOTA_FAKE_FILE --metze
3344                          */
3345                                                 
3346                         pstrcpy(fname, fsp->fsp_name);
3347                         /* We know this name is ok, it's already passed the checks. */
3348                         
3349                 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3350                         /*
3351                          * This is actually a QFILEINFO on a directory
3352                          * handle (returned from an NT SMB). NT5.0 seems
3353                          * to do this call. JRA.
3354                          */
3355                         /* We know this name is ok, it's already passed the checks. */
3356                         pstrcpy(fname, fsp->fsp_name);
3357                   
3358                         if (INFO_LEVEL_IS_UNIX(info_level)) {
3359                                 /* Always do lstat for UNIX calls. */
3360                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3361                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3362                                         return UNIXERROR(ERRDOS,ERRbadpath);
3363                                 }
3364                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3365                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3366                                 return UNIXERROR(ERRDOS,ERRbadpath);
3367                         }
3368
3369                         delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3370                 } else {
3371                         /*
3372                          * Original code - this is an open file.
3373                          */
3374                         CHECK_FSP(fsp,conn);
3375
3376                         pstrcpy(fname, fsp->fsp_name);
3377                         if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3378                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3379                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3380                         }
3381                         pos = fsp->fh->position_information;
3382                         delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3383                         access_mask = fsp->access_mask;
3384                 }
3385         } else {
3386                 NTSTATUS status = NT_STATUS_OK;
3387
3388                 /* qpathinfo */
3389                 if (total_params < 7) {
3390                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3391                 }
3392
3393                 info_level = SVAL(params,0);
3394
3395                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3396
3397                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3398                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3399                 }
3400
3401                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
3402                 if (!NT_STATUS_IS_OK(status)) {
3403                         return ERROR_NT(status);
3404                 }
3405
3406                 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3407                 if (!NT_STATUS_IS_OK(status)) {
3408                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3409                                 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3410                         }
3411                         return ERROR_NT(status);
3412                 }
3413
3414                 status = unix_convert(conn, fname, False, NULL, &sbuf);
3415                 if (!NT_STATUS_IS_OK(status)) {
3416                         return ERROR_NT(status);
3417                 }
3418                 status = check_name(conn, fname);
3419                 if (!NT_STATUS_IS_OK(status)) {
3420                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3421                         return ERROR_NT(status);
3422                 }
3423
3424                 if (INFO_LEVEL_IS_UNIX(info_level)) {
3425                         /* Always do lstat for UNIX calls. */
3426                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3427                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3428                                 return UNIXERROR(ERRDOS,ERRbadpath);
3429                         }
3430                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3431                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3432                         return UNIXERROR(ERRDOS,ERRbadpath);
3433                 }
3434
3435                 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
3436                 if (delete_pending) {
3437                         return ERROR_NT(NT_STATUS_DELETE_PENDING);
3438                 }
3439         }
3440
3441         nlink = sbuf.st_nlink;
3442
3443         if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3444                 /* NTFS does not seem to count ".." */
3445                 nlink -= 1;
3446         }
3447
3448         if ((nlink > 0) && delete_pending) {
3449                 nlink -= 1;
3450         }
3451
3452         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3453                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3454         }
3455
3456         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3457                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3458
3459         p = strrchr_m(fname,'/'); 
3460         if (!p)
3461                 base_name = fname;
3462         else
3463                 base_name = p+1;
3464
3465         mode = dos_mode(conn,fname,&sbuf);
3466         if (!mode)
3467                 mode = FILE_ATTRIBUTE_NORMAL;
3468
3469         fullpathname = fname;
3470         if (!(mode & aDIR))
3471                 file_size = get_file_size(sbuf);
3472
3473         /* Pull out any data sent here before we realloc. */
3474         switch (info_level) {
3475                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3476                 {
3477                         /* Pull any EA list from the data portion. */
3478                         uint32 ea_size;
3479
3480                         if (total_data < 4) {
3481                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3482                         }
3483                         ea_size = IVAL(pdata,0);
3484
3485                         if (total_data > 0 && ea_size != total_data) {
3486                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3487 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3488                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3489                         }
3490
3491                         if (!lp_ea_support(SNUM(conn))) {
3492                                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3493                         }
3494
3495                         if ((data_ctx = talloc_init("ea_list")) == NULL) {
3496                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3497                         }
3498
3499                         /* Pull out the list of names. */
3500                         ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3501                         if (!ea_list) {
3502                                 talloc_destroy(data_ctx);
3503                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3504                         }
3505                         break;
3506                 }
3507
3508                 case SMB_QUERY_POSIX_LOCK:
3509                 {
3510                         if (fsp == NULL || fsp->fh->fd == -1) {
3511                                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3512                         }
3513
3514                         if (total_data != POSIX_LOCK_DATA_SIZE) {
3515                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3516                         }
3517
3518                         if ((data_ctx = talloc_init("lock_request")) == NULL) {
3519                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3520                         }
3521
3522                         /* Copy the lock range data. */
3523                         lock_data = (char *)TALLOC_MEMDUP(
3524                                 data_ctx, pdata, total_data);
3525                         if (!lock_data) {
3526                                 talloc_destroy(data_ctx);
3527                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3528                         }
3529                 }
3530                 default:
3531                         break;
3532         }
3533
3534         *pparams = (char *)SMB_REALLOC(*pparams,2);
3535         if (*pparams == NULL) {
3536                 talloc_destroy(data_ctx);
3537                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3538         }
3539         params = *pparams;
3540         SSVAL(params,0,0);
3541         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3542         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3543         if (*ppdata == NULL ) {
3544                 talloc_destroy(data_ctx);
3545                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3546         }
3547         pdata = *ppdata;
3548
3549         create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3550         mtime_ts = get_mtimespec(&sbuf);
3551         atime_ts = get_atimespec(&sbuf);
3552
3553         allocation_size = get_allocation_size(conn,fsp,&sbuf);
3554
3555         if (fsp) {
3556                 if (!null_timespec(fsp->pending_modtime)) {
3557                         /* the pending modtime overrides the current modtime */
3558                         mtime_ts = fsp->pending_modtime;
3559                 }
3560         } else {
3561                 /* Do we have this path open ? */
3562                 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3563                 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3564                         /* the pending modtime overrides the current modtime */
3565                         mtime_ts = fsp1->pending_modtime;
3566                 }
3567                 if (fsp1 && fsp1->initial_allocation_size) {
3568                         allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3569                 }
3570         }
3571
3572         if (lp_dos_filetime_resolution(SNUM(conn))) {
3573                 dos_filetime_timespec(&create_time_ts);
3574                 dos_filetime_timespec(&mtime_ts);
3575                 dos_filetime_timespec(&atime_ts);
3576         }
3577
3578         create_time = convert_timespec_to_time_t(create_time_ts);
3579         mtime = convert_timespec_to_time_t(mtime_ts);
3580         atime = convert_timespec_to_time_t(atime_ts);
3581
3582         /* NT expects the name to be in an exact form of the *full*
3583            filename. See the trans2 torture test */
3584         if (strequal(base_name,".")) {
3585                 pstrcpy(dos_fname, "\\");
3586         } else {
3587                 pstr_sprintf(dos_fname, "\\%s", fname);
3588                 string_replace(dos_fname, '/', '\\');
3589         }
3590
3591         switch (info_level) {
3592                 case SMB_INFO_STANDARD:
3593                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3594                         data_size = 22;
3595                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3596                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3597                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3598                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
3599                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3600                         SSVAL(pdata,l1_attrFile,mode);
3601                         break;
3602
3603                 case SMB_INFO_QUERY_EA_SIZE:
3604                 {
3605                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3606                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3607                         data_size = 26;
3608                         srv_put_dos_date2(pdata,0,create_time);
3609                         srv_put_dos_date2(pdata,4,atime);
3610                         srv_put_dos_date2(pdata,8,mtime); /* write time */
3611                         SIVAL(pdata,12,(uint32)file_size);
3612                         SIVAL(pdata,16,(uint32)allocation_size);
3613                         SSVAL(pdata,20,mode);
3614                         SIVAL(pdata,22,ea_size);
3615                         break;
3616                 }
3617
3618                 case SMB_INFO_IS_NAME_VALID:
3619                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3620                         if (tran_call == TRANSACT2_QFILEINFO) {
3621                                 /* os/2 needs this ? really ?*/      
3622                                 return ERROR_DOS(ERRDOS,ERRbadfunc); 
3623                         }
3624                         data_size = 0;
3625                         param_size = 0;
3626                         break;
3627                         
3628                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3629                 {
3630                         size_t total_ea_len = 0;
3631                         struct ea_list *ea_file_list = NULL;
3632
3633                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3634
3635                         ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3636                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3637
3638                         if (!ea_list || (total_ea_len > data_size)) {
3639                                 talloc_destroy(data_ctx);
3640                                 data_size = 4;
3641                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3642                                 break;
3643                         }
3644
3645                         data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3646                         talloc_destroy(data_ctx);
3647                         break;
3648                 }
3649
3650                 case SMB_INFO_QUERY_ALL_EAS:
3651                 {
3652                         /* We have data_size bytes to put EA's into. */
3653                         size_t total_ea_len = 0;
3654
3655                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3656
3657                         data_ctx = talloc_init("ea_ctx");
3658                         if (!data_ctx) {
3659                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3660                         }
3661
3662                         ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3663                         if (!ea_list || (total_ea_len > data_size)) {
3664                                 talloc_destroy(data_ctx);
3665                                 data_size = 4;
3666                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3667                                 break;
3668                         }
3669
3670                         data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3671                         talloc_destroy(data_ctx);
3672                         break;
3673                 }
3674
3675                 case SMB_FILE_BASIC_INFORMATION:
3676                 case SMB_QUERY_FILE_BASIC_INFO:
3677
3678                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3679                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3680                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3681                         } else {
3682                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3683                                 data_size = 40;
3684                                 SIVAL(pdata,36,0);
3685                         }
3686                         put_long_date_timespec(pdata,create_time_ts);
3687                         put_long_date_timespec(pdata+8,atime_ts);
3688                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3689                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3690                         SIVAL(pdata,32,mode);
3691
3692                         DEBUG(5,("SMB_QFBI - "));
3693                         DEBUG(5,("create: %s ", ctime(&create_time)));
3694                         DEBUG(5,("access: %s ", ctime(&atime)));
3695                         DEBUG(5,("write: %s ", ctime(&mtime)));
3696                         DEBUG(5,("change: %s ", ctime(&mtime)));
3697                         DEBUG(5,("mode: %x\n", mode));
3698                         break;
3699
3700                 case SMB_FILE_STANDARD_INFORMATION:
3701                 case SMB_QUERY_FILE_STANDARD_INFO:
3702
3703                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3704                         data_size = 24;
3705                         SOFF_T(pdata,0,allocation_size);
3706                         SOFF_T(pdata,8,file_size);
3707                         SIVAL(pdata,16,nlink);
3708                         SCVAL(pdata,20,delete_pending?1:0);
3709                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3710                         SSVAL(pdata,22,0); /* Padding. */
3711                         break;
3712
3713                 case SMB_FILE_EA_INFORMATION:
3714                 case SMB_QUERY_FILE_EA_INFO:
3715                 {
3716                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3717                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3718                         data_size = 4;
3719                         SIVAL(pdata,0,ea_size);
3720                         break;
3721                 }
3722
3723                 /* Get the 8.3 name - used if NT SMB was negotiated. */
3724                 case SMB_QUERY_FILE_ALT_NAME_INFO:
3725                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3726                 {
3727                         pstring short_name;
3728
3729                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3730                         pstrcpy(short_name,base_name);
3731                         /* Mangle if not already 8.3 */
3732                         if(!mangle_is_8_3(short_name, True, conn->params)) {
3733                                 mangle_map(short_name,True,True,conn->params);
3734                         }
3735                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3736                         data_size = 4 + len;
3737                         SIVAL(pdata,0,len);
3738                         break;
3739                 }
3740
3741                 case SMB_QUERY_FILE_NAME_INFO:
3742                         /*
3743                           this must be *exactly* right for ACLs on mapped drives to work
3744                          */
3745                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3746                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3747                         data_size = 4 + len;
3748                         SIVAL(pdata,0,len);
3749                         break;
3750
3751                 case SMB_FILE_ALLOCATION_INFORMATION:
3752                 case SMB_QUERY_FILE_ALLOCATION_INFO:
3753                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3754                         data_size = 8;
3755                         SOFF_T(pdata,0,allocation_size);
3756                         break;
3757
3758                 case SMB_FILE_END_OF_FILE_INFORMATION:
3759                 case SMB_QUERY_FILE_END_OF_FILEINFO:
3760                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3761                         data_size = 8;
3762                         SOFF_T(pdata,0,file_size);
3763                         break;
3764
3765                 case SMB_QUERY_FILE_ALL_INFO:
3766                 case SMB_FILE_ALL_INFORMATION:
3767                 {
3768                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3769                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3770                         put_long_date_timespec(pdata,create_time_ts);
3771                         put_long_date_timespec(pdata+8,atime_ts);
3772                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3773                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3774                         SIVAL(pdata,32,mode);
3775                         SIVAL(pdata,36,0); /* padding. */
3776                         pdata += 40;
3777                         SOFF_T(pdata,0,allocation_size);
3778                         SOFF_T(pdata,8,file_size);
3779                         SIVAL(pdata,16,nlink);
3780                         SCVAL(pdata,20,delete_pending);
3781                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3782                         SSVAL(pdata,22,0);
3783                         pdata += 24;
3784                         SIVAL(pdata,0,ea_size);
3785                         pdata += 4; /* EA info */
3786                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3787                         SIVAL(pdata,0,len);
3788                         pdata += 4 + len;
3789                         data_size = PTR_DIFF(pdata,(*ppdata));
3790                         break;
3791                 }
3792                 case SMB_FILE_INTERNAL_INFORMATION:
3793                         /* This should be an index number - looks like
3794                            dev/ino to me :-) 
3795
3796                            I think this causes us to fail the IFSKIT
3797                            BasicFileInformationTest. -tpot */
3798
3799                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3800                         SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3801                         SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3802                         data_size = 8;
3803                         break;
3804
3805                 case SMB_FILE_ACCESS_INFORMATION:
3806                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3807                         SIVAL(pdata,0,access_mask);
3808                         data_size = 4;
3809                         break;
3810
3811                 case SMB_FILE_NAME_INFORMATION:
3812                         /* Pathname with leading '\'. */
3813                         {
3814                                 size_t byte_len;
3815                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3816                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3817                                 SIVAL(pdata,0,byte_len);
3818                                 data_size = 4 + byte_len;
3819                                 break;
3820                         }
3821
3822                 case SMB_FILE_DISPOSITION_INFORMATION:
3823                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3824                         data_size = 1;
3825                         SCVAL(pdata,0,delete_pending);
3826                         break;
3827
3828                 case SMB_FILE_POSITION_INFORMATION:
3829                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3830                         data_size = 8;
3831                         SOFF_T(pdata,0,pos);
3832                         break;
3833
3834                 case SMB_FILE_MODE_INFORMATION:
3835                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3836                         SIVAL(pdata,0,mode);
3837                         data_size = 4;
3838                         break;
3839
3840                 case SMB_FILE_ALIGNMENT_INFORMATION:
3841                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3842                         SIVAL(pdata,0,0); /* No alignment needed. */
3843                         data_size = 4;
3844                         break;
3845
3846 #if 0
3847                 /*
3848                  * NT4 server just returns "invalid query" to this - if we try to answer
3849                  * it then NTws gets a BSOD! (tridge).
3850                  * W2K seems to want this. JRA.
3851                  */
3852                 case SMB_QUERY_FILE_STREAM_INFO:
3853 #endif
3854                 case SMB_FILE_STREAM_INFORMATION:
3855                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3856                         if (mode & aDIR) {
3857                                 data_size = 0;
3858                         } else {
3859                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3860                                 SIVAL(pdata,0,0); /* ??? */
3861                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3862                                 SOFF_T(pdata,8,file_size);
3863                                 SOFF_T(pdata,16,allocation_size);
3864                                 data_size = 24 + byte_len;
3865                         }
3866                         break;
3867
3868                 case SMB_QUERY_COMPRESSION_INFO:
3869                 case SMB_FILE_COMPRESSION_INFORMATION:
3870                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3871                         SOFF_T(pdata,0,file_size);
3872                         SIVAL(pdata,8,0); /* ??? */
3873                         SIVAL(pdata,12,0); /* ??? */
3874                         data_size = 16;
3875                         break;
3876
3877                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3878                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3879                         put_long_date_timespec(pdata,create_time_ts);
3880                         put_long_date_timespec(pdata+8,atime_ts);
3881                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3882                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3883                         SOFF_T(pdata,32,allocation_size);
3884                         SOFF_T(pdata,40,file_size);
3885                         SIVAL(pdata,48,mode);
3886                         SIVAL(pdata,52,0); /* ??? */
3887                         data_size = 56;
3888                         break;
3889
3890                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3891                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3892                         SIVAL(pdata,0,mode);
3893                         SIVAL(pdata,4,0);
3894                         data_size = 8;
3895                         break;
3896
3897                 /*
3898                  * CIFS UNIX Extensions.
3899                  */
3900
3901                 case SMB_QUERY_FILE_UNIX_BASIC:
3902
3903                         pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3904                         data_size = PTR_DIFF(pdata,(*ppdata));
3905
3906                         {
3907                                 int i;
3908                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3909
3910                                 for (i=0; i<100; i++)
3911                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3912                                 DEBUG(4,("\n"));
3913                         }
3914
3915                         break;
3916
3917                 case SMB_QUERY_FILE_UNIX_INFO2:
3918
3919                         pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3920                         data_size = PTR_DIFF(pdata,(*ppdata));
3921
3922                         {
3923                                 int i;
3924                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3925
3926                                 for (i=0; i<100; i++)
3927                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3928                                 DEBUG(4,("\n"));
3929                         }
3930
3931                         break;
3932
3933                 case SMB_QUERY_FILE_UNIX_LINK:
3934                         {
3935                                 pstring buffer;
3936
3937                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3938 #ifdef S_ISLNK
3939                                 if(!S_ISLNK(sbuf.st_mode))
3940                                         return(UNIXERROR(ERRSRV,ERRbadlink));
3941 #else
3942                                 return(UNIXERROR(ERRDOS,ERRbadlink));
3943 #endif
3944                                 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
3945                                 if (len == -1)
3946                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3947                                 buffer[len] = 0;
3948                                 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3949                                 pdata += len;
3950                                 data_size = PTR_DIFF(pdata,(*ppdata));
3951
3952                                 break;
3953                         }
3954
3955 #if defined(HAVE_POSIX_ACLS)
3956                 case SMB_QUERY_POSIX_ACL:
3957                         {
3958                                 SMB_ACL_T file_acl = NULL;
3959                                 SMB_ACL_T def_acl = NULL;
3960                                 uint16 num_file_acls = 0;
3961                                 uint16 num_def_acls = 0;
3962
3963                                 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3964                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3965                                 } else {
3966                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3967                                 }
3968
3969                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3970                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3971                                                 fname ));
3972                                         return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3973                                 }
3974
3975                                 if (S_ISDIR(sbuf.st_mode)) {
3976                                         if (fsp && fsp->is_directory) {
3977                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3978                                         } else {
3979                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3980                                         }
3981                                         def_acl = free_empty_sys_acl(conn, def_acl);
3982                                 }
3983
3984                                 num_file_acls = count_acl_entries(conn, file_acl);
3985                                 num_def_acls = count_acl_entries(conn, def_acl);
3986
3987                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3988                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3989                                                 data_size,
3990                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3991                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
3992                                         if (file_acl) {
3993                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3994                                         }
3995                                         if (def_acl) {
3996                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3997                                         }
3998                                         return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3999                                 }
4000
4001                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4002                                 SSVAL(pdata,2,num_file_acls);
4003                                 SSVAL(pdata,4,num_def_acls);
4004                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4005                                         if (file_acl) {
4006                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4007                                         }
4008                                         if (def_acl) {
4009                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4010                                         }
4011                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4012                                 }
4013                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4014                                         if (file_acl) {
4015                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4016                                         }
4017                                         if (def_acl) {
4018                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4019                                         }
4020                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4021                                 }
4022
4023                                 if (file_acl) {
4024                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4025                                 }
4026                                 if (def_acl) {
4027                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4028                                 }
4029                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4030                                 break;
4031                         }
4032 #endif
4033
4034
4035                 case SMB_QUERY_POSIX_LOCK:
4036                 {
4037                         NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4038                         SMB_BIG_UINT count;
4039                         SMB_BIG_UINT offset;
4040                         uint32 lock_pid;
4041                         enum brl_type lock_type;
4042
4043                         if (total_data != POSIX_LOCK_DATA_SIZE) {
4044                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4045                         }
4046
4047                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4048                                 case POSIX_LOCK_TYPE_READ:
4049                                         lock_type = READ_LOCK;
4050                                         break;
4051                                 case POSIX_LOCK_TYPE_WRITE:
4052                                         lock_type = WRITE_LOCK;
4053                                         break;
4054                                 case POSIX_LOCK_TYPE_UNLOCK:
4055                                 default:
4056                                         /* There's no point in asking for an unlock... */
4057                                         talloc_destroy(data_ctx);
4058                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4059                         }
4060
4061                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4062 #if defined(HAVE_LONGLONG)
4063                         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4064                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4065                         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4066                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4067 #else /* HAVE_LONGLONG */
4068                         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4069                         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4070 #endif /* HAVE_LONGLONG */
4071
4072                         status = query_lock(fsp,
4073                                         &lock_pid,
4074                                         &count,
4075                                         &offset,
4076                                         &lock_type,
4077                                         POSIX_LOCK);
4078
4079                         if (ERROR_WAS_LOCK_DENIED(status)) {
4080                                 /* Here we need to report who has it locked... */
4081                                 data_size = POSIX_LOCK_DATA_SIZE;
4082
4083                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4084                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4085                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4086 #if defined(HAVE_LONGLONG)
4087                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4088                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4089                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4090                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4091 #else /* HAVE_LONGLONG */
4092                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4093                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4094 #endif /* HAVE_LONGLONG */
4095
4096                         } else if (NT_STATUS_IS_OK(status)) {
4097                                 /* For success we just return a copy of what we sent
4098                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4099                                 data_size = POSIX_LOCK_DATA_SIZE;
4100                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4101                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4102                         } else {
4103                                 return ERROR_NT(status);
4104                         }
4105                         break;
4106                 }
4107
4108                 default:
4109                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4110         }
4111
4112         send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4113
4114         return(-1);
4115 }
4116
4117 /****************************************************************************
4118  Set a hard link (called by UNIX extensions and by NT rename with HARD link
4119  code.
4120 ****************************************************************************/
4121
4122 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4123 {
4124         SMB_STRUCT_STAT sbuf1, sbuf2;
4125         pstring last_component_oldname;
4126         pstring last_component_newname;
4127         NTSTATUS status = NT_STATUS_OK;
4128
4129         ZERO_STRUCT(sbuf1);
4130         ZERO_STRUCT(sbuf2);
4131
4132         status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4133         if (!NT_STATUS_IS_OK(status)) {
4134                 return status;
4135         }
4136
4137         status = check_name(conn, oldname);
4138         if (!NT_STATUS_IS_OK(status)) {
4139                 return status;
4140         }
4141
4142         /* source must already exist. */
4143         if (!VALID_STAT(sbuf1)) {
4144                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4145         }
4146
4147         status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4148         if (!NT_STATUS_IS_OK(status)) {
4149                 return status;
4150         }
4151
4152         status = check_name(conn, newname);
4153         if (!NT_STATUS_IS_OK(status)) {
4154                 return status;
4155         }
4156
4157         /* Disallow if newname already exists. */
4158         if (VALID_STAT(sbuf2)) {
4159                 return NT_STATUS_OBJECT_NAME_COLLISION;
4160         }
4161
4162         /* No links from a directory. */
4163         if (S_ISDIR(sbuf1.st_mode)) {
4164                 return NT_STATUS_FILE_IS_A_DIRECTORY;
4165         }
4166
4167         /* Ensure this is within the share. */
4168         status = reduce_name(conn, oldname);
4169         if (!NT_STATUS_IS_OK(status)) {
4170                 return status;
4171         }
4172
4173         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4174
4175         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4176                 status = map_nt_error_from_unix(errno);
4177                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4178                                 nt_errstr(status), newname, oldname));
4179         }
4180
4181         return status;
4182 }
4183
4184 /****************************************************************************
4185  Deal with setting the time from any of the setfilepathinfo functions.
4186 ****************************************************************************/
4187
4188 static NTSTATUS smb_set_file_time(connection_struct *conn,
4189                                 files_struct *fsp,
4190                                 const char *fname,
4191                                 const SMB_STRUCT_STAT *psbuf,
4192                                 struct timespec ts[2])
4193 {
4194         uint32 action =
4195                 FILE_NOTIFY_CHANGE_LAST_ACCESS
4196                 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4197
4198         
4199         if (!VALID_STAT(*psbuf)) {
4200                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4201         }
4202
4203         /* get some defaults (no modifications) if any info is zero or -1. */
4204         if (null_timespec(ts[0])) {
4205                 ts[0] = get_atimespec(psbuf);
4206                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4207         }
4208
4209         if (null_timespec(ts[1])) {
4210                 ts[1] = get_mtimespec(psbuf);
4211                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4212         }
4213
4214         DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4215         DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4216
4217         /*
4218          * Try and set the times of this file if
4219          * they are different from the current values.
4220          */
4221
4222         {
4223                 struct timespec mts = get_mtimespec(psbuf);
4224                 struct timespec ats = get_atimespec(psbuf);
4225                 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4226                         return NT_STATUS_OK;
4227                 }
4228         }
4229
4230         if(fsp != NULL) {
4231                 /*
4232                  * This was a setfileinfo on an open file.
4233                  * NT does this a lot. We also need to 
4234                  * set the time here, as it can be read by 
4235                  * FindFirst/FindNext and with the patch for bug #2045
4236                  * in smbd/fileio.c it ensures that this timestamp is
4237                  * kept sticky even after a write. We save the request
4238                  * away and will set it on file close and after a write. JRA.
4239                  */
4240
4241                 if (!null_timespec(ts[1])) {
4242                         DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4243                                 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4244                         fsp_set_pending_modtime(fsp, ts[1]);
4245                 }
4246
4247         }
4248         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4249
4250         if(file_ntimes(conn, fname, ts)!=0) {
4251                 return map_nt_error_from_unix(errno);
4252         }
4253         if (action != 0) {
4254                 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4255         }
4256         return NT_STATUS_OK;
4257 }
4258
4259 /****************************************************************************
4260  Deal with setting the dosmode from any of the setfilepathinfo functions.
4261 ****************************************************************************/
4262
4263 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4264                                 const char *fname,
4265                                 SMB_STRUCT_STAT *psbuf,
4266                                 uint32 dosmode)
4267 {
4268         if (!VALID_STAT(*psbuf)) {
4269                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4270         }
4271
4272         if (dosmode) {
4273                 if (S_ISDIR(psbuf->st_mode)) {
4274                         dosmode |= aDIR;
4275                 } else {
4276                         dosmode &= ~aDIR;
4277                 }
4278         }
4279
4280         DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4281
4282         /* check the mode isn't different, before changing it */
4283         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4284
4285                 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4286                                         fname, (unsigned int)dosmode ));
4287
4288                 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4289                         DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4290                                                 fname, strerror(errno)));
4291                         return map_nt_error_from_unix(errno);
4292                 }
4293         }
4294         return NT_STATUS_OK;
4295 }
4296
4297 /****************************************************************************
4298  Deal with setting the size from any of the setfilepathinfo functions.
4299 ****************************************************************************/
4300
4301 static NTSTATUS smb_set_file_size(connection_struct *conn,
4302                                 files_struct *fsp,
4303                                 const char *fname,
4304                                 SMB_STRUCT_STAT *psbuf,
4305                                 SMB_OFF_T size)
4306 {
4307         NTSTATUS status = NT_STATUS_OK;
4308         files_struct *new_fsp = NULL;
4309
4310         if (!VALID_STAT(*psbuf)) {
4311                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4312         }
4313
4314         DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4315
4316         if (size == get_file_size(*psbuf)) {
4317                 return NT_STATUS_OK;
4318         }
4319
4320         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4321                 fname, (double)size ));
4322
4323         if (fsp && fsp->fh->fd != -1) {
4324                 /* Handle based call. */
4325                 if (vfs_set_filelen(fsp, size) == -1) {
4326                         return map_nt_error_from_unix(errno);
4327                 }
4328                 return NT_STATUS_OK;
4329         }
4330
4331         status = open_file_ntcreate(conn, fname, psbuf,
4332                                 FILE_WRITE_DATA,
4333                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4334                                 FILE_OPEN,
4335                                 0,
4336                                 FILE_ATTRIBUTE_NORMAL,
4337                                 FORCE_OPLOCK_BREAK_TO_NONE,
4338                                 NULL, &new_fsp);
4339         
4340         if (!NT_STATUS_IS_OK(status)) {
4341                 /* NB. We check for open_was_deferred in the caller. */
4342                 return status;
4343         }
4344
4345         if (vfs_set_filelen(new_fsp, size) == -1) {
4346                 status = map_nt_error_from_unix(errno);
4347                 close_file(new_fsp,NORMAL_CLOSE);
4348                 return status;
4349         }
4350
4351         close_file(new_fsp,NORMAL_CLOSE);
4352         return NT_STATUS_OK;
4353 }
4354
4355 /****************************************************************************
4356  Deal with SMB_INFO_SET_EA.
4357 ****************************************************************************/
4358
4359 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4360                                 const char *pdata,
4361                                 int total_data,
4362                                 files_struct *fsp,
4363                                 const char *fname)
4364 {
4365         struct ea_list *ea_list = NULL;
4366         TALLOC_CTX *ctx = NULL;
4367         NTSTATUS status = NT_STATUS_OK;
4368
4369         if (total_data < 10) {
4370
4371                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4372                    length. They seem to have no effect. Bug #3212. JRA */
4373
4374                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4375                         /* We're done. We only get EA info in this call. */
4376                         return NT_STATUS_OK;
4377                 }
4378
4379                 return NT_STATUS_INVALID_PARAMETER;
4380         }
4381
4382         if (IVAL(pdata,0) > total_data) {
4383                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4384                         IVAL(pdata,0), (unsigned int)total_data));
4385                 return NT_STATUS_INVALID_PARAMETER;
4386         }
4387
4388         ctx = talloc_init("SMB_INFO_SET_EA");
4389         if (!ctx) {
4390                 return NT_STATUS_NO_MEMORY;
4391         }
4392         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4393         if (!ea_list) {
4394                 talloc_destroy(ctx);
4395                 return NT_STATUS_INVALID_PARAMETER;
4396         }
4397         status = set_ea(conn, fsp, fname, ea_list);
4398         talloc_destroy(ctx);
4399
4400         return status;
4401 }
4402
4403 /****************************************************************************
4404  Deal with SMB_SET_FILE_DISPOSITION_INFO.
4405 ****************************************************************************/
4406
4407 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4408                                 const char *pdata,
4409                                 int total_data,
4410                                 files_struct *fsp,
4411                                 const char *fname,
4412                                 SMB_STRUCT_STAT *psbuf)
4413 {
4414         NTSTATUS status = NT_STATUS_OK;
4415         BOOL delete_on_close;
4416         uint32 dosmode = 0;
4417
4418         if (total_data < 1) {
4419                 return NT_STATUS_INVALID_PARAMETER;
4420         }
4421
4422         if (fsp == NULL) {
4423                 return NT_STATUS_INVALID_HANDLE;
4424         }
4425
4426         delete_on_close = (CVAL(pdata,0) ? True : False);
4427         dosmode = dos_mode(conn, fname, psbuf);
4428
4429         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4430                 "delete_on_close = %u\n",
4431                 fsp->fsp_name,
4432                 (unsigned int)dosmode,
4433                 (unsigned int)delete_on_close ));
4434
4435         status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4436  
4437         if (!NT_STATUS_IS_OK(status)) {
4438                 return status;
4439         }
4440
4441         /* The set is across all open files on this dev/inode pair. */
4442         if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4443                 return NT_STATUS_ACCESS_DENIED;
4444         }
4445         return NT_STATUS_OK;
4446 }
4447
4448 /****************************************************************************
4449  Deal with SMB_FILE_POSITION_INFORMATION.
4450 ****************************************************************************/
4451
4452 static NTSTATUS smb_file_position_information(connection_struct *conn,
4453                                 const char *pdata,
4454                                 int total_data,
4455                                 files_struct *fsp)
4456 {
4457         SMB_BIG_UINT position_information;
4458
4459         if (total_data < 8) {
4460                 return NT_STATUS_INVALID_PARAMETER;
4461         }
4462
4463         if (fsp == NULL) {
4464                 /* Ignore on pathname based set. */
4465                 return NT_STATUS_OK;
4466         }
4467
4468         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4469 #ifdef LARGE_SMB_OFF_T
4470         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4471 #else /* LARGE_SMB_OFF_T */
4472         if (IVAL(pdata,4) != 0) {
4473                 /* more than 32 bits? */
4474                 return NT_STATUS_INVALID_PARAMETER;
4475         }
4476 #endif /* LARGE_SMB_OFF_T */
4477
4478         DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4479                 fsp->fsp_name, (double)position_information ));
4480         fsp->fh->position_information = position_information;
4481         return NT_STATUS_OK;
4482 }
4483
4484 /****************************************************************************
4485  Deal with SMB_FILE_MODE_INFORMATION.
4486 ****************************************************************************/
4487
4488 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4489                                 const char *pdata,
4490                                 int total_data)
4491 {
4492         uint32 mode;
4493
4494         if (total_data < 4) {
4495                 return NT_STATUS_INVALID_PARAMETER;
4496         }
4497         mode = IVAL(pdata,0);
4498         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4499                 return NT_STATUS_INVALID_PARAMETER;
4500         }
4501         return NT_STATUS_OK;
4502 }
4503
4504 /****************************************************************************
4505  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4506 ****************************************************************************/
4507
4508 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4509                                 char *inbuf,
4510                                 const char *pdata,
4511                                 int total_data,
4512                                 const char *fname)
4513 {
4514         pstring link_target;
4515         const char *newname = fname;
4516         NTSTATUS status = NT_STATUS_OK;
4517
4518         /* Set a symbolic link. */
4519         /* Don't allow this if follow links is false. */
4520
4521         if (total_data == 0) {
4522                 return NT_STATUS_INVALID_PARAMETER;
4523         }
4524
4525         if (!lp_symlinks(SNUM(conn))) {
4526                 return NT_STATUS_ACCESS_DENIED;
4527         }
4528
4529         srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
4530
4531         /* !widelinks forces the target path to be within the share. */
4532         /* This means we can interpret the target as a pathname. */
4533         if (!lp_widelinks(SNUM(conn))) {
4534                 pstring rel_name;
4535                 char *last_dirp = NULL;
4536
4537                 if (*link_target == '/') {
4538                         /* No absolute paths allowed. */
4539                         return NT_STATUS_ACCESS_DENIED;
4540                 }
4541                 pstrcpy(rel_name, newname);
4542                 last_dirp = strrchr_m(rel_name, '/');
4543                 if (last_dirp) {
4544                         last_dirp[1] = '\0';
4545                 } else {
4546                         pstrcpy(rel_name, "./");
4547                 }
4548                 pstrcat(rel_name, link_target);
4549
4550                 status = check_name(conn, rel_name);
4551                 if (!NT_STATUS_IS_OK(status)) {
4552                         return status;
4553                 }
4554         }
4555
4556         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4557                         newname, link_target ));
4558
4559         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4560                 return map_nt_error_from_unix(errno);
4561         }
4562
4563         return NT_STATUS_OK;
4564 }
4565
4566 /****************************************************************************
4567  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4568 ****************************************************************************/
4569
4570 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4571                                 char *inbuf,
4572                                 char *outbuf,
4573                                 const char *pdata,
4574                                 int total_data,
4575                                 pstring fname)
4576 {
4577         pstring oldname;
4578         NTSTATUS status = NT_STATUS_OK;
4579
4580         /* Set a hard link. */
4581         if (total_data == 0) {
4582                 return NT_STATUS_INVALID_PARAMETER;
4583         }
4584
4585         srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
4586         if (!NT_STATUS_IS_OK(status)) {
4587                 return status;
4588         }
4589
4590         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4591         if (!NT_STATUS_IS_OK(status)) {
4592                 return status;
4593         }
4594
4595         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4596                 fname, oldname));
4597
4598         return hardlink_internals(conn, oldname, fname);
4599 }
4600
4601 /****************************************************************************
4602  Deal with SMB_FILE_RENAME_INFORMATION.
4603 ****************************************************************************/
4604
4605 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4606                                 char *inbuf,
4607                                 char *outbuf,
4608                                 const char *pdata,
4609                                 int total_data,
4610                                 files_struct *fsp,
4611                                 pstring fname)
4612 {
4613         BOOL overwrite;
4614         /* uint32 root_fid; */  /* Not used */
4615         uint32 len;
4616         pstring newname;
4617         pstring base_name;
4618         BOOL dest_has_wcard = False;
4619         NTSTATUS status = NT_STATUS_OK;
4620         char *p;
4621
4622         if (total_data < 13) {
4623                 return NT_STATUS_INVALID_PARAMETER;
4624         }
4625
4626         overwrite = (CVAL(pdata,0) ? True : False);
4627         /* root_fid = IVAL(pdata,4); */
4628         len = IVAL(pdata,8);
4629
4630         if (len > (total_data - 12) || (len == 0)) {
4631                 return NT_STATUS_INVALID_PARAMETER;
4632         }
4633
4634         srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
4635         if (!NT_STATUS_IS_OK(status)) {
4636                 return status;
4637         }
4638
4639         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4640         if (!NT_STATUS_IS_OK(status)) {
4641                 return status;
4642         }
4643
4644         /* Check the new name has no '/' characters. */
4645         if (strchr_m(newname, '/')) {
4646                 return NT_STATUS_NOT_SUPPORTED;
4647         }
4648
4649         /* Create the base directory. */
4650         pstrcpy(base_name, fname);
4651         p = strrchr_m(base_name, '/');
4652         if (p) {
4653                 p[1] = '\0';
4654         } else {
4655                 pstrcpy(base_name, "./");
4656         }
4657         /* Append the new name. */
4658         pstrcat(base_name, newname);
4659
4660         if (fsp) {
4661                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4662                         fsp->fnum, fsp->fsp_name, base_name ));
4663                 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4664         } else {
4665                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4666                         fname, newname ));
4667                 status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
4668         }
4669
4670         return status;
4671 }
4672
4673 /****************************************************************************
4674  Deal with SMB_SET_POSIX_ACL.
4675 ****************************************************************************/
4676
4677 #if defined(HAVE_POSIX_ACLS)
4678 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4679                                 const char *pdata,
4680                                 int total_data,
4681                                 files_struct *fsp,
4682                                 const char *fname,
4683                                 SMB_STRUCT_STAT *psbuf)
4684 {
4685         uint16 posix_acl_version;
4686         uint16 num_file_acls;
4687         uint16 num_def_acls;
4688         BOOL valid_file_acls = True;
4689         BOOL valid_def_acls = True;
4690
4691         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4692                 return NT_STATUS_INVALID_PARAMETER;
4693         }
4694         posix_acl_version = SVAL(pdata,0);
4695         num_file_acls = SVAL(pdata,2);
4696         num_def_acls = SVAL(pdata,4);
4697
4698         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4699                 valid_file_acls = False;
4700                 num_file_acls = 0;
4701         }
4702
4703         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4704                 valid_def_acls = False;
4705                 num_def_acls = 0;
4706         }
4707
4708         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4709                 return NT_STATUS_INVALID_PARAMETER;
4710         }
4711
4712         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4713                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4714                 return NT_STATUS_INVALID_PARAMETER;
4715         }
4716
4717         DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4718                 fname ? fname : fsp->fsp_name,
4719                 (unsigned int)num_file_acls,
4720                 (unsigned int)num_def_acls));
4721
4722         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4723                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4724                 return map_nt_error_from_unix(errno);
4725         }
4726
4727         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4728                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
4729                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4730                 return map_nt_error_from_unix(errno);
4731         }
4732         return NT_STATUS_OK;
4733 }
4734 #endif
4735
4736 /****************************************************************************
4737  Deal with SMB_SET_POSIX_LOCK.
4738 ****************************************************************************/
4739
4740 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4741                                 char *inbuf,
4742                                 int length,
4743                                 const char *pdata,
4744                                 int total_data,
4745                                 files_struct *fsp)
4746 {
4747         SMB_BIG_UINT count;
4748         SMB_BIG_UINT offset;
4749         uint32 lock_pid;
4750         BOOL blocking_lock = False;
4751         enum brl_type lock_type;
4752         NTSTATUS status = NT_STATUS_OK;
4753
4754         if (fsp == NULL || fsp->fh->fd == -1) {
4755                 return NT_STATUS_INVALID_HANDLE;
4756         }
4757
4758         if (total_data != POSIX_LOCK_DATA_SIZE) {
4759                 return NT_STATUS_INVALID_PARAMETER;
4760         }
4761
4762         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4763                 case POSIX_LOCK_TYPE_READ:
4764                         lock_type = READ_LOCK;
4765                         break;
4766                 case POSIX_LOCK_TYPE_WRITE:
4767                         /* Return the right POSIX-mappable error code for files opened read-only. */
4768                         if (!fsp->can_write) {
4769                                 return NT_STATUS_INVALID_HANDLE;
4770                         }
4771                         lock_type = WRITE_LOCK;
4772                         break;
4773                 case POSIX_LOCK_TYPE_UNLOCK:
4774                         lock_type = UNLOCK_LOCK;
4775                         break;
4776                 default:
4777                         return NT_STATUS_INVALID_PARAMETER;
4778         }
4779
4780         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4781                 blocking_lock = False;
4782         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4783                 blocking_lock = True;
4784         } else {
4785                 return NT_STATUS_INVALID_PARAMETER;
4786         }
4787
4788         if (!lp_blocking_locks(SNUM(conn))) { 
4789                 blocking_lock = False;
4790         }
4791
4792         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4793 #if defined(HAVE_LONGLONG)
4794         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4795                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4796         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4797                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4798 #else /* HAVE_LONGLONG */
4799         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4800         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4801 #endif /* HAVE_LONGLONG */
4802
4803         DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4804                         "lock_pid = %u, count = %.0f, offset = %.0f\n",
4805                 fsp->fsp_name,
4806                 (unsigned int)lock_type,
4807                 (unsigned int)lock_pid,
4808                 (double)count,
4809                 (double)offset ));
4810
4811         if (lock_type == UNLOCK_LOCK) {
4812                 status = do_unlock(smbd_messaging_context(),
4813                                 fsp,
4814                                 lock_pid,
4815                                 count,
4816                                 offset,
4817                                 POSIX_LOCK);
4818         } else {
4819                 uint32 block_smbpid;
4820
4821                 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
4822                                                         fsp,
4823                                                         lock_pid,
4824                                                         count,
4825                                                         offset,
4826                                                         lock_type,
4827                                                         POSIX_LOCK,
4828                                                         blocking_lock,
4829                                                         &status,
4830                                                         &block_smbpid);
4831
4832                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4833                         /*
4834                          * A blocking lock was requested. Package up
4835                          * this smb into a queued request and push it
4836                          * onto the blocking lock queue.
4837                          */
4838                         if(push_blocking_lock_request(br_lck,
4839                                                 inbuf, length,
4840                                                 fsp,
4841                                                 -1, /* infinite timeout. */
4842                                                 0,
4843                                                 lock_pid,
4844                                                 lock_type,
4845                                                 POSIX_LOCK,
4846                                                 offset,
4847                                                 count,
4848                                                 block_smbpid)) {
4849                                 TALLOC_FREE(br_lck);
4850                                 return status;
4851                         }
4852                 }
4853                 TALLOC_FREE(br_lck);
4854         }
4855
4856         return status;
4857 }
4858
4859 /****************************************************************************
4860  Deal with SMB_INFO_STANDARD.
4861 ****************************************************************************/
4862
4863 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4864                                         const char *pdata,
4865                                         int total_data,
4866                                         files_struct *fsp,
4867                                         const char *fname,
4868                                         const SMB_STRUCT_STAT *psbuf)
4869 {
4870         struct timespec ts[2];
4871
4872         if (total_data < 12) {
4873                 return NT_STATUS_INVALID_PARAMETER;
4874         }
4875
4876         /* access time */
4877         ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4878         /* write time */
4879         ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4880
4881         DEBUG(10,("smb_set_info_standard: file %s\n",
4882                 fname ? fname : fsp->fsp_name ));
4883
4884         return smb_set_file_time(conn,
4885                                 fsp,
4886                                 fname,
4887                                 psbuf,
4888                                 ts);
4889 }
4890
4891 /****************************************************************************
4892  Deal with SMB_SET_FILE_BASIC_INFO.
4893 ****************************************************************************/
4894
4895 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4896                                         const char *pdata,
4897                                         int total_data,
4898                                         files_struct *fsp,
4899                                         const char *fname,
4900                                         SMB_STRUCT_STAT *psbuf)
4901 {
4902         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4903         struct timespec write_time;
4904         struct timespec changed_time;
4905         uint32 dosmode = 0;
4906         struct timespec ts[2];
4907         NTSTATUS status = NT_STATUS_OK;
4908
4909         if (total_data < 36) {
4910                 return NT_STATUS_INVALID_PARAMETER;
4911         }
4912
4913         /* Set the attributes */
4914         dosmode = IVAL(pdata,32);
4915         status = smb_set_file_dosmode(conn,
4916                                         fname,
4917                                         psbuf,
4918                                         dosmode);
4919         if (!NT_STATUS_IS_OK(status)) {
4920                 return status;
4921         }
4922
4923         /* Ignore create time at offset pdata. */
4924
4925         /* access time */
4926         ts[0] = interpret_long_date(pdata+8);
4927
4928         write_time = interpret_long_date(pdata+16);
4929         changed_time = interpret_long_date(pdata+24);
4930
4931         /* mtime */
4932         ts[1] = timespec_min(&write_time, &changed_time);
4933
4934         if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4935                 ts[1] = write_time;
4936         }
4937
4938         /* Prefer a defined time to an undefined one. */
4939         if (null_timespec(ts[1])) {
4940                 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4941         }
4942
4943         DEBUG(10,("smb_set_file_basic_info: file %s\n",
4944                 fname ? fname : fsp->fsp_name ));
4945
4946         return smb_set_file_time(conn,
4947                                 fsp,
4948                                 fname,
4949                                 psbuf,
4950                                 ts);
4951 }
4952
4953 /****************************************************************************
4954  Deal with SMB_SET_FILE_ALLOCATION_INFO.
4955 ****************************************************************************/
4956
4957 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4958                                         const char *pdata,
4959                                         int total_data,
4960                                         files_struct *fsp,
4961                                         const char *fname,
4962                                         SMB_STRUCT_STAT *psbuf)
4963 {
4964         SMB_BIG_UINT allocation_size = 0;
4965         NTSTATUS status = NT_STATUS_OK;
4966         files_struct *new_fsp = NULL;
4967
4968         if (!VALID_STAT(*psbuf)) {
4969                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4970         }
4971
4972         if (total_data < 8) {
4973                 return NT_STATUS_INVALID_PARAMETER;
4974         }
4975
4976         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4977 #ifdef LARGE_SMB_OFF_T
4978         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4979 #else /* LARGE_SMB_OFF_T */
4980         if (IVAL(pdata,4) != 0) {
4981                 /* more than 32 bits? */
4982                 return NT_STATUS_INVALID_PARAMETER;
4983         }
4984 #endif /* LARGE_SMB_OFF_T */
4985
4986         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4987                         fname, (double)allocation_size ));
4988
4989         if (allocation_size) {
4990                 allocation_size = smb_roundup(conn, allocation_size);
4991         }
4992
4993         if(allocation_size == get_file_size(*psbuf)) {
4994                 return NT_STATUS_OK;
4995         }
4996  
4997         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4998                         fname, (double)allocation_size ));
4999  
5000         if (fsp && fsp->fh->fd != -1) {
5001                 /* Open file handle. */
5002                 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5003                         return map_nt_error_from_unix(errno);
5004                 }
5005                 return NT_STATUS_OK;
5006         }
5007
5008         /* Pathname or stat or directory file. */
5009
5010         status = open_file_ntcreate(conn, fname, psbuf,
5011                                 FILE_WRITE_DATA,
5012                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5013                                 FILE_OPEN,
5014                                 0,
5015                                 FILE_ATTRIBUTE_NORMAL,
5016                                 FORCE_OPLOCK_BREAK_TO_NONE,
5017                                 NULL, &new_fsp);
5018  
5019         if (!NT_STATUS_IS_OK(status)) {
5020                 /* NB. We check for open_was_deferred in the caller. */
5021                 return status;
5022         }
5023         if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5024                 status = map_nt_error_from_unix(errno);
5025                 close_file(new_fsp,NORMAL_CLOSE);
5026                 return status;
5027         }
5028
5029         close_file(new_fsp,NORMAL_CLOSE);
5030         return NT_STATUS_OK;
5031 }
5032
5033 /****************************************************************************
5034  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5035 ****************************************************************************/
5036
5037 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5038                                         const char *pdata,
5039                                         int total_data,
5040                                         files_struct *fsp,
5041                                         const char *fname,
5042                                         SMB_STRUCT_STAT *psbuf)
5043 {
5044         SMB_OFF_T size;
5045
5046         if (total_data < 8) {
5047                 return NT_STATUS_INVALID_PARAMETER;
5048         }
5049
5050         size = IVAL(pdata,0);
5051 #ifdef LARGE_SMB_OFF_T
5052         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5053 #else /* LARGE_SMB_OFF_T */
5054         if (IVAL(pdata,4) != 0) {
5055                 /* more than 32 bits? */
5056                 return NT_STATUS_INVALID_PARAMETER;
5057         }
5058 #endif /* LARGE_SMB_OFF_T */
5059         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5060                 "file %s to %.0f\n", fname, (double)size ));
5061
5062         return smb_set_file_size(conn,
5063                                 fsp,
5064                                 fname,
5065                                 psbuf,
5066                                 size);
5067 }
5068
5069 /****************************************************************************
5070  Allow a UNIX info mknod.
5071 ****************************************************************************/
5072
5073 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5074                                         const char *pdata,
5075                                         int total_data,
5076                                         const char *fname,
5077                                         SMB_STRUCT_STAT *psbuf)
5078 {
5079         uint32 file_type = IVAL(pdata,56);
5080 #if defined(HAVE_MAKEDEV)
5081         uint32 dev_major = IVAL(pdata,60);
5082         uint32 dev_minor = IVAL(pdata,68);
5083 #endif
5084         SMB_DEV_T dev = (SMB_DEV_T)0;
5085         uint32 raw_unixmode = IVAL(pdata,84);
5086         NTSTATUS status;
5087         mode_t unixmode;
5088
5089         if (total_data < 100) {
5090                 return NT_STATUS_INVALID_PARAMETER;
5091         }
5092
5093         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5094         if (!NT_STATUS_IS_OK(status)) {
5095                 return status;
5096         }
5097
5098 #if defined(HAVE_MAKEDEV)
5099         dev = makedev(dev_major, dev_minor);
5100 #endif
5101
5102         switch (file_type) {
5103 #if defined(S_IFIFO)
5104                 case UNIX_TYPE_FIFO:
5105                         unixmode |= S_IFIFO;
5106                         break;
5107 #endif
5108 #if defined(S_IFSOCK)
5109                 case UNIX_TYPE_SOCKET:
5110                         unixmode |= S_IFSOCK;
5111                         break;
5112 #endif
5113 #if defined(S_IFCHR)
5114                 case UNIX_TYPE_CHARDEV:
5115                         unixmode |= S_IFCHR;
5116                         break;
5117 #endif
5118 #if defined(S_IFBLK)
5119                 case UNIX_TYPE_BLKDEV:
5120                         unixmode |= S_IFBLK;
5121                         break;
5122 #endif
5123                 default:
5124                         return NT_STATUS_INVALID_PARAMETER;
5125         }
5126
5127         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5128 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5129
5130         /* Ok - do the mknod. */
5131         if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5132                 return map_nt_error_from_unix(errno);
5133         }
5134
5135         /* If any of the other "set" calls fail we
5136          * don't want to end up with a half-constructed mknod.
5137          */
5138
5139         if (lp_inherit_perms(SNUM(conn))) {
5140                 inherit_access_acl(
5141                         conn, parent_dirname(fname),
5142                         fname, unixmode);
5143         }
5144
5145         if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5146                 status = map_nt_error_from_unix(errno);
5147                 SMB_VFS_UNLINK(conn,fname);
5148                 return status;
5149         }
5150         return NT_STATUS_OK;
5151 }
5152
5153 /****************************************************************************
5154  Deal with SMB_SET_FILE_UNIX_BASIC.
5155 ****************************************************************************/
5156
5157 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5158                                         const char *pdata,
5159                                         int total_data,
5160                                         files_struct *fsp,
5161                                         const char *fname,
5162                                         SMB_STRUCT_STAT *psbuf)
5163 {
5164         struct timespec ts[2];
5165         uint32 raw_unixmode;
5166         mode_t unixmode;
5167         SMB_OFF_T size = 0;
5168         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5169         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5170         NTSTATUS status = NT_STATUS_OK;
5171         BOOL delete_on_fail = False;
5172         enum perm_type ptype;
5173
5174         if (total_data < 100) {
5175                 return NT_STATUS_INVALID_PARAMETER;
5176         }
5177
5178         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5179            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5180                 size=IVAL(pdata,0); /* first 8 Bytes are size */
5181 #ifdef LARGE_SMB_OFF_T
5182                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5183 #else /* LARGE_SMB_OFF_T */
5184                 if (IVAL(pdata,4) != 0) {
5185                         /* more than 32 bits? */
5186                         return NT_STATUS_INVALID_PARAMETER;
5187                 }
5188 #endif /* LARGE_SMB_OFF_T */
5189         }
5190
5191         ts[0] = interpret_long_date(pdata+24); /* access_time */
5192         ts[1] = interpret_long_date(pdata+32); /* modification_time */
5193         set_owner = (uid_t)IVAL(pdata,40);
5194         set_grp = (gid_t)IVAL(pdata,48);
5195         raw_unixmode = IVAL(pdata,84);
5196
5197         if (VALID_STAT(*psbuf)) {
5198                 if (S_ISDIR(psbuf->st_mode)) {
5199                         ptype = PERM_EXISTING_DIR;
5200                 } else {
5201                         ptype = PERM_EXISTING_FILE;
5202                 }
5203         } else {
5204                 ptype = PERM_NEW_FILE;
5205         }
5206
5207         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5208         if (!NT_STATUS_IS_OK(status)) {
5209                 return status;
5210         }
5211
5212         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5213 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5214                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5215
5216         if (!VALID_STAT(*psbuf)) {
5217                 /*
5218                  * The only valid use of this is to create character and block
5219                  * devices, and named pipes. This is deprecated (IMHO) and 
5220                  * a new info level should be used for mknod. JRA.
5221                  */
5222
5223                 status = smb_unix_mknod(conn,
5224                                         pdata,
5225                                         total_data,
5226                                         fname,
5227                                         psbuf);
5228                 if (!NT_STATUS_IS_OK(status)) {
5229                         return status;
5230                 }
5231
5232                 /* Ensure we don't try and change anything else. */
5233                 raw_unixmode = SMB_MODE_NO_CHANGE;
5234                 size = get_file_size(*psbuf);
5235                 ts[0] = get_atimespec(psbuf);
5236                 ts[1] = get_mtimespec(psbuf);
5237                 /* 
5238                  * We continue here as we might want to change the 
5239                  * owner uid/gid.
5240                  */
5241                 delete_on_fail = True;
5242         }
5243
5244 #if 1
5245         /* Horrible backwards compatibility hack as an old server bug
5246          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5247          * */
5248
5249         if (!size) {
5250                 size = get_file_size(*psbuf);
5251         }
5252 #endif
5253
5254         /*
5255          * Deal with the UNIX specific mode set.
5256          */
5257
5258         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5259                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5260                         (unsigned int)unixmode, fname ));
5261                 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5262                         return map_nt_error_from_unix(errno);
5263                 }
5264         }
5265
5266         /*
5267          * Deal with the UNIX specific uid set.
5268          */
5269
5270         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5271                 int ret;
5272
5273                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5274                         (unsigned int)set_owner, fname ));
5275
5276                 if (S_ISLNK(psbuf->st_mode)) {
5277                         ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5278                 } else {
5279                         ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5280                 }
5281
5282                 if (ret != 0) {
5283                         status = map_nt_error_from_unix(errno);
5284                         if (delete_on_fail) {
5285                                 SMB_VFS_UNLINK(conn,fname);
5286                         }
5287                         return status;
5288                 }
5289         }
5290
5291         /*
5292          * Deal with the UNIX specific gid set.
5293          */
5294
5295         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5296                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5297                         (unsigned int)set_owner, fname ));
5298                 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5299                         status = map_nt_error_from_unix(errno);
5300                         if (delete_on_fail) {
5301                                 SMB_VFS_UNLINK(conn,fname);
5302                         }
5303                         return status;
5304                 }
5305         }
5306
5307         /* Deal with any size changes. */
5308
5309         status = smb_set_file_size(conn,
5310                                 fsp,
5311                                 fname,
5312                                 psbuf,
5313                                 size);
5314         if (!NT_STATUS_IS_OK(status)) {
5315                 return status;
5316         }
5317
5318         /* Deal with any time changes. */
5319
5320         return smb_set_file_time(conn,
5321                                 fsp,
5322                                 fname,
5323                                 psbuf,
5324                                 ts);
5325 }
5326
5327 /****************************************************************************
5328  Deal with SMB_SET_FILE_UNIX_INFO2.
5329 ****************************************************************************/
5330
5331 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5332                                         const char *pdata,
5333                                         int total_data,
5334                                         files_struct *fsp,
5335                                         const char *fname,
5336                                         SMB_STRUCT_STAT *psbuf)
5337 {
5338         NTSTATUS status;
5339         uint32 smb_fflags;
5340         uint32 smb_fmask;
5341
5342         if (total_data < 116) {
5343                 return NT_STATUS_INVALID_PARAMETER;
5344         }
5345
5346         /* Start by setting all the fields that are common between UNIX_BASIC
5347          * and UNIX_INFO2.
5348          */
5349         status = smb_set_file_unix_basic(conn, pdata, total_data,
5350                                 fsp, fname, psbuf);
5351         if (!NT_STATUS_IS_OK(status)) {
5352                 return status;
5353         }
5354
5355         smb_fflags = IVAL(pdata, 108);
5356         smb_fmask = IVAL(pdata, 112);
5357
5358         /* NB: We should only attempt to alter the file flags if the client
5359          * sends a non-zero mask.
5360          */
5361         if (smb_fmask != 0) {
5362                 int stat_fflags = 0;
5363
5364                 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5365                             &stat_fflags)) {
5366                         /* Client asked to alter a flag we don't understand. */
5367                         return NT_STATUS_INVALID_PARAMETER;
5368                 }
5369
5370                 if (fsp && fsp->fh->fd != -1) {
5371                         /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
5372                         return NT_STATUS_NOT_SUPPORTED;
5373                 } else {
5374                         if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5375                                 return map_nt_error_from_unix(errno);
5376                         }
5377                 }
5378         }
5379
5380         /* XXX: need to add support for changing the create_time here. You
5381          * can do this for paths on Darwin with setattrlist(2). The right way
5382          * to hook this up is probably by extending the VFS utimes interface.
5383          */
5384
5385         return NT_STATUS_OK;
5386 }
5387
5388 /****************************************************************************
5389  Create a directory with POSIX semantics.
5390 ****************************************************************************/
5391
5392 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5393                                 char **ppdata,
5394                                 int total_data,
5395                                 const char *fname,
5396                                 SMB_STRUCT_STAT *psbuf,
5397                                 int *pdata_return_size)
5398 {
5399         NTSTATUS status = NT_STATUS_OK;
5400         uint32 raw_unixmode = 0;
5401         uint32 mod_unixmode = 0;
5402         mode_t unixmode = (mode_t)0;
5403         files_struct *fsp = NULL;
5404         uint16 info_level_return = 0;
5405         int info;
5406         char *pdata = *ppdata;
5407
5408         if (total_data < 18) {
5409                 return NT_STATUS_INVALID_PARAMETER;
5410         }
5411
5412         raw_unixmode = IVAL(pdata,8);
5413         /* Next 4 bytes are not yet defined. */
5414
5415         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5416         if (!NT_STATUS_IS_OK(status)) {
5417                 return status;
5418         }
5419
5420         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5421
5422         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5423                 fname, (unsigned int)unixmode ));
5424
5425         status = open_directory(conn,
5426                                 fname,
5427                                 psbuf,
5428                                 FILE_READ_ATTRIBUTES, /* Just a stat open */
5429                                 FILE_SHARE_NONE, /* Ignored for stat opens */
5430                                 FILE_CREATE,
5431                                 0,
5432                                 mod_unixmode,
5433                                 &info,
5434                                 &fsp);
5435
5436         if (NT_STATUS_IS_OK(status)) {
5437                 close_file(fsp, NORMAL_CLOSE);
5438         }
5439
5440         info_level_return = SVAL(pdata,16);
5441  
5442         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5443                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5444         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5445                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5446         } else {
5447                 *pdata_return_size = 12;
5448         }
5449
5450         /* Realloc the data size */
5451         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5452         if (*ppdata == NULL) {
5453                 *pdata_return_size = 0;
5454                 return NT_STATUS_NO_MEMORY;
5455         }
5456         pdata = *ppdata;
5457
5458         SSVAL(pdata,0,NO_OPLOCK_RETURN);
5459         SSVAL(pdata,2,0); /* No fnum. */
5460         SIVAL(pdata,4,info); /* Was directory created. */
5461
5462         switch (info_level_return) {
5463                 case SMB_QUERY_FILE_UNIX_BASIC:
5464                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5465                         SSVAL(pdata,10,0); /* Padding. */
5466                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5467                         break;
5468                 case SMB_QUERY_FILE_UNIX_INFO2:
5469                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5470                         SSVAL(pdata,10,0); /* Padding. */
5471                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5472                         break;
5473                 default:
5474                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5475                         SSVAL(pdata,10,0); /* Padding. */
5476                         break;
5477         }
5478
5479         return status;
5480 }
5481
5482 /****************************************************************************
5483  Open/Create a file with POSIX semantics.
5484 ****************************************************************************/
5485
5486 static NTSTATUS smb_posix_open(connection_struct *conn,
5487                                 char **ppdata,
5488                                 int total_data,
5489                                 const char *fname,
5490                                 SMB_STRUCT_STAT *psbuf,
5491                                 int *pdata_return_size)
5492 {
5493         BOOL extended_oplock_granted = False;
5494         char *pdata = *ppdata;
5495         uint32 flags = 0;
5496         uint32 wire_open_mode = 0;
5497         uint32 raw_unixmode = 0;
5498         uint32 mod_unixmode = 0;
5499         uint32 create_disp = 0;
5500         uint32 access_mask = 0;
5501         uint32 create_options = 0;
5502         NTSTATUS status = NT_STATUS_OK;
5503         mode_t unixmode = (mode_t)0;
5504         files_struct *fsp = NULL;
5505         int oplock_request = 0;
5506         int info = 0;
5507         uint16 info_level_return = 0;
5508
5509         if (total_data < 18) {
5510                 return NT_STATUS_INVALID_PARAMETER;
5511         }
5512
5513         flags = IVAL(pdata,0);
5514         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5515         if (oplock_request) {
5516                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5517         }
5518
5519         wire_open_mode = IVAL(pdata,4);
5520
5521         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5522                 return smb_posix_mkdir(conn,
5523                                         ppdata,
5524                                         total_data,
5525                                         fname,
5526                                         psbuf,
5527                                         pdata_return_size);
5528         }
5529
5530         switch (wire_open_mode & SMB_ACCMODE) {
5531                 case SMB_O_RDONLY:
5532                         access_mask = FILE_READ_DATA;
5533                         break;
5534                 case SMB_O_WRONLY:
5535                         access_mask = FILE_WRITE_DATA;
5536                         break;
5537                 case SMB_O_RDWR:
5538                         access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5539                         break;
5540                 default:
5541                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5542                                 (unsigned int)wire_open_mode ));
5543                         return NT_STATUS_INVALID_PARAMETER;
5544         }
5545
5546         wire_open_mode &= ~SMB_ACCMODE;
5547
5548         if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5549                 create_disp = FILE_CREATE;
5550         } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5551                 create_disp = FILE_OVERWRITE_IF;
5552         } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5553                 create_disp = FILE_OPEN_IF;
5554         } else {
5555                 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5556                         (unsigned int)wire_open_mode ));
5557                 return NT_STATUS_INVALID_PARAMETER;
5558         }
5559
5560         raw_unixmode = IVAL(pdata,8);
5561         /* Next 4 bytes are not yet defined. */
5562
5563         status = unix_perms_from_wire(conn,
5564                                 psbuf,
5565                                 raw_unixmode,
5566                                 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5567                                 &unixmode);
5568
5569         if (!NT_STATUS_IS_OK(status)) {
5570                 return status;
5571         }
5572
5573         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5574
5575         if (wire_open_mode & SMB_O_SYNC) {
5576                 create_options |= FILE_WRITE_THROUGH;
5577         }
5578         if (wire_open_mode & SMB_O_APPEND) {
5579                 access_mask |= FILE_APPEND_DATA;
5580         }
5581         if (wire_open_mode & SMB_O_DIRECT) {
5582                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5583         }
5584
5585         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5586                 fname,
5587                 (unsigned int)wire_open_mode,
5588                 (unsigned int)unixmode ));
5589
5590         status = open_file_ntcreate(conn,
5591                                 fname,
5592                                 psbuf,
5593                                 access_mask,
5594                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5595                                 create_disp,
5596                                 0,              /* no create options yet. */
5597                                 mod_unixmode,
5598                                 oplock_request,
5599                                 &info,
5600                                 &fsp);
5601
5602         if (!NT_STATUS_IS_OK(status)) {
5603                 return status;
5604         }
5605
5606         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5607                 extended_oplock_granted = True;
5608         }
5609
5610         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5611                 extended_oplock_granted = True;
5612         }
5613
5614         info_level_return = SVAL(pdata,16);
5615  
5616         /* Allocate the correct return size. */
5617
5618         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5619                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5620         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5621                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5622         } else {
5623                 *pdata_return_size = 12;
5624         }
5625
5626         /* Realloc the data size */
5627         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5628         if (*ppdata == NULL) {
5629                 close_file(fsp,ERROR_CLOSE);
5630                 *pdata_return_size = 0;
5631                 return NT_STATUS_NO_MEMORY;
5632         }
5633         pdata = *ppdata;
5634
5635         if (extended_oplock_granted) {
5636                 if (flags & REQUEST_BATCH_OPLOCK) {
5637                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5638                 } else {
5639                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5640                 }
5641         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5642                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5643         } else {
5644                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5645         }
5646
5647         SSVAL(pdata,2,fsp->fnum);
5648         SIVAL(pdata,4,info); /* Was file created etc. */
5649
5650         switch (info_level_return) {
5651                 case SMB_QUERY_FILE_UNIX_BASIC:
5652                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5653                         SSVAL(pdata,10,0); /* padding. */
5654                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5655                         break;
5656                 case SMB_QUERY_FILE_UNIX_INFO2:
5657                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5658                         SSVAL(pdata,10,0); /* padding. */
5659                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5660                         break;
5661                 default:
5662                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5663                         SSVAL(pdata,10,0); /* padding. */
5664                         break;
5665         }
5666         return NT_STATUS_OK;
5667 }
5668
5669 /****************************************************************************
5670  Delete a file with POSIX semantics.
5671 ****************************************************************************/
5672
5673 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5674                                 const char *pdata,
5675                                 int total_data,
5676                                 const char *fname,
5677                                 SMB_STRUCT_STAT *psbuf)
5678 {
5679         NTSTATUS status = NT_STATUS_OK;
5680         files_struct *fsp = NULL;
5681         uint16 flags = 0;
5682         int info = 0;
5683
5684         if (total_data < 2) {
5685                 return NT_STATUS_INVALID_PARAMETER;
5686         }
5687
5688         flags = SVAL(pdata,0);
5689
5690         if (!VALID_STAT(*psbuf)) {
5691                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5692         }
5693
5694         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5695                         !VALID_STAT_OF_DIR(*psbuf)) {
5696                 return NT_STATUS_NOT_A_DIRECTORY;
5697         }
5698
5699         DEBUG(10,("smb_posix_unlink: %s %s\n",
5700                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5701                 fname));
5702
5703         if (VALID_STAT_OF_DIR(*psbuf)) {
5704                 status = open_directory(conn,
5705                                         fname,
5706                                         psbuf,
5707                                         DELETE_ACCESS,
5708                                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5709                                         FILE_OPEN,
5710                                         FILE_DELETE_ON_CLOSE,
5711                                         FILE_FLAG_POSIX_SEMANTICS|0777,
5712                                         &info,                          
5713                                         &fsp);
5714         } else {
5715                 char del = 1;
5716
5717                 status = open_file_ntcreate(conn,
5718                                 fname,
5719                                 psbuf,
5720                                 DELETE_ACCESS,
5721                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5722                                 FILE_OPEN,
5723                                 0,
5724                                 FILE_FLAG_POSIX_SEMANTICS|0777,
5725                                 0, /* No oplock, but break existing ones. */
5726                                 &info,
5727                                 &fsp);
5728                 /* 
5729                  * For file opens we must set the delete on close
5730                  * after the open.
5731                  */
5732
5733                 if (!NT_STATUS_IS_OK(status)) {
5734                         return status;
5735                 }
5736
5737                 status = smb_set_file_disposition_info(conn,
5738                                                         &del,
5739                                                         1,
5740                                                         fsp,
5741                                                         fname,
5742                                                         psbuf);
5743         }
5744
5745         if (!NT_STATUS_IS_OK(status)) {
5746                 return status;
5747         }
5748         return close_file(fsp, NORMAL_CLOSE);
5749 }
5750
5751 /****************************************************************************
5752  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5753 ****************************************************************************/
5754
5755 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5756                                         unsigned int tran_call,
5757                                         char **pparams, int total_params, char **ppdata, int total_data,
5758                                         unsigned int max_data_bytes)
5759 {
5760         char *params = *pparams;
5761         char *pdata = *ppdata;
5762         uint16 info_level;
5763         SMB_STRUCT_STAT sbuf;
5764         pstring fname;
5765         files_struct *fsp = NULL;
5766         NTSTATUS status = NT_STATUS_OK;
5767         int data_return_size = 0;
5768
5769         if (!params) {
5770                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5771         }
5772
5773         ZERO_STRUCT(sbuf);
5774
5775         if (tran_call == TRANSACT2_SETFILEINFO) {
5776                 if (total_params < 4) {
5777                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5778                 }
5779
5780                 fsp = file_fsp(params,0);
5781                 info_level = SVAL(params,2);    
5782
5783                 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5784                         /*
5785                          * This is actually a SETFILEINFO on a directory
5786                          * handle (returned from an NT SMB). NT5.0 seems
5787                          * to do this call. JRA.
5788                          */
5789                         pstrcpy(fname, fsp->fsp_name);
5790                         if (INFO_LEVEL_IS_UNIX(info_level)) {
5791                                 /* Always do lstat for UNIX calls. */
5792                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5793                                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5794                                         return UNIXERROR(ERRDOS,ERRbadpath);
5795                                 }
5796                         } else {
5797                                 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5798                                         DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5799                                         return UNIXERROR(ERRDOS,ERRbadpath);
5800                                 }
5801                         }
5802                 } else if (fsp && fsp->print_file) {
5803                         /*
5804                          * Doing a DELETE_ON_CLOSE should cancel a print job.
5805                          */
5806                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5807                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5808
5809                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5810         
5811                                 SSVAL(params,0,0);
5812                                 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5813                                 return(-1);
5814                         } else
5815                                 return (UNIXERROR(ERRDOS,ERRbadpath));
5816             } else {
5817                         /*
5818                          * Original code - this is an open file.
5819                          */
5820                         CHECK_FSP(fsp,conn);
5821
5822                         pstrcpy(fname, fsp->fsp_name);
5823
5824                         if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5825                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5826                                 return(UNIXERROR(ERRDOS,ERRbadfid));
5827                         }
5828                 }
5829         } else {
5830                 /* set path info */
5831                 if (total_params < 7) {
5832                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5833                 }
5834
5835                 info_level = SVAL(params,0);    
5836                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
5837                 if (!NT_STATUS_IS_OK(status)) {
5838                         return ERROR_NT(status);
5839                 }
5840
5841                 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5842                 if (!NT_STATUS_IS_OK(status)) {
5843                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5844                                 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5845                         }
5846                         return ERROR_NT(status);
5847                 }
5848
5849                 status = unix_convert(conn, fname, False, NULL, &sbuf);
5850                 if (!NT_STATUS_IS_OK(status)) {
5851                         return ERROR_NT(status);
5852                 }
5853
5854                 status = check_name(conn, fname);
5855                 if (!NT_STATUS_IS_OK(status)) {
5856                         return ERROR_NT(status);
5857                 }
5858
5859                 if (INFO_LEVEL_IS_UNIX(info_level)) {
5860                         /*
5861                          * For CIFS UNIX extensions the target name may not exist.
5862                          */
5863
5864                         /* Always do lstat for UNIX calls. */
5865                         SMB_VFS_LSTAT(conn,fname,&sbuf);
5866
5867                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5868                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5869                         return UNIXERROR(ERRDOS,ERRbadpath);
5870                 }
5871         }
5872
5873         if (!CAN_WRITE(conn)) {
5874                 return ERROR_DOS(ERRSRV,ERRaccess);
5875         }
5876
5877         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5878                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5879         }
5880
5881         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5882                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5883
5884         /* Realloc the parameter size */
5885         *pparams = (char *)SMB_REALLOC(*pparams,2);
5886         if (*pparams == NULL) {
5887                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5888         }
5889         params = *pparams;
5890
5891         SSVAL(params,0,0);
5892
5893         if (fsp && !null_timespec(fsp->pending_modtime)) {
5894                 /* the pending modtime overrides the current modtime */
5895                 set_mtimespec(&sbuf, fsp->pending_modtime);
5896         }
5897
5898         switch (info_level) {
5899
5900                 case SMB_INFO_STANDARD:
5901                 {
5902                         status = smb_set_info_standard(conn,
5903                                         pdata,
5904                                         total_data,
5905                                         fsp,
5906                                         fname,
5907                                         &sbuf);
5908                         break;
5909                 }
5910
5911                 case SMB_INFO_SET_EA:
5912                 {
5913                         status = smb_info_set_ea(conn,
5914                                                 pdata,
5915                                                 total_data,
5916                                                 fsp,
5917                                                 fname);
5918                         break;
5919                 }
5920
5921                 case SMB_SET_FILE_BASIC_INFO:
5922                 case SMB_FILE_BASIC_INFORMATION:
5923                 {
5924                         status = smb_set_file_basic_info(conn,
5925                                                         pdata,
5926                                                         total_data,
5927                                                         fsp,
5928                                                         fname,
5929                                                         &sbuf);
5930                         break;
5931                 }
5932
5933                 case SMB_FILE_ALLOCATION_INFORMATION:
5934                 case SMB_SET_FILE_ALLOCATION_INFO:
5935                 {
5936                         status = smb_set_file_allocation_info(conn,
5937                                                                 pdata,
5938                                                                 total_data,
5939                                                                 fsp,
5940                                                                 fname,
5941                                                                 &sbuf);
5942                         break;
5943                 }
5944
5945                 case SMB_FILE_END_OF_FILE_INFORMATION:
5946                 case SMB_SET_FILE_END_OF_FILE_INFO:
5947                 {
5948                         status = smb_set_file_end_of_file_info(conn,
5949                                                                 pdata,
5950                                                                 total_data,
5951                                                                 fsp,
5952                                                                 fname,
5953                                                                 &sbuf);
5954                         break;
5955                 }
5956
5957                 case SMB_FILE_DISPOSITION_INFORMATION:
5958                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5959                 {
5960 #if 0
5961                         /* JRA - We used to just ignore this on a path ? 
5962                          * Shouldn't this be invalid level on a pathname
5963                          * based call ?
5964                          */
5965                         if (tran_call != TRANSACT2_SETFILEINFO) {
5966                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5967                         }
5968 #endif
5969                         status = smb_set_file_disposition_info(conn,
5970                                                 pdata,
5971                                                 total_data,
5972                                                 fsp,
5973                                                 fname,
5974                                                 &sbuf);
5975                         break;
5976                 }
5977
5978                 case SMB_FILE_POSITION_INFORMATION:
5979                 {
5980                         status = smb_file_position_information(conn,
5981                                                 pdata,
5982                                                 total_data,
5983                                                 fsp);
5984                         break;
5985                 }
5986
5987                 /* From tridge Samba4 : 
5988                  * MODE_INFORMATION in setfileinfo (I have no
5989                  * idea what "mode information" on a file is - it takes a value of 0,
5990                  * 2, 4 or 6. What could it be?).
5991                  */
5992
5993                 case SMB_FILE_MODE_INFORMATION:
5994                 {
5995                         status = smb_file_mode_information(conn,
5996                                                 pdata,
5997                                                 total_data);
5998                         break;
5999                 }
6000
6001                 /*
6002                  * CIFS UNIX extensions.
6003                  */
6004
6005                 case SMB_SET_FILE_UNIX_BASIC:
6006                 {
6007                         status = smb_set_file_unix_basic(conn,
6008                                                         pdata,
6009                                                         total_data,
6010                                                         fsp,
6011                                                         fname,
6012                                                         &sbuf);
6013                         break;
6014                 }
6015
6016                 case SMB_SET_FILE_UNIX_INFO2:
6017                 {
6018                         status = smb_set_file_unix_info2(conn,
6019                                                         pdata,
6020                                                         total_data,
6021                                                         fsp,
6022                                                         fname,
6023                                                         &sbuf);
6024                         break;
6025                 }
6026
6027                 case SMB_SET_FILE_UNIX_LINK:
6028                 {
6029                         if (tran_call != TRANSACT2_SETPATHINFO) {
6030                                 /* We must have a pathname for this. */
6031                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6032                         }
6033                         status = smb_set_file_unix_link(conn,
6034                                                 inbuf,
6035                                                 pdata,
6036                                                 total_data,
6037                                                 fname);
6038                         break;
6039                 }
6040
6041                 case SMB_SET_FILE_UNIX_HLINK:
6042                 {
6043                         if (tran_call != TRANSACT2_SETPATHINFO) {
6044                                 /* We must have a pathname for this. */
6045                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6046                         }
6047                         status = smb_set_file_unix_hlink(conn,
6048                                                 inbuf,
6049                                                 outbuf,
6050                                                 pdata,
6051                                                 total_data,
6052                                                 fname);
6053                         break;
6054                 }
6055
6056                 case SMB_FILE_RENAME_INFORMATION:
6057                 {
6058                         status = smb_file_rename_information(conn,
6059                                                         inbuf,
6060                                                         outbuf,
6061                                                         pdata,
6062                                                         total_data,
6063                                                         fsp,
6064                                                         fname);
6065                         break;
6066                 }
6067
6068 #if defined(HAVE_POSIX_ACLS)
6069                 case SMB_SET_POSIX_ACL:
6070                 {
6071                         status = smb_set_posix_acl(conn,
6072                                                 pdata,
6073                                                 total_data,
6074                                                 fsp,
6075                                                 fname,
6076                                                 &sbuf);
6077                         break;
6078                 }
6079 #endif
6080
6081                 case SMB_SET_POSIX_LOCK:
6082                 {
6083                         if (tran_call != TRANSACT2_SETFILEINFO) {
6084                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6085                         }
6086                         status = smb_set_posix_lock(conn,
6087                                                 inbuf,
6088                                                 length,
6089                                                 pdata,
6090                                                 total_data,
6091                                                 fsp);
6092                         break;
6093                 }
6094
6095                 case SMB_POSIX_PATH_OPEN:
6096                 {
6097                         if (tran_call != TRANSACT2_SETPATHINFO) {
6098                                 /* We must have a pathname for this. */
6099                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6100                         }
6101
6102                         status = smb_posix_open(conn,
6103                                                 ppdata,
6104                                                 total_data,
6105                                                 fname,
6106                                                 &sbuf,
6107                                                 &data_return_size);
6108                         break;
6109                 }
6110
6111                 case SMB_POSIX_PATH_UNLINK:
6112                 {
6113                         if (tran_call != TRANSACT2_SETPATHINFO) {
6114                                 /* We must have a pathname for this. */
6115                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6116                         }
6117
6118                         status = smb_posix_unlink(conn,
6119                                                 pdata,
6120                                                 total_data,
6121                                                 fname,
6122                                                 &sbuf);
6123                         break;
6124                 }
6125
6126                 default:
6127                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6128         }
6129
6130         
6131         if (!NT_STATUS_IS_OK(status)) {
6132                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6133                         /* We have re-scheduled this call. */
6134                         return -1;
6135                 }
6136                 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6137                         /* We have re-scheduled this call. */
6138                         return -1;
6139                 }
6140                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6141                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6142                 }
6143                 return ERROR_NT(status);
6144         }
6145
6146         SSVAL(params,0,0);
6147         send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6148   
6149         return -1;
6150 }
6151
6152 /****************************************************************************
6153  Reply to a TRANS2_MKDIR (make directory with extended attributes).
6154 ****************************************************************************/
6155
6156 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6157                                         char **pparams, int total_params, char **ppdata, int total_data,
6158                                         unsigned int max_data_bytes)
6159 {
6160         char *params = *pparams;
6161         char *pdata = *ppdata;
6162         pstring directory;
6163         SMB_STRUCT_STAT sbuf;
6164         NTSTATUS status = NT_STATUS_OK;
6165         struct ea_list *ea_list = NULL;
6166
6167         if (!CAN_WRITE(conn))
6168                 return ERROR_DOS(ERRSRV,ERRaccess);
6169
6170         if (total_params < 5) {
6171                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6172         }
6173
6174         srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
6175         if (!NT_STATUS_IS_OK(status)) {
6176                 return ERROR_NT(status);
6177         }
6178
6179         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6180
6181         status = unix_convert(conn, directory, False, NULL, &sbuf);
6182         if (!NT_STATUS_IS_OK(status)) {
6183                 return ERROR_NT(status);
6184         }
6185
6186         status = check_name(conn, directory);
6187         if (!NT_STATUS_IS_OK(status)) {
6188                 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6189                 return ERROR_NT(status);
6190         }
6191
6192         /* Any data in this call is an EA list. */
6193         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6194                 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6195         }
6196
6197         /*
6198          * OS/2 workplace shell seems to send SET_EA requests of "null"
6199          * length (4 bytes containing IVAL 4).
6200          * They seem to have no effect. Bug #3212. JRA.
6201          */
6202
6203         if (total_data != 4) {
6204                 if (total_data < 10) {
6205                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6206                 }
6207
6208                 if (IVAL(pdata,0) > total_data) {
6209                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6210                                 IVAL(pdata,0), (unsigned int)total_data));
6211                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6212                 }
6213
6214                 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6215                                        total_data - 4);
6216                 if (!ea_list) {
6217                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6218                 }
6219         } else if (IVAL(pdata,0) != 4) {
6220                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6221         }
6222
6223         status = create_directory(conn, directory);
6224
6225         if (!NT_STATUS_IS_OK(status)) {
6226                 return ERROR_NT(status);
6227         }
6228   
6229         /* Try and set any given EA. */
6230         if (ea_list) {
6231                 status = set_ea(conn, NULL, directory, ea_list);
6232                 if (!NT_STATUS_IS_OK(status)) {
6233                         return ERROR_NT(status);
6234                 }
6235         }
6236
6237         /* Realloc the parameter and data sizes */
6238         *pparams = (char *)SMB_REALLOC(*pparams,2);
6239         if(*pparams == NULL) {
6240                 return ERROR_NT(NT_STATUS_NO_MEMORY);
6241         }
6242         params = *pparams;
6243
6244         SSVAL(params,0,0);
6245
6246         send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6247   
6248         return(-1);
6249 }
6250
6251 /****************************************************************************
6252  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6253  We don't actually do this - we just send a null response.
6254 ****************************************************************************/
6255
6256 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6257                                         char **pparams, int total_params, char **ppdata, int total_data,
6258                                         unsigned int max_data_bytes)
6259 {
6260         static uint16 fnf_handle = 257;
6261         char *params = *pparams;
6262         uint16 info_level;
6263
6264         if (total_params < 6) {
6265                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6266         }
6267
6268         info_level = SVAL(params,4);
6269         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6270
6271         switch (info_level) {
6272                 case 1:
6273                 case 2:
6274                         break;
6275                 default:
6276                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6277         }
6278
6279         /* Realloc the parameter and data sizes */
6280         *pparams = (char *)SMB_REALLOC(*pparams,6);
6281         if (*pparams == NULL) {
6282                 return ERROR_NT(NT_STATUS_NO_MEMORY);
6283         }
6284         params = *pparams;
6285
6286         SSVAL(params,0,fnf_handle);
6287         SSVAL(params,2,0); /* No changes */
6288         SSVAL(params,4,0); /* No EA errors */
6289
6290         fnf_handle++;
6291
6292         if(fnf_handle == 0)
6293                 fnf_handle = 257;
6294
6295         send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6296   
6297         return(-1);
6298 }
6299
6300 /****************************************************************************
6301  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
6302  changes). Currently this does nothing.
6303 ****************************************************************************/
6304
6305 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6306                                         char **pparams, int total_params, char **ppdata, int total_data,
6307                                         unsigned int max_data_bytes)
6308 {
6309         char *params = *pparams;
6310
6311         DEBUG(3,("call_trans2findnotifynext\n"));
6312
6313         /* Realloc the parameter and data sizes */
6314         *pparams = (char *)SMB_REALLOC(*pparams,4);
6315         if (*pparams == NULL) {
6316                 return ERROR_NT(NT_STATUS_NO_MEMORY);
6317         }
6318         params = *pparams;
6319
6320         SSVAL(params,0,0); /* No changes */
6321         SSVAL(params,2,0); /* No EA errors */
6322
6323         send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6324   
6325         return(-1);
6326 }
6327
6328 /****************************************************************************
6329  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6330 ****************************************************************************/
6331
6332 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6333                                         char **pparams, int total_params, char **ppdata, int total_data,
6334                                         unsigned int max_data_bytes)
6335 {
6336         char *params = *pparams;
6337         pstring pathname;
6338         int reply_size = 0;
6339         int max_referral_level;
6340         NTSTATUS status = NT_STATUS_OK;
6341
6342         DEBUG(10,("call_trans2getdfsreferral\n"));
6343
6344         if (total_params < 3) {
6345                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6346         }
6347
6348         max_referral_level = SVAL(params,0);
6349
6350         if(!lp_host_msdfs())
6351                 return ERROR_DOS(ERRDOS,ERRbadfunc);
6352
6353         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
6354         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6355                 return ERROR_NT(status);
6356     
6357         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6358         send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6359
6360         return(-1);
6361 }
6362
6363 #define LMCAT_SPL       0x53
6364 #define LMFUNC_GETJOBID 0x60
6365
6366 /****************************************************************************
6367  Reply to a TRANS2_IOCTL - used for OS/2 printing.
6368 ****************************************************************************/
6369
6370 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6371                                         char **pparams, int total_params, char **ppdata, int total_data,
6372                                         unsigned int max_data_bytes)
6373 {
6374         char *pdata = *ppdata;
6375         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
6376
6377         /* check for an invalid fid before proceeding */
6378         
6379         if (!fsp)                                
6380                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
6381
6382         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6383                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6384                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6385                 if (*ppdata == NULL) {
6386                         return ERROR_NT(NT_STATUS_NO_MEMORY);
6387                 }
6388                 pdata = *ppdata;
6389
6390                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6391                         CAN ACCEPT THIS IN UNICODE. JRA. */
6392
6393                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
6394                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6395                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6396                 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6397                 return(-1);
6398         } else {
6399                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6400                 return ERROR_DOS(ERRSRV,ERRerror);
6401         }
6402 }
6403
6404 /****************************************************************************
6405  Reply to a SMBfindclose (stop trans2 directory search).
6406 ****************************************************************************/
6407
6408 int reply_findclose(connection_struct *conn,
6409                     char *inbuf,char *outbuf,int length,int bufsize)
6410 {
6411         int outsize = 0;
6412         int dptr_num=SVALS(inbuf,smb_vwv0);
6413         START_PROFILE(SMBfindclose);
6414
6415         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6416
6417         dptr_close(&dptr_num);
6418
6419         outsize = set_message(inbuf, outbuf,0,0,False);
6420
6421         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6422
6423         END_PROFILE(SMBfindclose);
6424         return(outsize);
6425 }
6426
6427 /****************************************************************************
6428  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6429 ****************************************************************************/
6430
6431 int reply_findnclose(connection_struct *conn, 
6432                      char *inbuf,char *outbuf,int length,int bufsize)
6433 {
6434         int outsize = 0;
6435         int dptr_num= -1;
6436         START_PROFILE(SMBfindnclose);
6437         
6438         dptr_num = SVAL(inbuf,smb_vwv0);
6439
6440         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6441
6442         /* We never give out valid handles for a 
6443            findnotifyfirst - so any dptr_num is ok here. 
6444            Just ignore it. */
6445
6446         outsize = set_message(inbuf, outbuf,0,0,False);
6447
6448         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6449
6450         END_PROFILE(SMBfindnclose);
6451         return(outsize);
6452 }
6453
6454 int handle_trans2(connection_struct *conn,
6455                   struct trans_state *state,
6456                   char *inbuf, char *outbuf, int size, int bufsize)
6457 {
6458         int outsize;
6459
6460         if (Protocol >= PROTOCOL_NT1) {
6461                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6462         }
6463
6464         /* Now we must call the relevant TRANS2 function */
6465         switch(state->call)  {
6466         case TRANSACT2_OPEN:
6467         {
6468                 START_PROFILE(Trans2_open);
6469                 outsize = call_trans2open(
6470                         conn, inbuf, outbuf, bufsize, 
6471                         &state->param, state->total_param,
6472                         &state->data, state->total_data,
6473                         state->max_data_return);
6474                 END_PROFILE(Trans2_open);
6475                 break;
6476         }
6477
6478         case TRANSACT2_FINDFIRST:
6479         {
6480                 START_PROFILE(Trans2_findfirst);
6481                 outsize = call_trans2findfirst(
6482                         conn, inbuf, outbuf, bufsize,
6483                         &state->param, state->total_param,
6484                         &state->data, state->total_data,
6485                         state->max_data_return);
6486                 END_PROFILE(Trans2_findfirst);
6487                 break;
6488         }
6489
6490         case TRANSACT2_FINDNEXT:
6491         {
6492                 START_PROFILE(Trans2_findnext);
6493                 outsize = call_trans2findnext(
6494                         conn, inbuf, outbuf, size, bufsize, 
6495                         &state->param, state->total_param,
6496                         &state->data, state->total_data,
6497                         state->max_data_return);
6498                 END_PROFILE(Trans2_findnext);
6499                 break;
6500         }
6501
6502         case TRANSACT2_QFSINFO:
6503         {
6504                 START_PROFILE(Trans2_qfsinfo);
6505                 outsize = call_trans2qfsinfo(
6506                         conn, inbuf, outbuf, size, bufsize,
6507                         &state->param, state->total_param,
6508                         &state->data, state->total_data,
6509                         state->max_data_return);
6510                 END_PROFILE(Trans2_qfsinfo);
6511             break;
6512         }
6513
6514         case TRANSACT2_SETFSINFO:
6515         {
6516                 START_PROFILE(Trans2_setfsinfo);
6517                 outsize = call_trans2setfsinfo(
6518                         conn, inbuf, outbuf, size, bufsize, 
6519                         &state->param, state->total_param,
6520                         &state->data, state->total_data,
6521                         state->max_data_return);
6522                 END_PROFILE(Trans2_setfsinfo);
6523                 break;
6524         }
6525
6526         case TRANSACT2_QPATHINFO:
6527         case TRANSACT2_QFILEINFO:
6528         {
6529                 START_PROFILE(Trans2_qpathinfo);
6530                 outsize = call_trans2qfilepathinfo(
6531                         conn, inbuf, outbuf, size, bufsize, state->call,
6532                         &state->param, state->total_param,
6533                         &state->data, state->total_data,
6534                         state->max_data_return);
6535                 END_PROFILE(Trans2_qpathinfo);
6536                 break;
6537         }
6538
6539         case TRANSACT2_SETPATHINFO:
6540         case TRANSACT2_SETFILEINFO:
6541         {
6542                 START_PROFILE(Trans2_setpathinfo);
6543                 outsize = call_trans2setfilepathinfo(
6544                         conn, inbuf, outbuf, size, bufsize, state->call,
6545                         &state->param, state->total_param,
6546                         &state->data, state->total_data,
6547                         state->max_data_return);
6548                 END_PROFILE(Trans2_setpathinfo);
6549                 break;
6550         }
6551
6552         case TRANSACT2_FINDNOTIFYFIRST:
6553         {
6554                 START_PROFILE(Trans2_findnotifyfirst);
6555                 outsize = call_trans2findnotifyfirst(
6556                         conn, inbuf, outbuf, size, bufsize, 
6557                         &state->param, state->total_param,
6558                         &state->data, state->total_data,
6559                         state->max_data_return);
6560                 END_PROFILE(Trans2_findnotifyfirst);
6561                 break;
6562         }
6563
6564         case TRANSACT2_FINDNOTIFYNEXT:
6565         {
6566                 START_PROFILE(Trans2_findnotifynext);
6567                 outsize = call_trans2findnotifynext(
6568                         conn, inbuf, outbuf, size, bufsize, 
6569                         &state->param, state->total_param,
6570                         &state->data, state->total_data,
6571                         state->max_data_return);
6572                 END_PROFILE(Trans2_findnotifynext);
6573                 break;
6574         }
6575
6576         case TRANSACT2_MKDIR:
6577         {
6578                 START_PROFILE(Trans2_mkdir);
6579                 outsize = call_trans2mkdir(
6580                         conn, inbuf, outbuf, size, bufsize,
6581                         &state->param, state->total_param,
6582                         &state->data, state->total_data,
6583                         state->max_data_return);
6584                 END_PROFILE(Trans2_mkdir);
6585                 break;
6586         }
6587
6588         case TRANSACT2_GET_DFS_REFERRAL:
6589         {
6590                 START_PROFILE(Trans2_get_dfs_referral);
6591                 outsize = call_trans2getdfsreferral(
6592                         conn, inbuf, outbuf, size, bufsize,
6593                         &state->param, state->total_param,
6594                         &state->data, state->total_data,
6595                         state->max_data_return);
6596                 END_PROFILE(Trans2_get_dfs_referral);
6597                 break;
6598         }
6599
6600         case TRANSACT2_IOCTL:
6601         {
6602                 START_PROFILE(Trans2_ioctl);
6603                 outsize = call_trans2ioctl(
6604                         conn, inbuf, outbuf, size, bufsize,
6605                         &state->param, state->total_param,
6606                         &state->data, state->total_data,
6607                         state->max_data_return);
6608                 END_PROFILE(Trans2_ioctl);
6609                 break;
6610         }
6611
6612         default:
6613                 /* Error in request */
6614                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6615                 outsize = ERROR_DOS(ERRSRV,ERRerror);
6616         }
6617
6618         return outsize;
6619 }
6620
6621 /****************************************************************************
6622  Reply to a SMBtrans2.
6623  ****************************************************************************/
6624
6625 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6626                  int size, int bufsize)
6627 {
6628         int outsize = 0;
6629         unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6630         unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6631         unsigned int psoff = SVAL(inbuf, smb_psoff);
6632         unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6633         unsigned int tran_call = SVAL(inbuf, smb_setup0);
6634         struct trans_state *state;
6635         NTSTATUS result;
6636
6637         START_PROFILE(SMBtrans2);
6638
6639         result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6640         if (!NT_STATUS_IS_OK(result)) {
6641                 DEBUG(2, ("Got invalid trans2 request: %s\n",
6642                           nt_errstr(result)));
6643                 END_PROFILE(SMBtrans2);
6644                 return ERROR_NT(result);
6645         }
6646
6647         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6648             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
6649             && (tran_call != TRANSACT2_QFILEINFO)) {
6650                 END_PROFILE(SMBtrans2);
6651                 return ERROR_DOS(ERRSRV,ERRaccess);
6652         }
6653
6654         if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6655                 DEBUG(0, ("talloc failed\n"));
6656                 END_PROFILE(SMBtrans2);
6657                 return ERROR_NT(NT_STATUS_NO_MEMORY);
6658         }
6659
6660         state->cmd = SMBtrans2;
6661
6662         state->mid = SVAL(inbuf, smb_mid);
6663         state->vuid = SVAL(inbuf, smb_uid);
6664         state->setup_count = SVAL(inbuf, smb_suwcnt);
6665         state->setup = NULL;
6666         state->total_param = SVAL(inbuf, smb_tpscnt);
6667         state->param = NULL;
6668         state->total_data =  SVAL(inbuf, smb_tdscnt);
6669         state->data = NULL;
6670         state->max_param_return = SVAL(inbuf, smb_mprcnt);
6671         state->max_data_return  = SVAL(inbuf, smb_mdrcnt);
6672         state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6673         state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6674         state->one_way = BITSETW(inbuf+smb_vwv5,1);
6675
6676         state->call = tran_call;
6677
6678         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6679            is so as a sanity check */
6680         if (state->setup_count != 1) {
6681                 /*
6682                  * Need to have rc=0 for ioctl to get job id for OS/2.
6683                  *  Network printing will fail if function is not successful.
6684                  *  Similar function in reply.c will be used if protocol
6685                  *  is LANMAN1.0 instead of LM1.2X002.
6686                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
6687                  *  outbuf doesn't have to be set(only job id is used).
6688                  */
6689                 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6690                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6691                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6692                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6693                 } else {
6694                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6695                         DEBUG(2,("Transaction is %d\n",tran_call));
6696                         TALLOC_FREE(state);
6697                         END_PROFILE(SMBtrans2);
6698                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6699                 }
6700         }
6701
6702         if ((dscnt > state->total_data) || (pscnt > state->total_param))
6703                 goto bad_param;
6704
6705         if (state->total_data) {
6706                 /* Can't use talloc here, the core routines do realloc on the
6707                  * params and data. */
6708                 state->data = (char *)SMB_MALLOC(state->total_data);
6709                 if (state->data == NULL) {
6710                         DEBUG(0,("reply_trans2: data malloc fail for %u "
6711                                  "bytes !\n", (unsigned int)state->total_data));
6712                         TALLOC_FREE(state);
6713                         END_PROFILE(SMBtrans2);
6714                         return(ERROR_DOS(ERRDOS,ERRnomem));
6715                 }
6716                 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6717                         goto bad_param;
6718                 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6719                     (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6720                         goto bad_param;
6721
6722                 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6723         }
6724
6725         if (state->total_param) {
6726                 /* Can't use talloc here, the core routines do realloc on the
6727                  * params and data. */
6728                 state->param = (char *)SMB_MALLOC(state->total_param);
6729                 if (state->param == NULL) {
6730                         DEBUG(0,("reply_trans: param malloc fail for %u "
6731                                  "bytes !\n", (unsigned int)state->total_param));
6732                         SAFE_FREE(state->data);
6733                         TALLOC_FREE(state);
6734                         END_PROFILE(SMBtrans2);
6735                         return(ERROR_DOS(ERRDOS,ERRnomem));
6736                 } 
6737                 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6738                         goto bad_param;
6739                 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6740                     (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6741                         goto bad_param;
6742
6743                 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6744         }
6745
6746         state->received_data  = dscnt;
6747         state->received_param = pscnt;
6748
6749         if ((state->received_param == state->total_param) &&
6750             (state->received_data == state->total_data)) {
6751
6752                 outsize = handle_trans2(conn, state, inbuf, outbuf,
6753                                         size, bufsize);
6754                 SAFE_FREE(state->data);
6755                 SAFE_FREE(state->param);
6756                 TALLOC_FREE(state);
6757                 END_PROFILE(SMBtrans2);
6758                 return outsize;
6759         }
6760
6761         DLIST_ADD(conn->pending_trans, state);
6762
6763         /* We need to send an interim response then receive the rest
6764            of the parameter/data bytes */
6765         outsize = set_message(inbuf, outbuf,0,0,False);
6766         show_msg(outbuf);
6767         END_PROFILE(SMBtrans2);
6768         return outsize;
6769
6770   bad_param:
6771
6772         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6773         SAFE_FREE(state->data);
6774         SAFE_FREE(state->param);
6775         TALLOC_FREE(state);
6776         END_PROFILE(SMBtrans2);
6777         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6778 }
6779
6780
6781 /****************************************************************************
6782  Reply to a SMBtranss2
6783  ****************************************************************************/
6784
6785 int reply_transs2(connection_struct *conn,
6786                   char *inbuf,char *outbuf,int size,int bufsize)
6787 {
6788         int outsize = 0;
6789         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6790         struct trans_state *state;
6791
6792         START_PROFILE(SMBtranss2);
6793
6794         show_msg(inbuf);
6795
6796         for (state = conn->pending_trans; state != NULL;
6797              state = state->next) {
6798                 if (state->mid == SVAL(inbuf,smb_mid)) {
6799                         break;
6800                 }
6801         }
6802
6803         if ((state == NULL) || (state->cmd != SMBtrans2)) {
6804                 END_PROFILE(SMBtranss2);
6805                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6806         }
6807
6808         /* Revise state->total_param and state->total_data in case they have
6809            changed downwards */
6810
6811         if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6812                 state->total_param = SVAL(inbuf, smb_tpscnt);
6813         if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6814                 state->total_data = SVAL(inbuf, smb_tdscnt);
6815
6816         pcnt = SVAL(inbuf, smb_spscnt);
6817         poff = SVAL(inbuf, smb_spsoff);
6818         pdisp = SVAL(inbuf, smb_spsdisp);
6819
6820         dcnt = SVAL(inbuf, smb_sdscnt);
6821         doff = SVAL(inbuf, smb_sdsoff);
6822         ddisp = SVAL(inbuf, smb_sdsdisp);
6823
6824         state->received_param += pcnt;
6825         state->received_data += dcnt;
6826                 
6827         if ((state->received_data > state->total_data) ||
6828             (state->received_param > state->total_param))
6829                 goto bad_param;
6830
6831         if (pcnt) {
6832                 if (pdisp+pcnt > state->total_param)
6833                         goto bad_param;
6834                 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6835                         goto bad_param;
6836                 if (pdisp > state->total_param)
6837                         goto bad_param;
6838                 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6839                     (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6840                         goto bad_param;
6841                 if (state->param + pdisp < state->param)
6842                         goto bad_param;
6843
6844                 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6845                        pcnt);
6846         }
6847
6848         if (dcnt) {
6849                 if (ddisp+dcnt > state->total_data)
6850                         goto bad_param;
6851                 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6852                         goto bad_param;
6853                 if (ddisp > state->total_data)
6854                         goto bad_param;
6855                 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6856                     (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6857                         goto bad_param;
6858                 if (state->data + ddisp < state->data)
6859                         goto bad_param;
6860
6861                 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6862                        dcnt);      
6863         }
6864
6865         if ((state->received_param < state->total_param) ||
6866             (state->received_data < state->total_data)) {
6867                 END_PROFILE(SMBtranss2);
6868                 return -1;
6869         }
6870
6871         /* construct_reply_common has done us the favor to pre-fill the
6872          * command field with SMBtranss2 which is wrong :-)
6873          */
6874         SCVAL(outbuf,smb_com,SMBtrans2);
6875
6876         outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
6877
6878         DLIST_REMOVE(conn->pending_trans, state);
6879         SAFE_FREE(state->data);
6880         SAFE_FREE(state->param);
6881         TALLOC_FREE(state);
6882
6883         if (outsize == 0) {
6884                 END_PROFILE(SMBtranss2);
6885                 return(ERROR_DOS(ERRSRV,ERRnosupport));
6886         }
6887         
6888         END_PROFILE(SMBtranss2);
6889         return(outsize);
6890
6891   bad_param:
6892
6893         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6894         DLIST_REMOVE(conn->pending_trans, state);
6895         SAFE_FREE(state->data);
6896         SAFE_FREE(state->param);
6897         TALLOC_FREE(state);
6898         END_PROFILE(SMBtranss2);
6899         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6900 }