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