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