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