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