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