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