r17347: Some C++ warnings -- 271 left
[ira/wip.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_ARRAY(mem_ctx, char, 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 = (char *)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, char *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 = (char *)SMB_REALLOC(
1755                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
1756         if(*ppdata == NULL ) {
1757                 talloc_destroy(ea_ctx);
1758                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1759         }
1760         pdata = *ppdata;
1761
1762         /* Realloc the params space */
1763         *pparams = (char *)SMB_REALLOC(*pparams, 10);
1764         if (*pparams == NULL) {
1765                 talloc_destroy(ea_ctx);
1766                 return ERROR_NT(NT_STATUS_NO_MEMORY);
1767         }
1768         params = *pparams;
1769
1770         /* Save the wildcard match and attribs we are using on this directory - 
1771                 needed as lanman2 assumes these are being saved between calls */
1772
1773         dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid), mask, mask_contains_wcard, dirtype);
1774         if (dptr_num < 0) {
1775                 talloc_destroy(ea_ctx);
1776                 return(UNIXERROR(ERRDOS,ERRbadfile));
1777         }
1778
1779         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n",dptr_num, mask, dirtype));
1780
1781         /* We don't need to check for VOL here as this is returned by 
1782                 a different TRANS2 call. */
1783   
1784         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
1785         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
1786                 dont_descend = True;
1787     
1788         p = pdata;
1789         space_remaining = max_data_bytes;
1790         out_of_space = False;
1791
1792         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
1793                 BOOL got_exact_match = False;
1794
1795                 /* this is a heuristic to avoid seeking the dirptr except when 
1796                         absolutely necessary. It allows for a filename of about 40 chars */
1797                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
1798                         out_of_space = True;
1799                         finished = False;
1800                 } else {
1801                         finished = !get_lanman2_dir_entry(conn,
1802                                         inbuf, outbuf,
1803                                         mask,dirtype,info_level,
1804                                         requires_resume_key,dont_descend,
1805                                         &p,pdata,space_remaining, &out_of_space, &got_exact_match,
1806                                         &last_entry_off, ea_list, ea_ctx);
1807                 }
1808
1809                 if (finished && out_of_space)
1810                         finished = False;
1811
1812                 if (!finished && !out_of_space)
1813                         numentries++;
1814
1815                 /*
1816                  * As an optimisation if we know we aren't looking
1817                  * for a wildcard name (ie. the name matches the wildcard exactly)
1818                  * then we can finish on any (first) match.
1819                  * This speeds up large directory searches. JRA.
1820                  */
1821
1822                 if(got_exact_match)
1823                         finished = True;
1824
1825                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
1826         }
1827   
1828         talloc_destroy(ea_ctx);
1829
1830         /* Check if we can close the dirptr */
1831         if(close_after_first || (finished && close_if_end)) {
1832                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
1833                 dptr_close(&dptr_num);
1834         }
1835
1836         /* 
1837          * If there are no matching entries we must return ERRDOS/ERRbadfile - 
1838          * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
1839          * the protocol level is less than NT1. Tested with smbclient. JRA.
1840          * This should fix the OS/2 client bug #2335.
1841          */
1842
1843         if(numentries == 0) {
1844                 dptr_close(&dptr_num);
1845                 if (Protocol < PROTOCOL_NT1) {
1846                         return ERROR_DOS(ERRDOS,ERRnofiles);
1847                 } else {
1848                         return ERROR_BOTH(NT_STATUS_NO_SUCH_FILE,ERRDOS,ERRbadfile);
1849                 }
1850         }
1851
1852         /* At this point pdata points to numentries directory entries. */
1853
1854         /* Set up the return parameter block */
1855         SSVAL(params,0,dptr_num);
1856         SSVAL(params,2,numentries);
1857         SSVAL(params,4,finished);
1858         SSVAL(params,6,0); /* Never an EA error */
1859         SSVAL(params,8,last_entry_off);
1860
1861         send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata));
1862
1863         if ((! *directory) && dptr_path(dptr_num))
1864                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
1865
1866         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
1867                 smb_fn_name(CVAL(inbuf,smb_com)), 
1868                 mask, directory, dirtype, numentries ) );
1869
1870         /* 
1871          * Force a name mangle here to ensure that the
1872          * mask as an 8.3 name is top of the mangled cache.
1873          * The reasons for this are subtle. Don't remove
1874          * this code unless you know what you are doing
1875          * (see PR#13758). JRA.
1876          */
1877
1878         if(!mangle_is_8_3_wildcards( mask, False, conn->params))
1879                 mangle_map(mask, True, True, conn->params);
1880
1881         return(-1);
1882 }
1883
1884 /****************************************************************************
1885  Reply to a TRANS2_FINDNEXT.
1886 ****************************************************************************/
1887
1888 static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
1889                                         char **pparams, int total_params, char **ppdata, int total_data,
1890                                         unsigned int max_data_bytes)
1891 {
1892         /* We must be careful here that we don't return more than the
1893                 allowed number of data bytes. If this means returning fewer than
1894                 maxentries then so be it. We assume that the redirector has
1895                 enough room for the fixed number of parameter bytes it has
1896                 requested. */
1897         char *params = *pparams;
1898         char *pdata = *ppdata;
1899         int dptr_num = SVAL(params,0);
1900         int maxentries = SVAL(params,2);
1901         uint16 info_level = SVAL(params,4);
1902         uint32 resume_key = IVAL(params,6);
1903         uint16 findnext_flags = SVAL(params,10);
1904         BOOL close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
1905         BOOL close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1906         BOOL requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1907         BOOL continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
1908         BOOL mask_contains_wcard = False;
1909         pstring resume_name;
1910         pstring mask;
1911         pstring directory;
1912         char *p;
1913         uint16 dirtype;
1914         int numentries = 0;
1915         int i, last_entry_off=0;
1916         BOOL finished = False;
1917         BOOL dont_descend = False;
1918         BOOL out_of_space = False;
1919         int space_remaining;
1920         TALLOC_CTX *ea_ctx = NULL;
1921         struct ea_list *ea_list = NULL;
1922         NTSTATUS ntstatus = NT_STATUS_OK;
1923
1924         if (total_params < 12) {
1925                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1926         }
1927
1928         *mask = *directory = *resume_name = 0;
1929
1930         srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), -1, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1931         if (!NT_STATUS_IS_OK(ntstatus)) {
1932                 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
1933                    complain (it thinks we're asking for the directory above the shared
1934                    path or an invalid name). Catch this as the resume name is only compared, never used in
1935                    a file access. JRA. */
1936                 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
1937                         pstrcpy(resume_name, "..");
1938                 } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
1939                         pstrcpy(resume_name, ".");
1940                 } else {
1941                         return ERROR_NT(ntstatus);
1942                 }
1943         }
1944
1945         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
1946 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
1947 resume_key = %d resume name = %s continue=%d level = %d\n",
1948                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
1949                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
1950
1951         if (!maxentries) {
1952                 /* W2K3 seems to treat zero as 1. */
1953                 maxentries = 1;
1954         }
1955
1956         switch (info_level) {
1957                 case SMB_FIND_INFO_STANDARD:
1958                 case SMB_FIND_EA_SIZE:
1959                 case SMB_FIND_EA_LIST:
1960                 case SMB_FIND_FILE_DIRECTORY_INFO:
1961                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1962                 case SMB_FIND_FILE_NAMES_INFO:
1963                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1964                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1965                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1966                         break;
1967                 case SMB_FIND_FILE_UNIX:
1968                         if (!lp_unix_extensions()) {
1969                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1970                         }
1971                         break;
1972                 default:
1973                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
1974         }
1975
1976         if (info_level == SMB_FIND_EA_LIST) {
1977                 uint32 ea_size;
1978
1979                 if (total_data < 4) {
1980                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1981                 }
1982
1983                 ea_size = IVAL(pdata,0);
1984                 if (ea_size != total_data) {
1985                         DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
1986 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
1987                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
1988                 }
1989                                                                                                                                                      
1990                 if (!lp_ea_support(SNUM(conn))) {
1991                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
1992                 }
1993                                                                                                                                                      
1994                 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
1995                         return ERROR_NT(NT_STATUS_NO_MEMORY);
1996                 }
1997
1998                 /* Pull out the list of names. */
1999                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2000                 if (!ea_list) {
2001                         talloc_destroy(ea_ctx);
2002                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2003                 }
2004         }
2005
2006         *ppdata = (char *)SMB_REALLOC(
2007                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2008         if(*ppdata == NULL) {
2009                 talloc_destroy(ea_ctx);
2010                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2011         }
2012
2013         pdata = *ppdata;
2014
2015         /* Realloc the params space */
2016         *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2017         if(*pparams == NULL ) {
2018                 talloc_destroy(ea_ctx);
2019                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2020         }
2021
2022         params = *pparams;
2023
2024         /* Check that the dptr is valid */
2025         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2026                 talloc_destroy(ea_ctx);
2027                 return ERROR_DOS(ERRDOS,ERRnofiles);
2028         }
2029
2030         string_set(&conn->dirpath,dptr_path(dptr_num));
2031
2032         /* Get the wildcard mask from the dptr */
2033         if((p = dptr_wcard(dptr_num))== NULL) {
2034                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2035                 talloc_destroy(ea_ctx);
2036                 return ERROR_DOS(ERRDOS,ERRnofiles);
2037         }
2038
2039         pstrcpy(mask, p);
2040         pstrcpy(directory,conn->dirpath);
2041
2042         /* Get the attr mask from the dptr */
2043         dirtype = dptr_attr(dptr_num);
2044
2045         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2046                 dptr_num, mask, dirtype, 
2047                 (long)conn->dirptr,
2048                 dptr_TellDir(conn->dirptr)));
2049
2050         /* We don't need to check for VOL here as this is returned by 
2051                 a different TRANS2 call. */
2052
2053         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2054         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2055                 dont_descend = True;
2056     
2057         p = pdata;
2058         space_remaining = max_data_bytes;
2059         out_of_space = False;
2060
2061         /* 
2062          * Seek to the correct position. We no longer use the resume key but
2063          * depend on the last file name instead.
2064          */
2065
2066         if(*resume_name && !continue_bit) {
2067                 SMB_STRUCT_STAT st;
2068
2069                 long current_pos = 0;
2070                 /*
2071                  * Remember, mangle_map is called by
2072                  * get_lanman2_dir_entry(), so the resume name
2073                  * could be mangled. Ensure we check the unmangled name.
2074                  */
2075
2076                 if (mangle_is_mangled(resume_name, conn->params)) {
2077                         mangle_check_cache(resume_name, sizeof(resume_name)-1,
2078                                            conn->params);
2079                 }
2080
2081                 /*
2082                  * Fix for NT redirector problem triggered by resume key indexes
2083                  * changing between directory scans. We now return a resume key of 0
2084                  * and instead look for the filename to continue from (also given
2085                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2086                  * findfirst/findnext (as is usual) then the directory pointer
2087                  * should already be at the correct place.
2088                  */
2089
2090                 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2091         } /* end if resume_name && !continue_bit */
2092
2093         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2094                 BOOL got_exact_match = False;
2095
2096                 /* this is a heuristic to avoid seeking the dirptr except when 
2097                         absolutely necessary. It allows for a filename of about 40 chars */
2098                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2099                         out_of_space = True;
2100                         finished = False;
2101                 } else {
2102                         finished = !get_lanman2_dir_entry(conn,
2103                                                 inbuf, outbuf,
2104                                                 mask,dirtype,info_level,
2105                                                 requires_resume_key,dont_descend,
2106                                                 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2107                                                 &last_entry_off, ea_list, ea_ctx);
2108                 }
2109
2110                 if (finished && out_of_space)
2111                         finished = False;
2112
2113                 if (!finished && !out_of_space)
2114                         numentries++;
2115
2116                 /*
2117                  * As an optimisation if we know we aren't looking
2118                  * for a wildcard name (ie. the name matches the wildcard exactly)
2119                  * then we can finish on any (first) match.
2120                  * This speeds up large directory searches. JRA.
2121                  */
2122
2123                 if(got_exact_match)
2124                         finished = True;
2125
2126                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2127         }
2128   
2129         talloc_destroy(ea_ctx);
2130
2131         /* Check if we can close the dirptr */
2132         if(close_after_request || (finished && close_if_end)) {
2133                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2134                 dptr_close(&dptr_num); /* This frees up the saved mask */
2135         }
2136
2137         /* Set up the return parameter block */
2138         SSVAL(params,0,numentries);
2139         SSVAL(params,2,finished);
2140         SSVAL(params,4,0); /* Never an EA error */
2141         SSVAL(params,6,last_entry_off);
2142
2143         send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata));
2144
2145         if ((! *directory) && dptr_path(dptr_num))
2146                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2147
2148         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2149                 smb_fn_name(CVAL(inbuf,smb_com)), 
2150                 mask, directory, dirtype, numentries ) );
2151
2152         return(-1);
2153 }
2154
2155 /****************************************************************************
2156  Reply to a TRANS2_QFSINFO (query filesystem info).
2157 ****************************************************************************/
2158
2159 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2160                                         char **pparams, int total_params, char **ppdata, int total_data,
2161                                         unsigned int max_data_bytes)
2162 {
2163         char *pdata = *ppdata;
2164         char *params = *pparams;
2165         uint16 info_level = SVAL(params,0);
2166         int data_len, len;
2167         SMB_STRUCT_STAT st;
2168         char *vname = volume_label(SNUM(conn));
2169         int snum = SNUM(conn);
2170         char *fstype = lp_fstype(SNUM(conn));
2171         int quota_flag = 0;
2172
2173         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2174
2175         if(SMB_VFS_STAT(conn,".",&st)!=0) {
2176                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2177                 return ERROR_DOS(ERRSRV,ERRinvdevice);
2178         }
2179
2180         *ppdata = (char *)SMB_REALLOC(
2181                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2182         if (*ppdata == NULL ) {
2183                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2184         }
2185
2186         pdata = *ppdata;
2187         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2188
2189         switch (info_level) {
2190                 case SMB_INFO_ALLOCATION:
2191                 {
2192                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2193                         data_len = 18;
2194                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2195                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2196                         }
2197
2198                         block_size = lp_block_size(snum);
2199                         if (bsize < block_size) {
2200                                 SMB_BIG_UINT factor = block_size/bsize;
2201                                 bsize = block_size;
2202                                 dsize /= factor;
2203                                 dfree /= factor;
2204                         }
2205                         if (bsize > block_size) {
2206                                 SMB_BIG_UINT factor = bsize/block_size;
2207                                 bsize = block_size;
2208                                 dsize *= factor;
2209                                 dfree *= factor;
2210                         }
2211                         bytes_per_sector = 512;
2212                         sectors_per_unit = bsize/bytes_per_sector;
2213
2214                         DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2215 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2216                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2217
2218                         SIVAL(pdata,l1_idFileSystem,st.st_dev);
2219                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2220                         SIVAL(pdata,l1_cUnit,dsize);
2221                         SIVAL(pdata,l1_cUnitAvail,dfree);
2222                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
2223                         break;
2224                 }
2225
2226                 case SMB_INFO_VOLUME:
2227                         /* Return volume name */
2228                         /* 
2229                          * Add volume serial number - hash of a combination of
2230                          * the called hostname and the service name.
2231                          */
2232                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2233                         /*
2234                          * Win2k3 and previous mess this up by sending a name length
2235                          * one byte short. I believe only older clients (OS/2 Win9x) use
2236                          * this call so try fixing this by adding a terminating null to
2237                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2238                          */
2239                         len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2240                         SCVAL(pdata,l2_vol_cch,len);
2241                         data_len = l2_vol_szVolLabel + len;
2242                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2243                                 (unsigned)st.st_ctime, len, vname));
2244                         break;
2245
2246                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2247                 case SMB_FS_ATTRIBUTE_INFORMATION:
2248
2249
2250 #if defined(HAVE_SYS_QUOTAS)
2251                         quota_flag = FILE_VOLUME_QUOTAS;
2252 #endif
2253
2254                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2255                                 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2256                                 quota_flag); /* FS ATTRIBUTES */
2257
2258                         SIVAL(pdata,4,255); /* Max filename component length */
2259                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2260                                 and will think we can't do long filenames */
2261                         len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2262                         SIVAL(pdata,8,len);
2263                         data_len = 12 + len;
2264                         break;
2265
2266                 case SMB_QUERY_FS_LABEL_INFO:
2267                 case SMB_FS_LABEL_INFORMATION:
2268                         len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2269                         data_len = 4 + len;
2270                         SIVAL(pdata,0,len);
2271                         break;
2272
2273                 case SMB_QUERY_FS_VOLUME_INFO:      
2274                 case SMB_FS_VOLUME_INFORMATION:
2275
2276                         /* 
2277                          * Add volume serial number - hash of a combination of
2278                          * the called hostname and the service name.
2279                          */
2280                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
2281                                 (str_checksum(get_local_machine_name())<<16));
2282
2283                         len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2284                         SIVAL(pdata,12,len);
2285                         data_len = 18+len;
2286                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
2287                                 (int)strlen(vname),vname, lp_servicename(snum)));
2288                         break;
2289
2290                 case SMB_QUERY_FS_SIZE_INFO:
2291                 case SMB_FS_SIZE_INFORMATION:
2292                 {
2293                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2294                         data_len = 24;
2295                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2296                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2297                         }
2298                         block_size = lp_block_size(snum);
2299                         if (bsize < block_size) {
2300                                 SMB_BIG_UINT factor = block_size/bsize;
2301                                 bsize = block_size;
2302                                 dsize /= factor;
2303                                 dfree /= factor;
2304                         }
2305                         if (bsize > block_size) {
2306                                 SMB_BIG_UINT factor = bsize/block_size;
2307                                 bsize = block_size;
2308                                 dsize *= factor;
2309                                 dfree *= factor;
2310                         }
2311                         bytes_per_sector = 512;
2312                         sectors_per_unit = bsize/bytes_per_sector;
2313                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2314 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2315                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2316                         SBIG_UINT(pdata,0,dsize);
2317                         SBIG_UINT(pdata,8,dfree);
2318                         SIVAL(pdata,16,sectors_per_unit);
2319                         SIVAL(pdata,20,bytes_per_sector);
2320                         break;
2321                 }
2322
2323                 case SMB_FS_FULL_SIZE_INFORMATION:
2324                 {
2325                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2326                         data_len = 32;
2327                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2328                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2329                         }
2330                         block_size = lp_block_size(snum);
2331                         if (bsize < block_size) {
2332                                 SMB_BIG_UINT factor = block_size/bsize;
2333                                 bsize = block_size;
2334                                 dsize /= factor;
2335                                 dfree /= factor;
2336                         }
2337                         if (bsize > block_size) {
2338                                 SMB_BIG_UINT factor = bsize/block_size;
2339                                 bsize = block_size;
2340                                 dsize *= factor;
2341                                 dfree *= factor;
2342                         }
2343                         bytes_per_sector = 512;
2344                         sectors_per_unit = bsize/bytes_per_sector;
2345                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2346 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2347                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2348                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2349                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2350                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2351                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2352                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2353                         break;
2354                 }
2355
2356                 case SMB_QUERY_FS_DEVICE_INFO:
2357                 case SMB_FS_DEVICE_INFORMATION:
2358                         data_len = 8;
2359                         SIVAL(pdata,0,0); /* dev type */
2360                         SIVAL(pdata,4,0); /* characteristics */
2361                         break;
2362
2363 #ifdef HAVE_SYS_QUOTAS
2364                 case SMB_FS_QUOTA_INFORMATION:
2365                 /* 
2366                  * what we have to send --metze:
2367                  *
2368                  * Unknown1:            24 NULL bytes
2369                  * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2370                  * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
2371                  * Quota Flags:         2 byte :
2372                  * Unknown3:            6 NULL bytes
2373                  *
2374                  * 48 bytes total
2375                  * 
2376                  * details for Quota Flags:
2377                  * 
2378                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2379                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2380                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2381                  * 0x0001 Enable Quotas: enable quota for this fs
2382                  *
2383                  */
2384                 {
2385                         /* we need to fake up a fsp here,
2386                          * because its not send in this call
2387                          */
2388                         files_struct fsp;
2389                         SMB_NTQUOTA_STRUCT quotas;
2390                         
2391                         ZERO_STRUCT(fsp);
2392                         ZERO_STRUCT(quotas);
2393                         
2394                         fsp.conn = conn;
2395                         fsp.fnum = -1;
2396                         
2397                         /* access check */
2398                         if (current_user.ut.uid != 0) {
2399                                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2400                                         lp_servicename(SNUM(conn)),conn->user));
2401                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2402                         }
2403                         
2404                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2405                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2406                                 return ERROR_DOS(ERRSRV,ERRerror);
2407                         }
2408
2409                         data_len = 48;
2410
2411                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
2412                 
2413                         /* Unknown1 24 NULL bytes*/
2414                         SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2415                         SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2416                         SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2417                 
2418                         /* Default Soft Quota 8 bytes */
2419                         SBIG_UINT(pdata,24,quotas.softlim);
2420
2421                         /* Default Hard Quota 8 bytes */
2422                         SBIG_UINT(pdata,32,quotas.hardlim);
2423         
2424                         /* Quota flag 2 bytes */
2425                         SSVAL(pdata,40,quotas.qflags);
2426                 
2427                         /* Unknown3 6 NULL bytes */
2428                         SSVAL(pdata,42,0);
2429                         SIVAL(pdata,44,0);
2430                         
2431                         break;
2432                 }
2433 #endif /* HAVE_SYS_QUOTAS */
2434                 case SMB_FS_OBJECTID_INFORMATION:
2435                         data_len = 64;
2436                         break;
2437
2438                 /*
2439                  * Query the version and capabilities of the CIFS UNIX extensions
2440                  * in use.
2441                  */
2442
2443                 case SMB_QUERY_CIFS_UNIX_INFO:
2444                         if (!lp_unix_extensions()) {
2445                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2446                         }
2447                         data_len = 12;
2448                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2449                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2450                         /* We have POSIX ACLs, pathname and locking capability. */
2451                         SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2452                                         CIFS_UNIX_POSIX_ACLS_CAP|
2453                                         CIFS_UNIX_POSIX_PATHNAMES_CAP|
2454                                         CIFS_UNIX_FCNTL_LOCKS_CAP)));
2455                         break;
2456
2457                 case SMB_QUERY_POSIX_FS_INFO:
2458                 {
2459                         int rc;
2460                         vfs_statvfs_struct svfs;
2461
2462                         if (!lp_unix_extensions()) {
2463                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2464                         }
2465
2466                         rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2467
2468                         if (!rc) {
2469                                 data_len = 56;
2470                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
2471                                 SIVAL(pdata,4,svfs.BlockSize);
2472                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2473                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2474                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2475                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2476                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2477                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2478                                 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2479 #ifdef EOPNOTSUPP
2480                         } else if (rc == EOPNOTSUPP) {
2481                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2482 #endif /* EOPNOTSUPP */
2483                         } else {
2484                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2485                                 return ERROR_DOS(ERRSRV,ERRerror);
2486                         }
2487                         break;
2488                 }
2489
2490                 case SMB_MAC_QUERY_FS_INFO:
2491                         /*
2492                          * Thursby MAC extension... ONLY on NTFS filesystems
2493                          * once we do streams then we don't need this
2494                          */
2495                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2496                                 data_len = 88;
2497                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2498                                 break;
2499                         }
2500                         /* drop through */
2501                 default:
2502                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2503         }
2504
2505
2506         send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len);
2507
2508         DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2509
2510         return -1;
2511 }
2512
2513 /****************************************************************************
2514  Reply to a TRANS2_SETFSINFO (set filesystem info).
2515 ****************************************************************************/
2516
2517 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2518                                         char **pparams, int total_params, char **ppdata, int total_data,
2519                                         unsigned int max_data_bytes)
2520 {
2521         char *pdata = *ppdata;
2522         char *params = *pparams;
2523         uint16 info_level;
2524         int outsize;
2525
2526         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2527
2528         /*  */
2529         if (total_params < 4) {
2530                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2531                         total_params));
2532                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2533         }
2534
2535         info_level = SVAL(params,2);
2536
2537         switch(info_level) {
2538                 case SMB_SET_CIFS_UNIX_INFO:
2539                         {
2540                                 uint16 client_unix_major;
2541                                 uint16 client_unix_minor;
2542                                 uint32 client_unix_cap_low;
2543                                 uint32 client_unix_cap_high;
2544
2545                                 if (!lp_unix_extensions()) {
2546                                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2547                                 }
2548
2549                                 /* There should be 12 bytes of capabilities set. */
2550                                 if (total_data < 8) {
2551                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2552                                 }
2553                                 client_unix_major = SVAL(pdata,0);
2554                                 client_unix_minor = SVAL(pdata,2);
2555                                 client_unix_cap_low = IVAL(pdata,4);
2556                                 client_unix_cap_high = IVAL(pdata,8);
2557                                 /* Just print these values for now. */
2558                                 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2559 cap_low = 0x%x, cap_high = 0x%x\n",
2560                                         (unsigned int)client_unix_major,
2561                                         (unsigned int)client_unix_minor,
2562                                         (unsigned int)client_unix_cap_low,
2563                                         (unsigned int)client_unix_cap_high ));
2564
2565                                 /* Here is where we must switch to posix pathname processing... */
2566                                 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2567                                         lp_set_posix_pathnames();
2568                                         mangle_change_to_posix();
2569                                 }
2570
2571                                 if (client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) {
2572                                         lp_set_posix_cifsx_locktype(POSIX_LOCK);
2573                                 }
2574                                 break;
2575                         }
2576                 case SMB_FS_QUOTA_INFORMATION:
2577                         {
2578                                 files_struct *fsp = NULL;
2579                                 SMB_NTQUOTA_STRUCT quotas;
2580         
2581                                 ZERO_STRUCT(quotas);
2582
2583                                 /* access check */
2584                                 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2585                                         DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2586                                                 lp_servicename(SNUM(conn)),conn->user));
2587                                         return ERROR_DOS(ERRSRV,ERRaccess);
2588                                 }
2589
2590                                 /* note: normaly there're 48 bytes,
2591                                  * but we didn't use the last 6 bytes for now 
2592                                  * --metze 
2593                                  */
2594                                 fsp = file_fsp(params,0);
2595                                 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2596                                         DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2597                                         return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2598                                 }
2599
2600                                 if (total_data < 42) {
2601                                         DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2602                                                 total_data));
2603                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2604                                 }
2605                         
2606                                 /* unknown_1 24 NULL bytes in pdata*/
2607                 
2608                                 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2609                                 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2610 #ifdef LARGE_SMB_OFF_T
2611                                 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2612 #else /* LARGE_SMB_OFF_T */
2613                                 if ((IVAL(pdata,28) != 0)&&
2614                                         ((quotas.softlim != 0xFFFFFFFF)||
2615                                         (IVAL(pdata,28)!=0xFFFFFFFF))) {
2616                                         /* more than 32 bits? */
2617                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2618                                 }
2619 #endif /* LARGE_SMB_OFF_T */
2620                 
2621                                 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2622                                 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2623 #ifdef LARGE_SMB_OFF_T
2624                                 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2625 #else /* LARGE_SMB_OFF_T */
2626                                 if ((IVAL(pdata,36) != 0)&&
2627                                         ((quotas.hardlim != 0xFFFFFFFF)||
2628                                         (IVAL(pdata,36)!=0xFFFFFFFF))) {
2629                                         /* more than 32 bits? */
2630                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2631                                 }
2632 #endif /* LARGE_SMB_OFF_T */
2633                 
2634                                 /* quota_flags 2 bytes **/
2635                                 quotas.qflags = SVAL(pdata,40);
2636                 
2637                                 /* unknown_2 6 NULL bytes follow*/
2638                 
2639                                 /* now set the quotas */
2640                                 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2641                                         DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2642                                         return ERROR_DOS(ERRSRV,ERRerror);
2643                                 }
2644                         
2645                                 break;
2646                         }
2647                 default:
2648                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2649                                 info_level));
2650                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2651                         break;
2652         }
2653
2654         /* 
2655          * sending this reply works fine, 
2656          * but I'm not sure it's the same 
2657          * like windows do...
2658          * --metze
2659          */ 
2660         outsize = set_message(outbuf,10,0,True);
2661
2662         return outsize;
2663 }
2664
2665 /****************************************************************************
2666  Utility function to set bad path error.
2667 ****************************************************************************/
2668
2669 int set_bad_path_error(int err, BOOL bad_path, char *outbuf, int def_class, uint32 def_code)
2670 {
2671         DEBUG(10,("set_bad_path_error: err = %d bad_path = %d\n",
2672                         err, (int)bad_path ));
2673
2674         if(err == ENOENT) {
2675                 if (bad_path) {
2676                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2677                 } else {
2678                         return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
2679                 }
2680         }
2681         return UNIXERROR(def_class,def_code);
2682 }
2683
2684 #if defined(HAVE_POSIX_ACLS)
2685 /****************************************************************************
2686  Utility function to count the number of entries in a POSIX acl.
2687 ****************************************************************************/
2688
2689 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2690 {
2691         unsigned int ace_count = 0;
2692         int entry_id = SMB_ACL_FIRST_ENTRY;
2693         SMB_ACL_ENTRY_T entry;
2694
2695         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2696                 /* get_next... */
2697                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2698                         entry_id = SMB_ACL_NEXT_ENTRY;
2699                 }
2700                 ace_count++;
2701         }
2702         return ace_count;
2703 }
2704
2705 /****************************************************************************
2706  Utility function to marshall a POSIX acl into wire format.
2707 ****************************************************************************/
2708
2709 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2710 {
2711         int entry_id = SMB_ACL_FIRST_ENTRY;
2712         SMB_ACL_ENTRY_T entry;
2713
2714         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2715                 SMB_ACL_TAG_T tagtype;
2716                 SMB_ACL_PERMSET_T permset;
2717                 unsigned char perms = 0;
2718                 unsigned int own_grp;
2719
2720                 /* get_next... */
2721                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2722                         entry_id = SMB_ACL_NEXT_ENTRY;
2723                 }
2724
2725                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2726                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2727                         return False;
2728                 }
2729
2730                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2731                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2732                         return False;
2733                 }
2734
2735                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2736                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2737                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2738
2739                 SCVAL(pdata,1,perms);
2740
2741                 switch (tagtype) {
2742                         case SMB_ACL_USER_OBJ:
2743                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2744                                 own_grp = (unsigned int)pst->st_uid;
2745                                 SIVAL(pdata,2,own_grp);
2746                                 SIVAL(pdata,6,0);
2747                                 break;
2748                         case SMB_ACL_USER:
2749                                 {
2750                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2751                                         if (!puid) {
2752                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2753                                         }
2754                                         own_grp = (unsigned int)*puid;
2755                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
2756                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
2757                                         SIVAL(pdata,2,own_grp);
2758                                         SIVAL(pdata,6,0);
2759                                         break;
2760                                 }
2761                         case SMB_ACL_GROUP_OBJ:
2762                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
2763                                 own_grp = (unsigned int)pst->st_gid;
2764                                 SIVAL(pdata,2,own_grp);
2765                                 SIVAL(pdata,6,0);
2766                                 break;
2767                         case SMB_ACL_GROUP:
2768                                 {
2769                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
2770                                         if (!pgid) {
2771                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2772                                         }
2773                                         own_grp = (unsigned int)*pgid;
2774                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
2775                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
2776                                         SIVAL(pdata,2,own_grp);
2777                                         SIVAL(pdata,6,0);
2778                                         break;
2779                                 }
2780                         case SMB_ACL_MASK:
2781                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
2782                                 SIVAL(pdata,2,0xFFFFFFFF);
2783                                 SIVAL(pdata,6,0xFFFFFFFF);
2784                                 break;
2785                         case SMB_ACL_OTHER:
2786                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
2787                                 SIVAL(pdata,2,0xFFFFFFFF);
2788                                 SIVAL(pdata,6,0xFFFFFFFF);
2789                                 break;
2790                         default:
2791                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
2792                                 return False;
2793                 }
2794                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
2795         }
2796
2797         return True;
2798 }
2799 #endif
2800
2801 /****************************************************************************
2802  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
2803  file name or file id).
2804 ****************************************************************************/
2805
2806 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2807                                         unsigned int tran_call,
2808                                         char **pparams, int total_params, char **ppdata, int total_data,
2809                                         unsigned int max_data_bytes)
2810 {
2811         char *params = *pparams;
2812         char *pdata = *ppdata;
2813         uint16 info_level;
2814         int mode=0;
2815         int nlink;
2816         SMB_OFF_T file_size=0;
2817         SMB_BIG_UINT allocation_size=0;
2818         unsigned int data_size = 0;
2819         unsigned int param_size = 2;
2820         SMB_STRUCT_STAT sbuf;
2821         pstring fname, dos_fname;
2822         char *fullpathname;
2823         char *base_name;
2824         char *p;
2825         SMB_OFF_T pos = 0;
2826         BOOL bad_path = False;
2827         BOOL delete_pending = False;
2828         int len;
2829         time_t c_time;
2830         files_struct *fsp = NULL;
2831         TALLOC_CTX *data_ctx = NULL;
2832         struct ea_list *ea_list = NULL;
2833         uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
2834         char *lock_data = NULL;
2835
2836         if (!params)
2837                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2838
2839         ZERO_STRUCT(sbuf);
2840
2841         if (tran_call == TRANSACT2_QFILEINFO) {
2842                 if (total_params < 4) {
2843                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2844                 }
2845
2846                 fsp = file_fsp(params,0);
2847                 info_level = SVAL(params,2);
2848
2849                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
2850
2851                 if(fsp && (fsp->fake_file_handle)) {
2852                         /*
2853                          * This is actually for the QUOTA_FAKE_FILE --metze
2854                          */
2855                                                 
2856                         pstrcpy(fname, fsp->fsp_name);
2857                         /* We know this name is ok, it's already passed the checks. */
2858                         
2859                 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
2860                         /*
2861                          * This is actually a QFILEINFO on a directory
2862                          * handle (returned from an NT SMB). NT5.0 seems
2863                          * to do this call. JRA.
2864                          */
2865                         /* We know this name is ok, it's already passed the checks. */
2866                         pstrcpy(fname, fsp->fsp_name);
2867                   
2868                         if (INFO_LEVEL_IS_UNIX(info_level)) {
2869                                 /* Always do lstat for UNIX calls. */
2870                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2871                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2872                                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2873                                 }
2874                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
2875                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2876                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2877                         }
2878
2879                         delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2880                 } else {
2881                         /*
2882                          * Original code - this is an open file.
2883                          */
2884                         CHECK_FSP(fsp,conn);
2885
2886                         pstrcpy(fname, fsp->fsp_name);
2887                         if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
2888                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
2889                                 return(UNIXERROR(ERRDOS,ERRbadfid));
2890                         }
2891                         pos = fsp->fh->position_information;
2892                         delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2893                         access_mask = fsp->access_mask;
2894                 }
2895         } else {
2896                 NTSTATUS status = NT_STATUS_OK;
2897
2898                 /* qpathinfo */
2899                 if (total_params < 6) {
2900                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2901                 }
2902
2903                 info_level = SVAL(params,0);
2904
2905                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
2906
2907                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
2908                 if (!NT_STATUS_IS_OK(status)) {
2909                         return ERROR_NT(status);
2910                 }
2911
2912                 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
2913
2914                 unix_convert(fname,conn,0,&bad_path,&sbuf);
2915                 if (bad_path) {
2916                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
2917                 }
2918                 if (!check_name(fname,conn)) {
2919                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
2920                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2921                 }
2922
2923                 if (INFO_LEVEL_IS_UNIX(info_level)) {
2924                         /* Always do lstat for UNIX calls. */
2925                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
2926                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
2927                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2928                         }
2929                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
2930                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
2931                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
2932                 }
2933
2934                 delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
2935                 if (delete_pending) {
2936                         return ERROR_NT(NT_STATUS_DELETE_PENDING);
2937                 }
2938         }
2939
2940         nlink = sbuf.st_nlink;
2941
2942         if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
2943                 /* NTFS does not seem to count ".." */
2944                 nlink -= 1;
2945         }
2946
2947         if ((nlink > 0) && delete_pending) {
2948                 nlink -= 1;
2949         }
2950
2951         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
2952                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2953         }
2954
2955         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
2956                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
2957
2958         p = strrchr_m(fname,'/'); 
2959         if (!p)
2960                 base_name = fname;
2961         else
2962                 base_name = p+1;
2963
2964         mode = dos_mode(conn,fname,&sbuf);
2965         if (!mode)
2966                 mode = FILE_ATTRIBUTE_NORMAL;
2967
2968         fullpathname = fname;
2969         if (!(mode & aDIR))
2970                 file_size = get_file_size(sbuf);
2971
2972         /* Pull out any data sent here before we realloc. */
2973         switch (info_level) {
2974                 case SMB_INFO_QUERY_EAS_FROM_LIST:
2975                 {
2976                         /* Pull any EA list from the data portion. */
2977                         uint32 ea_size;
2978
2979                         if (total_data < 4) {
2980                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2981                         }
2982                         ea_size = IVAL(pdata,0);
2983
2984                         if (total_data > 0 && ea_size != total_data) {
2985                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
2986 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2987                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2988                         }
2989
2990                         if (!lp_ea_support(SNUM(conn))) {
2991                                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
2992                         }
2993
2994                         if ((data_ctx = talloc_init("ea_list")) == NULL) {
2995                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2996                         }
2997
2998                         /* Pull out the list of names. */
2999                         ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3000                         if (!ea_list) {
3001                                 talloc_destroy(data_ctx);
3002                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3003                         }
3004                         break;
3005                 }
3006
3007                 case SMB_QUERY_POSIX_LOCK:
3008                 {
3009                         if (fsp == NULL || fsp->fh->fd == -1) {
3010                                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3011                         }
3012
3013                         if (total_data != POSIX_LOCK_DATA_SIZE) {
3014                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3015                         }
3016
3017                         if ((data_ctx = talloc_init("lock_request")) == NULL) {
3018                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3019                         }
3020
3021                         /* Copy the lock range data. */
3022                         lock_data = (char *)talloc_memdup(
3023                                 data_ctx, pdata, total_data);
3024                         if (!lock_data) {
3025                                 talloc_destroy(data_ctx);
3026                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3027                         }
3028                 }
3029                 default:
3030                         break;
3031         }
3032
3033         *pparams = (char *)SMB_REALLOC(*pparams,2);
3034         if (*pparams == NULL) {
3035                 talloc_destroy(data_ctx);
3036                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3037         }
3038         params = *pparams;
3039         SSVAL(params,0,0);
3040         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3041         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3042         if (*ppdata == NULL ) {
3043                 talloc_destroy(data_ctx);
3044                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3045         }
3046         pdata = *ppdata;
3047
3048         c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3049
3050         allocation_size = get_allocation_size(conn,fsp,&sbuf);
3051
3052         if (fsp) {
3053                 if (fsp->pending_modtime) {
3054                         /* the pending modtime overrides the current modtime */
3055                         sbuf.st_mtime = fsp->pending_modtime;
3056                 }
3057         } else {
3058                 /* Do we have this path open ? */
3059                 files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
3060                 if (fsp1 && fsp1->pending_modtime) {
3061                         /* the pending modtime overrides the current modtime */
3062                         sbuf.st_mtime = fsp1->pending_modtime;
3063                 }
3064                 if (fsp1 && fsp1->initial_allocation_size) {
3065                         allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3066                 }
3067         }
3068
3069         if (lp_dos_filetime_resolution(SNUM(conn))) {
3070                 c_time &= ~1;
3071                 sbuf.st_atime &= ~1;
3072                 sbuf.st_ctime &= ~1;
3073                 sbuf.st_mtime &= ~1;
3074         }
3075
3076         /* NT expects the name to be in an exact form of the *full*
3077            filename. See the trans2 torture test */
3078         if (strequal(base_name,".")) {
3079                 pstrcpy(dos_fname, "\\");
3080         } else {
3081                 pstr_sprintf(dos_fname, "\\%s", fname);
3082                 string_replace(dos_fname, '/', '\\');
3083         }
3084
3085         switch (info_level) {
3086                 case SMB_INFO_STANDARD:
3087                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3088                         data_size = 22;
3089                         srv_put_dos_date2(pdata,l1_fdateCreation,c_time);
3090                         srv_put_dos_date2(pdata,l1_fdateLastAccess,sbuf.st_atime);
3091                         srv_put_dos_date2(pdata,l1_fdateLastWrite,sbuf.st_mtime); /* write time */
3092                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
3093                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3094                         SSVAL(pdata,l1_attrFile,mode);
3095                         break;
3096
3097                 case SMB_INFO_QUERY_EA_SIZE:
3098                 {
3099                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3100                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3101                         data_size = 26;
3102                         srv_put_dos_date2(pdata,0,c_time);
3103                         srv_put_dos_date2(pdata,4,sbuf.st_atime);
3104                         srv_put_dos_date2(pdata,8,sbuf.st_mtime); /* write time */
3105                         SIVAL(pdata,12,(uint32)file_size);
3106                         SIVAL(pdata,16,(uint32)allocation_size);
3107                         SSVAL(pdata,20,mode);
3108                         SIVAL(pdata,22,ea_size);
3109                         break;
3110                 }
3111
3112                 case SMB_INFO_IS_NAME_VALID:
3113                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3114                         if (tran_call == TRANSACT2_QFILEINFO) {
3115                                 /* os/2 needs this ? really ?*/      
3116                                 return ERROR_DOS(ERRDOS,ERRbadfunc); 
3117                         }
3118                         data_size = 0;
3119                         param_size = 0;
3120                         break;
3121                         
3122                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3123                 {
3124                         size_t total_ea_len = 0;
3125                         struct ea_list *ea_file_list = NULL;
3126
3127                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3128
3129                         ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3130                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3131
3132                         if (!ea_list || (total_ea_len > data_size)) {
3133                                 talloc_destroy(data_ctx);
3134                                 data_size = 4;
3135                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3136                                 break;
3137                         }
3138
3139                         data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3140                         talloc_destroy(data_ctx);
3141                         break;
3142                 }
3143
3144                 case SMB_INFO_QUERY_ALL_EAS:
3145                 {
3146                         /* We have data_size bytes to put EA's into. */
3147                         size_t total_ea_len = 0;
3148
3149                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3150
3151                         data_ctx = talloc_init("ea_ctx");
3152                         if (!data_ctx) {
3153                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3154                         }
3155
3156                         ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3157                         if (!ea_list || (total_ea_len > data_size)) {
3158                                 talloc_destroy(data_ctx);
3159                                 data_size = 4;
3160                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3161                                 break;
3162                         }
3163
3164                         data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3165                         talloc_destroy(data_ctx);
3166                         break;
3167                 }
3168
3169                 case SMB_FILE_BASIC_INFORMATION:
3170                 case SMB_QUERY_FILE_BASIC_INFO:
3171
3172                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3173                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3174                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3175                         } else {
3176                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3177                                 data_size = 40;
3178                                 SIVAL(pdata,36,0);
3179                         }
3180                         put_long_date(pdata,c_time);
3181                         put_long_date(pdata+8,sbuf.st_atime);
3182                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3183                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3184                         SIVAL(pdata,32,mode);
3185
3186                         DEBUG(5,("SMB_QFBI - "));
3187                         {
3188                                 time_t create_time = c_time;
3189                                 DEBUG(5,("create: %s ", ctime(&create_time)));
3190                         }
3191                         DEBUG(5,("access: %s ", ctime(&sbuf.st_atime)));
3192                         DEBUG(5,("write: %s ", ctime(&sbuf.st_mtime)));
3193                         DEBUG(5,("change: %s ", ctime(&sbuf.st_mtime)));
3194                         DEBUG(5,("mode: %x\n", mode));
3195                         break;
3196
3197                 case SMB_FILE_STANDARD_INFORMATION:
3198                 case SMB_QUERY_FILE_STANDARD_INFO:
3199
3200                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3201                         data_size = 24;
3202                         SOFF_T(pdata,0,allocation_size);
3203                         SOFF_T(pdata,8,file_size);
3204                         SIVAL(pdata,16,nlink);
3205                         SCVAL(pdata,20,delete_pending?1:0);
3206                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3207                         SSVAL(pdata,22,0); /* Padding. */
3208                         break;
3209
3210                 case SMB_FILE_EA_INFORMATION:
3211                 case SMB_QUERY_FILE_EA_INFO:
3212                 {
3213                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3214                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3215                         data_size = 4;
3216                         SIVAL(pdata,0,ea_size);
3217                         break;
3218                 }
3219
3220                 /* Get the 8.3 name - used if NT SMB was negotiated. */
3221                 case SMB_QUERY_FILE_ALT_NAME_INFO:
3222                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3223                 {
3224                         pstring short_name;
3225
3226                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3227                         pstrcpy(short_name,base_name);
3228                         /* Mangle if not already 8.3 */
3229                         if(!mangle_is_8_3(short_name, True, conn->params)) {
3230                                 mangle_map(short_name,True,True,conn->params);
3231                         }
3232                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3233                         data_size = 4 + len;
3234                         SIVAL(pdata,0,len);
3235                         break;
3236                 }
3237
3238                 case SMB_QUERY_FILE_NAME_INFO:
3239                         /*
3240                           this must be *exactly* right for ACLs on mapped drives to work
3241                          */
3242                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3243                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3244                         data_size = 4 + len;
3245                         SIVAL(pdata,0,len);
3246                         break;
3247
3248                 case SMB_FILE_ALLOCATION_INFORMATION:
3249                 case SMB_QUERY_FILE_ALLOCATION_INFO:
3250                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3251                         data_size = 8;
3252                         SOFF_T(pdata,0,allocation_size);
3253                         break;
3254
3255                 case SMB_FILE_END_OF_FILE_INFORMATION:
3256                 case SMB_QUERY_FILE_END_OF_FILEINFO:
3257                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3258                         data_size = 8;
3259                         SOFF_T(pdata,0,file_size);
3260                         break;
3261
3262                 case SMB_QUERY_FILE_ALL_INFO:
3263                 case SMB_FILE_ALL_INFORMATION:
3264                 {
3265                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3266                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3267                         put_long_date(pdata,c_time);
3268                         put_long_date(pdata+8,sbuf.st_atime);
3269                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3270                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3271                         SIVAL(pdata,32,mode);
3272                         SIVAL(pdata,36,0); /* padding. */
3273                         pdata += 40;
3274                         SOFF_T(pdata,0,allocation_size);
3275                         SOFF_T(pdata,8,file_size);
3276                         SIVAL(pdata,16,nlink);
3277                         SCVAL(pdata,20,delete_pending);
3278                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3279                         SSVAL(pdata,22,0);
3280                         pdata += 24;
3281                         SIVAL(pdata,0,ea_size);
3282                         pdata += 4; /* EA info */
3283                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3284                         SIVAL(pdata,0,len);
3285                         pdata += 4 + len;
3286                         data_size = PTR_DIFF(pdata,(*ppdata));
3287                         break;
3288                 }
3289                 case SMB_FILE_INTERNAL_INFORMATION:
3290                         /* This should be an index number - looks like
3291                            dev/ino to me :-) 
3292
3293                            I think this causes us to fail the IFSKIT
3294                            BasicFileInformationTest. -tpot */
3295
3296                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3297                         SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3298                         SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3299                         data_size = 8;
3300                         break;
3301
3302                 case SMB_FILE_ACCESS_INFORMATION:
3303                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3304                         SIVAL(pdata,0,access_mask);
3305                         data_size = 4;
3306                         break;
3307
3308                 case SMB_FILE_NAME_INFORMATION:
3309                         /* Pathname with leading '\'. */
3310                         {
3311                                 size_t byte_len;
3312                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3313                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3314                                 SIVAL(pdata,0,byte_len);
3315                                 data_size = 4 + byte_len;
3316                                 break;
3317                         }
3318
3319                 case SMB_FILE_DISPOSITION_INFORMATION:
3320                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3321                         data_size = 1;
3322                         SCVAL(pdata,0,delete_pending);
3323                         break;
3324
3325                 case SMB_FILE_POSITION_INFORMATION:
3326                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3327                         data_size = 8;
3328                         SOFF_T(pdata,0,pos);
3329                         break;
3330
3331                 case SMB_FILE_MODE_INFORMATION:
3332                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3333                         SIVAL(pdata,0,mode);
3334                         data_size = 4;
3335                         break;
3336
3337                 case SMB_FILE_ALIGNMENT_INFORMATION:
3338                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3339                         SIVAL(pdata,0,0); /* No alignment needed. */
3340                         data_size = 4;
3341                         break;
3342
3343 #if 0
3344                 /*
3345                  * NT4 server just returns "invalid query" to this - if we try to answer
3346                  * it then NTws gets a BSOD! (tridge).
3347                  * W2K seems to want this. JRA.
3348                  */
3349                 case SMB_QUERY_FILE_STREAM_INFO:
3350 #endif
3351                 case SMB_FILE_STREAM_INFORMATION:
3352                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3353                         if (mode & aDIR) {
3354                                 data_size = 0;
3355                         } else {
3356                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3357                                 SIVAL(pdata,0,0); /* ??? */
3358                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3359                                 SOFF_T(pdata,8,file_size);
3360                                 SIVAL(pdata,16,allocation_size);
3361                                 SIVAL(pdata,20,0); /* ??? */
3362                                 data_size = 24 + byte_len;
3363                         }
3364                         break;
3365
3366                 case SMB_QUERY_COMPRESSION_INFO:
3367                 case SMB_FILE_COMPRESSION_INFORMATION:
3368                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3369                         SOFF_T(pdata,0,file_size);
3370                         SIVAL(pdata,8,0); /* ??? */
3371                         SIVAL(pdata,12,0); /* ??? */
3372                         data_size = 16;
3373                         break;
3374
3375                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3376                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3377                         put_long_date(pdata,c_time);
3378                         put_long_date(pdata+8,sbuf.st_atime);
3379                         put_long_date(pdata+16,sbuf.st_mtime); /* write time */
3380                         put_long_date(pdata+24,sbuf.st_mtime); /* change time */
3381                         SIVAL(pdata,32,allocation_size);
3382                         SOFF_T(pdata,40,file_size);
3383                         SIVAL(pdata,48,mode);
3384                         SIVAL(pdata,52,0); /* ??? */
3385                         data_size = 56;
3386                         break;
3387
3388                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3389                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3390                         SIVAL(pdata,0,mode);
3391                         SIVAL(pdata,4,0);
3392                         data_size = 8;
3393                         break;
3394
3395                 /*
3396                  * CIFS UNIX Extensions.
3397                  */
3398
3399                 case SMB_QUERY_FILE_UNIX_BASIC:
3400
3401                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC\n"));
3402                         DEBUG(4,("call_trans2qfilepathinfo: st_mode=%o\n",(int)sbuf.st_mode));
3403
3404                         SOFF_T(pdata,0,get_file_size(sbuf));             /* File size 64 Bit */
3405                         pdata += 8;
3406
3407                         SOFF_T(pdata,0,get_allocation_size(conn,fsp,&sbuf)); /* Number of bytes used on disk - 64 Bit */
3408                         pdata += 8;
3409
3410                         put_long_date(pdata,sbuf.st_ctime);       /* Creation Time 64 Bit */
3411                         put_long_date(pdata+8,sbuf.st_atime);     /* Last access time 64 Bit */
3412                         put_long_date(pdata+16,sbuf.st_mtime);    /* Last modification time 64 Bit */
3413                         pdata += 24;
3414
3415                         SIVAL(pdata,0,sbuf.st_uid);               /* user id for the owner */
3416                         SIVAL(pdata,4,0);
3417                         pdata += 8;
3418
3419                         SIVAL(pdata,0,sbuf.st_gid);               /* group id of owner */
3420                         SIVAL(pdata,4,0);
3421                         pdata += 8;
3422
3423                         SIVAL(pdata,0,unix_filetype(sbuf.st_mode));
3424                         pdata += 4;
3425
3426                         SIVAL(pdata,0,unix_dev_major(sbuf.st_rdev));   /* Major device number if type is device */
3427                         SIVAL(pdata,4,0);
3428                         pdata += 8;
3429
3430                         SIVAL(pdata,0,unix_dev_minor(sbuf.st_rdev));   /* Minor device number if type is device */
3431                         SIVAL(pdata,4,0);
3432                         pdata += 8;
3433
3434                         SINO_T_VAL(pdata,0,(SMB_INO_T)sbuf.st_ino);   /* inode number */
3435                         pdata += 8;
3436                                 
3437                         SIVAL(pdata,0, unix_perms_to_wire(sbuf.st_mode));     /* Standard UNIX file permissions */
3438                         SIVAL(pdata,4,0);
3439                         pdata += 8;
3440
3441                         SIVAL(pdata,0,sbuf.st_nlink);             /* number of hard links */
3442                         SIVAL(pdata,4,0);
3443                         pdata += 8;
3444                         data_size = PTR_DIFF(pdata,(*ppdata));
3445
3446                         {
3447                                 int i;
3448                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3449
3450                                 for (i=0; i<100; i++)
3451                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3452                                 DEBUG(4,("\n"));
3453                         }
3454
3455                         break;
3456
3457                 case SMB_QUERY_FILE_UNIX_LINK:
3458                         {
3459                                 pstring buffer;
3460
3461                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3462 #ifdef S_ISLNK
3463                                 if(!S_ISLNK(sbuf.st_mode))
3464                                         return(UNIXERROR(ERRSRV,ERRbadlink));
3465 #else
3466                                 return(UNIXERROR(ERRDOS,ERRbadlink));
3467 #endif
3468                                 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
3469                                 if (len == -1)
3470                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3471                                 buffer[len] = 0;
3472                                 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3473                                 pdata += len;
3474                                 data_size = PTR_DIFF(pdata,(*ppdata));
3475
3476                                 break;
3477                         }
3478
3479 #if defined(HAVE_POSIX_ACLS)
3480                 case SMB_QUERY_POSIX_ACL:
3481                         {
3482                                 SMB_ACL_T file_acl = NULL;
3483                                 SMB_ACL_T def_acl = NULL;
3484                                 uint16 num_file_acls = 0;
3485                                 uint16 num_def_acls = 0;
3486
3487                                 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3488                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3489                                 } else {
3490                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3491                                 }
3492
3493                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3494                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3495                                                 fname ));
3496                                         return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3497                                 }
3498
3499                                 if (S_ISDIR(sbuf.st_mode)) {
3500                                         if (fsp && fsp->is_directory) {
3501                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3502                                         } else {
3503                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
3504                                         }
3505                                         def_acl = free_empty_sys_acl(conn, def_acl);
3506                                 }
3507
3508                                 num_file_acls = count_acl_entries(conn, file_acl);
3509                                 num_def_acls = count_acl_entries(conn, def_acl);
3510
3511                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
3512                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
3513                                                 data_size,
3514                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
3515                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
3516                                         if (file_acl) {
3517                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3518                                         }
3519                                         if (def_acl) {
3520                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3521                                         }
3522                                         return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
3523                                 }
3524
3525                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3526                                 SSVAL(pdata,2,num_file_acls);
3527                                 SSVAL(pdata,4,num_def_acls);
3528                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
3529                                         if (file_acl) {
3530                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3531                                         }
3532                                         if (def_acl) {
3533                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3534                                         }
3535                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3536                                 }
3537                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
3538                                         if (file_acl) {
3539                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3540                                         }
3541                                         if (def_acl) {
3542                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3543                                         }
3544                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
3545                                 }
3546
3547                                 if (file_acl) {
3548                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
3549                                 }
3550                                 if (def_acl) {
3551                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
3552                                 }
3553                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
3554                                 break;
3555                         }
3556 #endif
3557
3558
3559                 case SMB_QUERY_POSIX_LOCK:
3560                 {
3561                         NTSTATUS status = NT_STATUS_INVALID_LEVEL;
3562                         SMB_BIG_UINT count;
3563                         SMB_BIG_UINT offset;
3564                         uint32 lock_pid;
3565                         enum brl_type lock_type;
3566
3567                         if (total_data != POSIX_LOCK_DATA_SIZE) {
3568                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3569                         }
3570
3571                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
3572                                 case POSIX_LOCK_TYPE_READ:
3573                                         lock_type = READ_LOCK;
3574                                         break;
3575                                 case POSIX_LOCK_TYPE_WRITE:
3576                                         lock_type = WRITE_LOCK;
3577                                         break;
3578                                 case POSIX_LOCK_TYPE_UNLOCK:
3579                                 default:
3580                                         /* There's no point in asking for an unlock... */
3581                                         talloc_destroy(data_ctx);
3582                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3583                         }
3584
3585                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
3586 #if defined(HAVE_LONGLONG)
3587                         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
3588                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
3589                         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
3590                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
3591 #else /* HAVE_LONGLONG */
3592                         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
3593                         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
3594 #endif /* HAVE_LONGLONG */
3595
3596                         status = query_lock(fsp,
3597                                         &lock_pid,
3598                                         &count,
3599                                         &offset,
3600                                         &lock_type,
3601                                         POSIX_LOCK);
3602
3603                         if (ERROR_WAS_LOCK_DENIED(status)) {
3604                                 /* Here we need to report who has it locked... */
3605                                 data_size = POSIX_LOCK_DATA_SIZE;
3606
3607                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
3608                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
3609                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
3610 #if defined(HAVE_LONGLONG)
3611                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
3612                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
3613                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
3614                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
3615 #else /* HAVE_LONGLONG */
3616                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
3617                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
3618 #endif /* HAVE_LONGLONG */
3619
3620                         } else if (NT_STATUS_IS_OK(status)) {
3621                                 /* For success we just return a copy of what we sent
3622                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
3623                                 data_size = POSIX_LOCK_DATA_SIZE;
3624                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
3625                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
3626                         } else {
3627                                 return ERROR_NT(status);
3628                         }
3629                         break;
3630                 }
3631
3632                 default:
3633                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3634         }
3635
3636         send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size);
3637
3638         return(-1);
3639 }
3640
3641 /****************************************************************************
3642  Set a hard link (called by UNIX extensions and by NT rename with HARD link
3643  code.
3644 ****************************************************************************/
3645
3646 NTSTATUS hardlink_internals(connection_struct *conn, char *oldname, char *newname)
3647 {
3648         BOOL bad_path_oldname = False;
3649         BOOL bad_path_newname = False;
3650         SMB_STRUCT_STAT sbuf1, sbuf2;
3651         pstring last_component_oldname;
3652         pstring last_component_newname;
3653         NTSTATUS status = NT_STATUS_OK;
3654
3655         ZERO_STRUCT(sbuf1);
3656         ZERO_STRUCT(sbuf2);
3657
3658         /* No wildcards. */
3659         if (ms_has_wild(newname) || ms_has_wild(oldname)) {
3660                 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
3661         }
3662
3663         unix_convert(oldname,conn,last_component_oldname,&bad_path_oldname,&sbuf1);
3664         if (bad_path_oldname) {
3665                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3666         }
3667
3668         /* Quick check for "." and ".." */
3669         if (last_component_oldname[0] == '.') {
3670                 if (!last_component_oldname[1] || (last_component_oldname[1] == '.' && !last_component_oldname[2])) {
3671                         return NT_STATUS_OBJECT_NAME_INVALID;
3672                 }
3673         }
3674
3675         /* source must already exist. */
3676         if (!VALID_STAT(sbuf1)) {
3677                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3678         }
3679
3680         if (!check_name(oldname,conn)) {
3681                 return NT_STATUS_ACCESS_DENIED;
3682         }
3683
3684         unix_convert(newname,conn,last_component_newname,&bad_path_newname,&sbuf2);
3685         if (bad_path_newname) {
3686                 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3687         }
3688
3689         /* Quick check for "." and ".." */
3690         if (last_component_newname[0] == '.') {
3691                 if (!last_component_newname[1] || (last_component_newname[1] == '.' && !last_component_newname[2])) {
3692                         return NT_STATUS_OBJECT_NAME_INVALID;
3693                 }
3694         }
3695
3696         /* Disallow if newname already exists. */
3697         if (VALID_STAT(sbuf2)) {
3698                 return NT_STATUS_OBJECT_NAME_COLLISION;
3699         }
3700
3701         if (!check_name(newname,conn)) {
3702                 return NT_STATUS_ACCESS_DENIED;
3703         }
3704
3705         /* No links from a directory. */
3706         if (S_ISDIR(sbuf1.st_mode)) {
3707                 return NT_STATUS_FILE_IS_A_DIRECTORY;
3708         }
3709
3710         /* Ensure this is within the share. */
3711         if (!reduce_name(conn, oldname) != 0)
3712                 return NT_STATUS_ACCESS_DENIED;
3713
3714         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
3715
3716         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
3717                 status = map_nt_error_from_unix(errno);
3718                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3719                                 nt_errstr(status), newname, oldname));
3720         }
3721
3722         return status;
3723 }
3724
3725 /****************************************************************************
3726  Reply to a TRANS2_SETFILEINFO (set file info by fileid).
3727 ****************************************************************************/
3728
3729 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3730                                         unsigned int tran_call,
3731                                         char **pparams, int total_params, char **ppdata, int total_data,
3732                                         unsigned int max_data_bytes)
3733 {
3734         char *params = *pparams;
3735         char *pdata = *ppdata;
3736         uint16 info_level;
3737         int dosmode=0;
3738         SMB_OFF_T size=0;
3739         struct utimbuf tvs;
3740         SMB_STRUCT_STAT sbuf;
3741         pstring fname;
3742         int fd = -1;
3743         BOOL bad_path = False;
3744         files_struct *fsp = NULL;
3745         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
3746         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
3747         mode_t unixmode = 0;
3748         NTSTATUS status = NT_STATUS_OK;
3749
3750         if (!params)
3751                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3752
3753         ZERO_STRUCT(sbuf);
3754         ZERO_STRUCT(tvs);
3755
3756         if (tran_call == TRANSACT2_SETFILEINFO) {
3757                 if (total_params < 4) {
3758                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3759                 }
3760
3761                 fsp = file_fsp(params,0);
3762                 info_level = SVAL(params,2);    
3763
3764                 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3765                         /*
3766                          * This is actually a SETFILEINFO on a directory
3767                          * handle (returned from an NT SMB). NT5.0 seems
3768                          * to do this call. JRA.
3769                          */
3770                         pstrcpy(fname, fsp->fsp_name);
3771                         if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
3772                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
3773                                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3774                         }
3775                 } else if (fsp && fsp->print_file) {
3776                         /*
3777                          * Doing a DELETE_ON_CLOSE should cancel a print job.
3778                          */
3779                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
3780                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
3781
3782                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
3783         
3784                                 SSVAL(params,0,0);
3785                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3786                                 return(-1);
3787                         } else
3788                                 return (UNIXERROR(ERRDOS,ERRbadpath));
3789             } else {
3790                         /*
3791                          * Original code - this is an open file.
3792                          */
3793                         CHECK_FSP(fsp,conn);
3794
3795                         pstrcpy(fname, fsp->fsp_name);
3796                         fd = fsp->fh->fd;
3797
3798                         if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
3799                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
3800                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3801                         }
3802                 }
3803         } else {
3804                 /* set path info */
3805                 if (total_params < 6) {
3806                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3807                 }
3808
3809                 info_level = SVAL(params,0);    
3810                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), -1, STR_TERMINATE, &status);
3811                 if (!NT_STATUS_IS_OK(status)) {
3812                         return ERROR_NT(status);
3813                 }
3814                 unix_convert(fname,conn,0,&bad_path,&sbuf);
3815                 if (bad_path) {
3816                         return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
3817                 }
3818
3819                 /*
3820                  * For CIFS UNIX extensions the target name may not exist.
3821                  */
3822
3823                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
3824                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
3825                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3826                 }    
3827
3828                 if(!check_name(fname, conn)) {
3829                         return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadpath);
3830                 }
3831
3832         }
3833
3834         if (!CAN_WRITE(conn))
3835                 return ERROR_DOS(ERRSRV,ERRaccess);
3836
3837         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3838                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3839         }
3840
3841         if (VALID_STAT(sbuf))
3842                 unixmode = sbuf.st_mode;
3843
3844         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
3845                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
3846
3847         /* Realloc the parameter size */
3848         *pparams = (char *)SMB_REALLOC(*pparams,2);
3849         if (*pparams == NULL) {
3850                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3851         }
3852         params = *pparams;
3853
3854         SSVAL(params,0,0);
3855
3856         if (fsp && fsp->pending_modtime) {
3857                 /* the pending modtime overrides the current modtime */
3858                 sbuf.st_mtime = fsp->pending_modtime;
3859         }
3860
3861         size = get_file_size(sbuf);
3862         tvs.modtime = sbuf.st_mtime;
3863         tvs.actime = sbuf.st_atime;
3864         dosmode = dos_mode(conn,fname,&sbuf);
3865         unixmode = sbuf.st_mode;
3866
3867         set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
3868         set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
3869
3870         switch (info_level) {
3871                 case SMB_INFO_STANDARD:
3872                 {
3873                         if (total_data < 12) {
3874                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3875                         }
3876
3877                         /* access time */
3878                         tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
3879                         /* write time */
3880                         tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
3881                         break;
3882                 }
3883
3884                 case SMB_INFO_SET_EA:
3885                 {
3886                         struct ea_list *ea_list = NULL;
3887                         TALLOC_CTX *ctx = NULL;
3888
3889                         if (total_data < 10) {
3890
3891                                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3892                                    length. They seem to have no effect. Bug #3212. JRA */
3893
3894                                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3895                                         /* We're done. We only get EA info in this call. */
3896                                         SSVAL(params,0,0);
3897                                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3898                                         return(-1);
3899                                 }
3900
3901                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3902                         }
3903
3904                         if (IVAL(pdata,0) > total_data) {
3905                                 DEBUG(10,("call_trans2setfilepathinfo: bad total data size (%u) > %u\n",
3906                                         IVAL(pdata,0), (unsigned int)total_data));
3907                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3908                         }
3909
3910                         ctx = talloc_init("SMB_INFO_SET_EA");
3911                         if (!ctx) {
3912                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3913                         }
3914                         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3915                         if (!ea_list) {
3916                                 talloc_destroy(ctx);
3917                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3918                         }
3919                         status = set_ea(conn, fsp, fname, ea_list);
3920                         talloc_destroy(ctx);
3921
3922                         if (!NT_STATUS_IS_OK(status)) {
3923                                 return ERROR_NT(status);
3924                         }
3925
3926                         /* We're done. We only get EA info in this call. */
3927                         SSVAL(params,0,0);
3928                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
3929                         return(-1);
3930                 }
3931
3932 #if 0
3933                 /* The following 2 info levels are only valid on query, not set. Remove them. JRA. */
3934                 /* XXXX um, i don't think this is right.
3935                         it's also not in the cifs6.txt spec.
3936                 */
3937                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3938                         if (total_data < 28)
3939                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3940
3941                         tvs.actime = make_unix_date2(pdata+8);
3942                         tvs.modtime = make_unix_date2(pdata+12);
3943                         size = IVAL(pdata,16);
3944                         dosmode = IVAL(pdata,24);
3945                         break;
3946
3947                 /* XXXX nor this.  not in cifs6.txt, either. */
3948                 case SMB_INFO_QUERY_ALL_EAS:
3949                         if (total_data < 28)
3950                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3951
3952                         tvs.actime = make_unix_date2(pdata+8);
3953                         tvs.modtime = make_unix_date2(pdata+12);
3954                         size = IVAL(pdata,16);
3955                         dosmode = IVAL(pdata,24);
3956                         break;
3957 #endif
3958
3959                 case SMB_SET_FILE_BASIC_INFO:
3960                 case SMB_FILE_BASIC_INFORMATION:
3961                 {
3962                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
3963                         time_t write_time;
3964                         time_t changed_time;
3965
3966                         if (total_data < 36) {
3967                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3968                         }
3969
3970                         /* Ignore create time at offset pdata. */
3971
3972                         /* access time */
3973                         tvs.actime = interpret_long_date(pdata+8);
3974
3975                         write_time = interpret_long_date(pdata+16);
3976                         changed_time = interpret_long_date(pdata+24);
3977
3978                         tvs.modtime = MIN(write_time, changed_time);
3979
3980                         if (write_time > tvs.modtime && write_time != (time_t)-1) {
3981                                 tvs.modtime = write_time;
3982                         }
3983                         /* Prefer a defined time to an undefined one. */
3984                         if (null_mtime(tvs.modtime)) {
3985                                 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
3986                         }
3987
3988                         /* attributes */
3989                         dosmode = IVAL(pdata,32);
3990                         break;
3991                 }
3992
3993                 case SMB_FILE_ALLOCATION_INFORMATION:
3994                 case SMB_SET_FILE_ALLOCATION_INFO:
3995                 {
3996                         int ret = -1;
3997                         SMB_BIG_UINT allocation_size;
3998
3999                         if (total_data < 8) {
4000                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4001                         }
4002
4003                         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4004 #ifdef LARGE_SMB_OFF_T
4005                         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4006 #else /* LARGE_SMB_OFF_T */
4007                         if (IVAL(pdata,4) != 0) {
4008                                 /* more than 32 bits? */
4009                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4010                         }
4011 #endif /* LARGE_SMB_OFF_T */
4012                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
4013                                         fname, (double)allocation_size ));
4014
4015                         if (allocation_size) {
4016                                 allocation_size = smb_roundup(conn, allocation_size);
4017                         }
4018
4019                         if(allocation_size != get_file_size(sbuf)) {
4020                                 SMB_STRUCT_STAT new_sbuf;
4021  
4022                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
4023                                         fname, (double)allocation_size ));
4024  
4025                                 if (fd == -1) {
4026                                         files_struct *new_fsp = NULL;
4027  
4028                                         status = open_file_ntcreate(conn, fname, &sbuf,
4029                                                                         FILE_WRITE_DATA,
4030                                                                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4031                                                                         FILE_OPEN,
4032                                                                         0,
4033                                                                         FILE_ATTRIBUTE_NORMAL,
4034                                                                         FORCE_OPLOCK_BREAK_TO_NONE,
4035                                                                         NULL, &new_fsp);
4036  
4037                                         if (!NT_STATUS_IS_OK(status)) {
4038                                                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4039                                                         /* We have re-scheduled this call. */
4040                                                         return -1;
4041                                                 }
4042                                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4043                                         }
4044                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
4045                                         if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
4046                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4047                                                                         new_fsp->fnum, strerror(errno)));
4048                                                 ret = -1;
4049                                         }
4050                                         close_file(new_fsp,NORMAL_CLOSE);
4051                                 } else {
4052                                         ret = vfs_allocate_file_space(fsp, allocation_size);
4053                                         if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
4054                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4055                                                                         fsp->fnum, strerror(errno)));
4056                                                 ret = -1;
4057                                         }
4058                                 }
4059                                 if (ret == -1)
4060                                         return ERROR_NT(NT_STATUS_DISK_FULL);
4061
4062                                 /* Allocate can truncate size... */
4063                                 size = get_file_size(new_sbuf);
4064                         }
4065
4066                         break;
4067                 }
4068
4069                 case SMB_FILE_END_OF_FILE_INFORMATION:
4070                 case SMB_SET_FILE_END_OF_FILE_INFO:
4071                 {
4072                         if (total_data < 8) {
4073                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4074                         }
4075
4076                         size = IVAL(pdata,0);
4077 #ifdef LARGE_SMB_OFF_T
4078                         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4079 #else /* LARGE_SMB_OFF_T */
4080                         if (IVAL(pdata,4) != 0) {
4081                                 /* more than 32 bits? */
4082                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4083                         }
4084 #endif /* LARGE_SMB_OFF_T */
4085                         DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
4086                         break;
4087                 }
4088
4089                 case SMB_FILE_DISPOSITION_INFORMATION:
4090                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
4091                 {
4092                         BOOL delete_on_close;
4093
4094                         if (total_data < 1) {
4095                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4096                         }
4097
4098                         delete_on_close = (CVAL(pdata,0) ? True : False);
4099
4100                         /* Just ignore this set on a path. */
4101                         if (tran_call != TRANSACT2_SETFILEINFO)
4102                                 break;
4103
4104                         if (fsp == NULL)
4105                                 return(UNIXERROR(ERRDOS,ERRbadfid));
4106
4107                         status = can_set_delete_on_close(fsp, delete_on_close,
4108                                                          dosmode);
4109  
4110                         if (!NT_STATUS_IS_OK(status)) {
4111                                 return ERROR_NT(status);
4112                         }
4113
4114                         /* The set is across all open files on this dev/inode pair. */
4115                         if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4116                                 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4117                         }
4118
4119                         SSVAL(params,0,0);
4120                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4121                         return(-1);
4122                 }
4123
4124                 case SMB_FILE_POSITION_INFORMATION:
4125                 {
4126                         SMB_BIG_UINT position_information;
4127
4128                         if (total_data < 8) {
4129                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4130                         }
4131
4132                         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4133 #ifdef LARGE_SMB_OFF_T
4134                         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4135 #else /* LARGE_SMB_OFF_T */
4136                         if (IVAL(pdata,4) != 0) {
4137                                 /* more than 32 bits? */
4138                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4139                         }
4140 #endif /* LARGE_SMB_OFF_T */
4141                         DEBUG(10,("call_trans2setfilepathinfo: Set file position information for file %s to %.0f\n",
4142                                         fname, (double)position_information ));
4143                         if (fsp) {
4144                                 fsp->fh->position_information = position_information;
4145                         }
4146
4147                         /* We're done. We only get position info in this call. */
4148                         SSVAL(params,0,0);
4149                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4150                         return(-1);
4151                 }
4152
4153                 /* From tridge Samba4 : 
4154                  * MODE_INFORMATION in setfileinfo (I have no
4155                  * idea what "mode information" on a file is - it takes a value of 0,
4156                  * 2, 4 or 6. What could it be?).
4157                  */
4158
4159                 case SMB_FILE_MODE_INFORMATION:
4160                 {
4161                         uint32 mode;
4162
4163                         if (total_data < 4) {
4164                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4165                         }
4166                         mode = IVAL(pdata,0);
4167                         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4168                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4169                         }
4170
4171                         /* We're done. We only get mode info in this call. */
4172                         SSVAL(params,0,0);
4173                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4174                         return(-1);
4175                 }
4176
4177                 /*
4178                  * CIFS UNIX extensions.
4179                  */
4180
4181                 case SMB_SET_FILE_UNIX_BASIC:
4182                 {
4183                         uint32 raw_unixmode;
4184
4185                         if (total_data < 100) {
4186                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4187                         }
4188
4189                         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4190                            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4191                                 size=IVAL(pdata,0); /* first 8 Bytes are size */
4192 #ifdef LARGE_SMB_OFF_T
4193                                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4194 #else /* LARGE_SMB_OFF_T */
4195                                 if (IVAL(pdata,4) != 0) {
4196                                         /* more than 32 bits? */
4197                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4198                                 }
4199 #endif /* LARGE_SMB_OFF_T */
4200                         }
4201                         pdata+=24;          /* ctime & st_blocks are not changed */
4202                         tvs.actime = interpret_long_date(pdata); /* access_time */
4203                         tvs.modtime = interpret_long_date(pdata+8); /* modification_time */
4204                         pdata+=16;
4205                         set_owner = (uid_t)IVAL(pdata,0);
4206                         pdata += 8;
4207                         set_grp = (gid_t)IVAL(pdata,0);
4208                         pdata += 8;
4209                         raw_unixmode = IVAL(pdata,28);
4210                         unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4211                         dosmode = 0; /* Ensure dos mode change doesn't override this. */
4212
4213                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4214 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4215                                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4216
4217                         if (!VALID_STAT(sbuf)) {
4218
4219                                 /*
4220                                  * The only valid use of this is to create character and block
4221                                  * devices, and named pipes. This is deprecated (IMHO) and 
4222                                  * a new info level should be used for mknod. JRA.
4223                                  */
4224
4225                                 uint32 file_type = IVAL(pdata,0);
4226 #if defined(HAVE_MAKEDEV)
4227                                 uint32 dev_major = IVAL(pdata,4);
4228                                 uint32 dev_minor = IVAL(pdata,12);
4229 #endif
4230
4231                                 uid_t myuid = geteuid();
4232                                 gid_t mygid = getegid();
4233                                 SMB_DEV_T dev = (SMB_DEV_T)0;
4234
4235                                 if (tran_call == TRANSACT2_SETFILEINFO)
4236                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
4237
4238                                 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4239                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4240                                 }
4241
4242 #if defined(HAVE_MAKEDEV)
4243                                 dev = makedev(dev_major, dev_minor);
4244 #endif
4245
4246                                 /* We can only create as the owner/group we are. */
4247
4248                                 if ((set_owner != myuid) && (set_owner != (uid_t)SMB_UID_NO_CHANGE))
4249                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
4250                                 if ((set_grp != mygid) && (set_grp != (gid_t)SMB_GID_NO_CHANGE))
4251                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
4252
4253                                 switch (file_type) {
4254 #if defined(S_IFIFO)
4255                                         case UNIX_TYPE_FIFO:
4256                                                 unixmode |= S_IFIFO;
4257                                                 break;
4258 #endif
4259 #if defined(S_IFSOCK)
4260                                         case UNIX_TYPE_SOCKET:
4261                                                 unixmode |= S_IFSOCK;
4262                                                 break;
4263 #endif
4264 #if defined(S_IFCHR)
4265                                         case UNIX_TYPE_CHARDEV:
4266                                                 unixmode |= S_IFCHR;
4267                                                 break;
4268 #endif
4269 #if defined(S_IFBLK)
4270                                         case UNIX_TYPE_BLKDEV:
4271                                                 unixmode |= S_IFBLK;
4272                                                 break;
4273 #endif
4274                                         default:
4275                                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4276                                 }
4277
4278                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4279 0%o for file %s\n", (double)dev, unixmode, fname ));
4280
4281                                 /* Ok - do the mknod. */
4282                                 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0)
4283                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4284
4285                                 inherit_access_acl(conn, fname, unixmode);
4286
4287                                 SSVAL(params,0,0);
4288                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4289                                 return(-1);
4290                         }
4291
4292                         /*
4293                          * Deal with the UNIX specific mode set.
4294                          */
4295
4296                         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4297                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4298                                         (unsigned int)unixmode, fname ));
4299                                 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4300                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4301                         }
4302
4303                         /*
4304                          * Deal with the UNIX specific uid set.
4305                          */
4306
4307                         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4308                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4309                                         (unsigned int)set_owner, fname ));
4310                                 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0)
4311                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4312                         }
4313
4314                         /*
4315                          * Deal with the UNIX specific gid set.
4316                          */
4317
4318                         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4319                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4320                                         (unsigned int)set_owner, fname ));
4321                                 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0)
4322                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4323                         }
4324                         break;
4325                 }
4326
4327                 case SMB_SET_FILE_UNIX_LINK:
4328                 {
4329                         pstring link_target;
4330                         char *newname = fname;
4331
4332                         /* Set a symbolic link. */
4333                         /* Don't allow this if follow links is false. */
4334
4335                         if (!lp_symlinks(SNUM(conn)))
4336                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4337
4338                         srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), -1, STR_TERMINATE);
4339
4340                         /* !widelinks forces the target path to be within the share. */
4341                         /* This means we can interpret the target as a pathname. */
4342                         if (!lp_widelinks(SNUM(conn))) {
4343                                 pstring rel_name;
4344                                 char *last_dirp = NULL;
4345
4346                                 unix_format(link_target);
4347                                 if (*link_target == '/') {
4348                                         /* No absolute paths allowed. */
4349                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4350                                 }
4351                                 pstrcpy(rel_name, newname);
4352                                 last_dirp = strrchr_m(rel_name, '/');
4353                                 if (last_dirp) {
4354                                         last_dirp[1] = '\0';
4355                                 } else {
4356                                         pstrcpy(rel_name, "./");
4357                                 }
4358                                 pstrcat(rel_name, link_target);
4359
4360                                 if (!check_name(rel_name, conn)) {
4361                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4362                                 }
4363                         }
4364
4365                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4366                                 fname, link_target ));
4367
4368                         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0)
4369                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4370                         SSVAL(params,0,0);
4371                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4372                         return(-1);
4373                 }
4374
4375                 case SMB_SET_FILE_UNIX_HLINK:
4376                 {
4377                         pstring oldname;
4378                         char *newname = fname;
4379
4380                         /* Set a hard link. */
4381                         srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), -1, STR_TERMINATE, &status);
4382                         if (!NT_STATUS_IS_OK(status)) {
4383                                 return ERROR_NT(status);
4384                         }
4385
4386                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4387                                 fname, oldname));
4388
4389                         status = hardlink_internals(conn, oldname, newname);
4390                         if (!NT_STATUS_IS_OK(status)) {
4391                                 return ERROR_NT(status);
4392                         }
4393
4394                         SSVAL(params,0,0);
4395                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4396                         return(-1);
4397                 }
4398
4399                 case SMB_FILE_RENAME_INFORMATION:
4400                 {
4401                         BOOL overwrite;
4402                         /* uint32 root_fid; */  /* Not used */
4403                         uint32 len;
4404                         pstring newname;
4405                         pstring base_name;
4406                         char *p;
4407
4408                         if (total_data < 12) {
4409                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4410                         }
4411
4412                         overwrite = (CVAL(pdata,0) ? True : False);
4413                         /* root_fid = IVAL(pdata,4); */
4414                         len = IVAL(pdata,8);
4415                         srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4416                         if (!NT_STATUS_IS_OK(status)) {
4417                                 return ERROR_NT(status);
4418                         }
4419
4420                         /* Check the new name has no '/' characters. */
4421                         if (strchr_m(newname, '/'))
4422                                 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4423
4424                         RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
4425
4426                         /* Create the base directory. */
4427                         pstrcpy(base_name, fname);
4428                         p = strrchr_m(base_name, '/');
4429                         if (p)
4430                                 *p = '\0';
4431                         /* Append the new name. */
4432                         pstrcat(base_name, "/");
4433                         pstrcat(base_name, newname);
4434
4435                         if (fsp) {
4436                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4437                                         fsp->fnum, fsp->fsp_name, base_name ));
4438                                 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4439                         } else {
4440                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4441                                         fname, newname ));
4442                                 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4443                         }
4444                         if (!NT_STATUS_IS_OK(status)) {
4445                                 return ERROR_NT(status);
4446                         }
4447                         process_pending_change_notify_queue((time_t)0);
4448                         SSVAL(params,0,0);
4449                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4450                         return(-1);
4451                 }
4452
4453 #if defined(HAVE_POSIX_ACLS)
4454                 case SMB_SET_POSIX_ACL:
4455                 {
4456                         uint16 posix_acl_version;
4457                         uint16 num_file_acls;
4458                         uint16 num_def_acls;
4459                         BOOL valid_file_acls = True;
4460                         BOOL valid_def_acls = True;
4461
4462                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4463                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4464                         }
4465                         posix_acl_version = SVAL(pdata,0);
4466                         num_file_acls = SVAL(pdata,2);
4467                         num_def_acls = SVAL(pdata,4);
4468
4469                         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4470                                 valid_file_acls = False;
4471                                 num_file_acls = 0;
4472                         }
4473
4474                         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4475                                 valid_def_acls = False;
4476                                 num_def_acls = 0;
4477                         }
4478
4479                         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4480                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4481                         }
4482
4483                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4484                                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4485                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4486                         }
4487
4488                         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4489                                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4490                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4491                         }
4492
4493                         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4494                                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
4495                                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4496                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4497                         }
4498
4499                         SSVAL(params,0,0);
4500                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4501                         return(-1);
4502                 }
4503 #endif
4504
4505                 case SMB_SET_POSIX_LOCK:
4506                 {
4507                         SMB_BIG_UINT count;
4508                         SMB_BIG_UINT offset;
4509                         uint32 lock_pid;
4510                         BOOL blocking_lock = False;
4511                         enum brl_type lock_type;
4512
4513                         if (fsp == NULL || fsp->fh->fd == -1) {
4514                                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4515                         }
4516
4517                         if (total_data != POSIX_LOCK_DATA_SIZE) {
4518                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4519                         }
4520
4521                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4522                                 case POSIX_LOCK_TYPE_READ:
4523                                         lock_type = READ_LOCK;
4524                                         break;
4525                                 case POSIX_LOCK_TYPE_WRITE:
4526                                         /* Return the right POSIX-mappable error code for files opened read-only. */
4527                                         if (!fsp->can_write) {
4528                                                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4529                                         }
4530                                         lock_type = WRITE_LOCK;
4531                                         break;
4532                                 case POSIX_LOCK_TYPE_UNLOCK:
4533                                         lock_type = UNLOCK_LOCK;
4534                                         break;
4535                                 default:
4536                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4537                         }
4538
4539                         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4540                                 blocking_lock = False;
4541                         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4542                                 blocking_lock = True;
4543                         } else {
4544                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4545                         }
4546
4547                         if (!lp_blocking_locks(SNUM(conn))) { 
4548                                 blocking_lock = False;
4549                         }
4550
4551                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4552 #if defined(HAVE_LONGLONG)
4553                         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4554                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4555                         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4556                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4557 #else /* HAVE_LONGLONG */
4558                         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4559                         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4560 #endif /* HAVE_LONGLONG */
4561
4562                         if (lock_type == UNLOCK_LOCK) {
4563                                 status = do_unlock(fsp,
4564                                                 lock_pid,
4565                                                 count,
4566                                                 offset,
4567                                                 POSIX_LOCK);
4568                         } else {
4569                                 struct byte_range_lock *br_lck = do_lock(fsp,
4570                                                                         lock_pid,
4571                                                                         count,
4572                                                                         offset,
4573                                                                         lock_type,
4574                                                                         blocking_lock,
4575                                                                         POSIX_LOCK,
4576                                                                         &status);
4577
4578                                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4579                                         /*
4580                                          * A blocking lock was requested. Package up
4581                                          * this smb into a queued request and push it
4582                                          * onto the blocking lock queue.
4583                                          */
4584                                         if(push_blocking_lock_request(br_lck,
4585                                                                 inbuf, length,
4586                                                                 fsp,
4587                                                                 -1, /* infinite timeout. */
4588                                                                 0,
4589                                                                 lock_pid,
4590                                                                 lock_type,
4591                                                                 POSIX_LOCK,
4592                                                                 offset,
4593                                                                 count)) {
4594                                                 TALLOC_FREE(br_lck);
4595                                                 return -1;
4596                                         }
4597                                 }
4598                                 TALLOC_FREE(br_lck);
4599                         }
4600
4601                         if (!NT_STATUS_IS_OK(status)) {
4602                                 return ERROR_NT(status);
4603                         }
4604
4605                         SSVAL(params,0,0);
4606                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4607                         return(-1);
4608                 }
4609
4610                 default:
4611                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4612         }
4613
4614         /* get some defaults (no modifications) if any info is zero or -1. */
4615         if (null_mtime(tvs.actime)) {
4616                 tvs.actime = sbuf.st_atime;
4617         }
4618
4619         if (null_mtime(tvs.modtime)) {
4620                 tvs.modtime = sbuf.st_mtime;
4621         }
4622
4623         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4624         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4625         DEBUG(6,("size: %.0f ", (double)size));
4626
4627         if (dosmode) {
4628                 if (S_ISDIR(sbuf.st_mode))
4629                         dosmode |= aDIR;
4630                 else
4631                         dosmode &= ~aDIR;
4632         }
4633
4634         DEBUG(6,("dosmode: %x\n"  , dosmode));
4635
4636         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4637                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4638                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4639                 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4640
4641                 /*
4642                  * Only do this test if we are not explicitly
4643                  * changing the size of a file.
4644                  */
4645                 if (!size)
4646                         size = get_file_size(sbuf);
4647         }
4648
4649         /*
4650          * Try and set the times, size and mode of this file -
4651          * if they are different from the current values
4652          */
4653
4654         /* check the mode isn't different, before changing it */
4655         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4656
4657                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4658
4659                 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4660                         DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4661                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4662                 }
4663         }
4664
4665         /* Now the size. */
4666         if (size != get_file_size(sbuf)) {
4667
4668                 int ret;
4669
4670                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4671                         fname, (double)size ));
4672
4673                 if (fd == -1) {
4674                         files_struct *new_fsp = NULL;
4675
4676                         status = open_file_ntcreate(conn, fname, &sbuf,
4677                                                 FILE_WRITE_DATA,
4678                                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4679                                                 FILE_OPEN,
4680                                                 0,
4681                                                 FILE_ATTRIBUTE_NORMAL,
4682                                                 FORCE_OPLOCK_BREAK_TO_NONE,
4683                                                 NULL, &new_fsp);
4684         
4685                         if (!NT_STATUS_IS_OK(status)) {
4686                                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4687                                         /* We have re-scheduled this call. */
4688                                         return -1;
4689                                 }
4690                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4691                         }
4692                         ret = vfs_set_filelen(new_fsp, size);
4693                         close_file(new_fsp,NORMAL_CLOSE);
4694                 } else {
4695                         ret = vfs_set_filelen(fsp, size);
4696                 }
4697
4698                 if (ret == -1) {
4699                         return (UNIXERROR(ERRHRD,ERRdiskfull));
4700                 }
4701         }
4702
4703         /*
4704          * Finally the times.
4705          */
4706         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4707                 if(fsp != NULL) {
4708                         /*
4709                          * This was a setfileinfo on an open file.
4710                          * NT does this a lot. We also need to 
4711                          * set the time here, as it can be read by 
4712                          * FindFirst/FindNext and with the patch for bug #2045
4713                          * in smbd/fileio.c it ensures that this timestamp is
4714                          * kept sticky even after a write. We save the request
4715                          * away and will set it on file close and after a write. JRA.
4716                          */
4717
4718                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4719                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4720                                 fsp_set_pending_modtime(fsp, tvs.modtime);
4721                         }
4722
4723                 }
4724                 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4725
4726                 if(file_utime(conn, fname, &tvs)!=0) {
4727                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4728                 }
4729         }
4730
4731         SSVAL(params,0,0);
4732         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4733   
4734         return(-1);
4735 }
4736
4737 /****************************************************************************
4738  Reply to a TRANS2_MKDIR (make directory with extended attributes).
4739 ****************************************************************************/
4740
4741 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4742                                         char **pparams, int total_params, char **ppdata, int total_data,
4743                                         unsigned int max_data_bytes)
4744 {
4745         char *params = *pparams;
4746         char *pdata = *ppdata;
4747         pstring directory;
4748         int ret = -1;
4749         SMB_STRUCT_STAT sbuf;
4750         BOOL bad_path = False;
4751         NTSTATUS status = NT_STATUS_OK;
4752         TALLOC_CTX *ctx = NULL;
4753         struct ea_list *ea_list = NULL;
4754
4755         if (!CAN_WRITE(conn))
4756                 return ERROR_DOS(ERRSRV,ERRaccess);
4757
4758         if (total_params < 4) {
4759                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4760         }
4761
4762         srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), -1, STR_TERMINATE, &status);
4763         if (!NT_STATUS_IS_OK(status)) {
4764                 return ERROR_NT(status);
4765         }
4766
4767         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4768
4769         unix_convert(directory,conn,0,&bad_path,&sbuf);
4770         if (bad_path) {
4771                 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
4772         }
4773
4774         /* Any data in this call is an EA list. */
4775         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
4776                 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
4777         }
4778
4779         /*
4780          * OS/2 workplace shell seems to send SET_EA requests of "null"
4781          * length (4 bytes containing IVAL 4).
4782          * They seem to have no effect. Bug #3212. JRA.
4783          */
4784
4785         if (total_data != 4) {
4786                 if (total_data < 10) {
4787                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4788                 }
4789
4790                 if (IVAL(pdata,0) > total_data) {
4791                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
4792                                 IVAL(pdata,0), (unsigned int)total_data));
4793                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4794                 }
4795
4796                 ctx = talloc_init("TRANS2_MKDIR_SET_EA");
4797                 if (!ctx) {
4798                         return ERROR_NT(NT_STATUS_NO_MEMORY);
4799                 }
4800                 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4801                 if (!ea_list) {
4802                         talloc_destroy(ctx);
4803                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4804                 }
4805         } else if (IVAL(pdata,0) != 4) {
4806                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4807         }
4808
4809         if (check_name(directory,conn)) {
4810                 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory,True));
4811         }
4812   
4813         if(ret < 0) {
4814                 talloc_destroy(ctx);
4815                 DEBUG(5,("call_trans2mkdir error (%s)\n", strerror(errno)));
4816                 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRnoaccess);
4817         }
4818
4819         /* Try and set any given EA. */
4820         if (total_data) {
4821                 status = set_ea(conn, NULL, directory, ea_list);
4822                 talloc_destroy(ctx);
4823                 if (!NT_STATUS_IS_OK(status)) {
4824                         return ERROR_NT(status);
4825                 }
4826         }
4827
4828         /* Realloc the parameter and data sizes */
4829         *pparams = (char *)SMB_REALLOC(*pparams,2);
4830         if(*pparams == NULL) {
4831                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4832         }
4833         params = *pparams;
4834
4835         SSVAL(params,0,0);
4836
4837         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
4838   
4839         return(-1);
4840 }
4841
4842 /****************************************************************************
4843  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
4844  We don't actually do this - we just send a null response.
4845 ****************************************************************************/
4846
4847 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4848                                         char **pparams, int total_params, char **ppdata, int total_data,
4849                                         unsigned int max_data_bytes)
4850 {
4851         static uint16 fnf_handle = 257;
4852         char *params = *pparams;
4853         uint16 info_level;
4854
4855         if (total_params < 6) {
4856                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4857         }
4858
4859         info_level = SVAL(params,4);
4860         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
4861
4862         switch (info_level) {
4863                 case 1:
4864                 case 2:
4865                         break;
4866                 default:
4867                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4868         }
4869
4870         /* Realloc the parameter and data sizes */
4871         *pparams = (char *)SMB_REALLOC(*pparams,6);
4872         if (*pparams == NULL) {
4873                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4874         }
4875         params = *pparams;
4876
4877         SSVAL(params,0,fnf_handle);
4878         SSVAL(params,2,0); /* No changes */
4879         SSVAL(params,4,0); /* No EA errors */
4880
4881         fnf_handle++;
4882
4883         if(fnf_handle == 0)
4884                 fnf_handle = 257;
4885
4886         send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0);
4887   
4888         return(-1);
4889 }
4890
4891 /****************************************************************************
4892  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
4893  changes). Currently this does nothing.
4894 ****************************************************************************/
4895
4896 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4897                                         char **pparams, int total_params, char **ppdata, int total_data,
4898                                         unsigned int max_data_bytes)
4899 {
4900         char *params = *pparams;
4901
4902         DEBUG(3,("call_trans2findnotifynext\n"));
4903
4904         /* Realloc the parameter and data sizes */
4905         *pparams = (char *)SMB_REALLOC(*pparams,4);
4906         if (*pparams == NULL) {
4907                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4908         }
4909         params = *pparams;
4910
4911         SSVAL(params,0,0); /* No changes */
4912         SSVAL(params,2,0); /* No EA errors */
4913
4914         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0);
4915   
4916         return(-1);
4917 }
4918
4919 /****************************************************************************
4920  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
4921 ****************************************************************************/
4922
4923 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4924                                         char **pparams, int total_params, char **ppdata, int total_data,
4925                                         unsigned int max_data_bytes)
4926 {
4927         char *params = *pparams;
4928         pstring pathname;
4929         int reply_size = 0;
4930         int max_referral_level;
4931
4932         DEBUG(10,("call_trans2getdfsreferral\n"));
4933
4934         if (total_params < 2) {
4935                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4936         }
4937
4938         max_referral_level = SVAL(params,0);
4939
4940         if(!lp_host_msdfs())
4941                 return ERROR_DOS(ERRDOS,ERRbadfunc);
4942
4943         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), -1, STR_TERMINATE);
4944         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
4945                 return UNIXERROR(ERRDOS,ERRbadfile);
4946     
4947         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
4948         send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size);
4949
4950         return(-1);
4951 }
4952
4953 #define LMCAT_SPL       0x53
4954 #define LMFUNC_GETJOBID 0x60
4955
4956 /****************************************************************************
4957  Reply to a TRANS2_IOCTL - used for OS/2 printing.
4958 ****************************************************************************/
4959
4960 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
4961                                         char **pparams, int total_params, char **ppdata, int total_data,
4962                                         unsigned int max_data_bytes)
4963 {
4964         char *pdata = *ppdata;
4965         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
4966
4967         /* check for an invalid fid before proceeding */
4968         
4969         if (!fsp)                                
4970                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
4971
4972         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
4973                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
4974                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
4975                 if (*ppdata == NULL) {
4976                         return ERROR_NT(NT_STATUS_NO_MEMORY);
4977                 }
4978                 pdata = *ppdata;
4979
4980                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
4981                         CAN ACCEPT THIS IN UNICODE. JRA. */
4982
4983                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
4984                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
4985                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
4986                 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32);
4987                 return(-1);
4988         } else {
4989                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
4990                 return ERROR_DOS(ERRSRV,ERRerror);
4991         }
4992 }
4993
4994 /****************************************************************************
4995  Reply to a SMBfindclose (stop trans2 directory search).
4996 ****************************************************************************/
4997
4998 int reply_findclose(connection_struct *conn,
4999                     char *inbuf,char *outbuf,int length,int bufsize)
5000 {
5001         int outsize = 0;
5002         int dptr_num=SVALS(inbuf,smb_vwv0);
5003         START_PROFILE(SMBfindclose);
5004
5005         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
5006
5007         dptr_close(&dptr_num);
5008
5009         outsize = set_message(outbuf,0,0,False);
5010
5011         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
5012
5013         END_PROFILE(SMBfindclose);
5014         return(outsize);
5015 }
5016
5017 /****************************************************************************
5018  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
5019 ****************************************************************************/
5020
5021 int reply_findnclose(connection_struct *conn, 
5022                      char *inbuf,char *outbuf,int length,int bufsize)
5023 {
5024         int outsize = 0;
5025         int dptr_num= -1;
5026         START_PROFILE(SMBfindnclose);
5027         
5028         dptr_num = SVAL(inbuf,smb_vwv0);
5029
5030         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
5031
5032         /* We never give out valid handles for a 
5033            findnotifyfirst - so any dptr_num is ok here. 
5034            Just ignore it. */
5035
5036         outsize = set_message(outbuf,0,0,False);
5037
5038         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
5039
5040         END_PROFILE(SMBfindnclose);
5041         return(outsize);
5042 }
5043
5044 int handle_trans2(connection_struct *conn,
5045                   struct trans_state *state,
5046                   char *inbuf, char *outbuf, int size, int bufsize)
5047 {
5048         int outsize;
5049
5050         if (Protocol >= PROTOCOL_NT1) {
5051                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5052         }
5053
5054         /* Now we must call the relevant TRANS2 function */
5055         switch(state->call)  {
5056         case TRANSACT2_OPEN:
5057         {
5058                 START_PROFILE_NESTED(Trans2_open);
5059                 outsize = call_trans2open(
5060                         conn, inbuf, outbuf, bufsize, 
5061                         &state->param, state->total_param,
5062                         &state->data, state->total_data,
5063                         state->max_data_return);
5064                 END_PROFILE_NESTED(Trans2_open);
5065                 break;
5066         }
5067
5068         case TRANSACT2_FINDFIRST:
5069         {
5070                 START_PROFILE_NESTED(Trans2_findfirst);
5071                 outsize = call_trans2findfirst(
5072                         conn, inbuf, outbuf, bufsize,
5073                         &state->param, state->total_param,
5074                         &state->data, state->total_data,
5075                         state->max_data_return);
5076                 END_PROFILE_NESTED(Trans2_findfirst);
5077                 break;
5078         }
5079
5080         case TRANSACT2_FINDNEXT:
5081         {
5082                 START_PROFILE_NESTED(Trans2_findnext);
5083                 outsize = call_trans2findnext(
5084                         conn, inbuf, outbuf, size, bufsize, 
5085                         &state->param, state->total_param,
5086                         &state->data, state->total_data,
5087                         state->max_data_return);
5088                 END_PROFILE_NESTED(Trans2_findnext);
5089                 break;
5090         }
5091
5092         case TRANSACT2_QFSINFO:
5093         {
5094                 START_PROFILE_NESTED(Trans2_qfsinfo);
5095                 outsize = call_trans2qfsinfo(
5096                         conn, inbuf, outbuf, size, bufsize,
5097                         &state->param, state->total_param,
5098                         &state->data, state->total_data,
5099                         state->max_data_return);
5100                 END_PROFILE_NESTED(Trans2_qfsinfo);
5101             break;
5102         }
5103
5104         case TRANSACT2_SETFSINFO:
5105         {
5106                 START_PROFILE_NESTED(Trans2_setfsinfo);
5107                 outsize = call_trans2setfsinfo(
5108                         conn, inbuf, outbuf, size, bufsize, 
5109                         &state->param, state->total_param,
5110                         &state->data, state->total_data,
5111                         state->max_data_return);
5112                 END_PROFILE_NESTED(Trans2_setfsinfo);
5113                 break;
5114         }
5115
5116         case TRANSACT2_QPATHINFO:
5117         case TRANSACT2_QFILEINFO:
5118         {
5119                 START_PROFILE_NESTED(Trans2_qpathinfo);
5120                 outsize = call_trans2qfilepathinfo(
5121                         conn, inbuf, outbuf, size, bufsize, state->call,
5122                         &state->param, state->total_param,
5123                         &state->data, state->total_data,
5124                         state->max_data_return);
5125                 END_PROFILE_NESTED(Trans2_qpathinfo);
5126                 break;
5127         }
5128
5129         case TRANSACT2_SETPATHINFO:
5130         case TRANSACT2_SETFILEINFO:
5131         {
5132                 START_PROFILE_NESTED(Trans2_setpathinfo);
5133                 outsize = call_trans2setfilepathinfo(
5134                         conn, inbuf, outbuf, size, bufsize, state->call,
5135                         &state->param, state->total_param,
5136                         &state->data, state->total_data,
5137                         state->max_data_return);
5138                 END_PROFILE_NESTED(Trans2_setpathinfo);
5139                 break;
5140         }
5141
5142         case TRANSACT2_FINDNOTIFYFIRST:
5143         {
5144                 START_PROFILE_NESTED(Trans2_findnotifyfirst);
5145                 outsize = call_trans2findnotifyfirst(
5146                         conn, inbuf, outbuf, size, bufsize, 
5147                         &state->param, state->total_param,
5148                         &state->data, state->total_data,
5149                         state->max_data_return);
5150                 END_PROFILE_NESTED(Trans2_findnotifyfirst);
5151                 break;
5152         }
5153
5154         case TRANSACT2_FINDNOTIFYNEXT:
5155         {
5156                 START_PROFILE_NESTED(Trans2_findnotifynext);
5157                 outsize = call_trans2findnotifynext(
5158                         conn, inbuf, outbuf, size, bufsize, 
5159                         &state->param, state->total_param,
5160                         &state->data, state->total_data,
5161                         state->max_data_return);
5162                 END_PROFILE_NESTED(Trans2_findnotifynext);
5163                 break;
5164         }
5165
5166         case TRANSACT2_MKDIR:
5167         {
5168                 START_PROFILE_NESTED(Trans2_mkdir);
5169                 outsize = call_trans2mkdir(
5170                         conn, inbuf, outbuf, size, bufsize,
5171                         &state->param, state->total_param,
5172                         &state->data, state->total_data,
5173                         state->max_data_return);
5174                 END_PROFILE_NESTED(Trans2_mkdir);
5175                 break;
5176         }
5177
5178         case TRANSACT2_GET_DFS_REFERRAL:
5179         {
5180                 START_PROFILE_NESTED(Trans2_get_dfs_referral);
5181                 outsize = call_trans2getdfsreferral(
5182                         conn, inbuf, outbuf, size, bufsize,
5183                         &state->param, state->total_param,
5184                         &state->data, state->total_data,
5185                         state->max_data_return);
5186                 END_PROFILE_NESTED(Trans2_get_dfs_referral);
5187                 break;
5188         }
5189
5190         case TRANSACT2_IOCTL:
5191         {
5192                 START_PROFILE_NESTED(Trans2_ioctl);
5193                 outsize = call_trans2ioctl(
5194                         conn, inbuf, outbuf, size, bufsize,
5195                         &state->param, state->total_param,
5196                         &state->data, state->total_data,
5197                         state->max_data_return);
5198                 END_PROFILE_NESTED(Trans2_ioctl);
5199                 break;
5200         }
5201
5202         default:
5203                 /* Error in request */
5204                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5205                 outsize = ERROR_DOS(ERRSRV,ERRerror);
5206         }
5207
5208         return outsize;
5209 }
5210
5211 /****************************************************************************
5212  Reply to a SMBtrans2.
5213  ****************************************************************************/
5214
5215 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
5216                  int size, int bufsize)
5217 {
5218         int outsize = 0;
5219         unsigned int dsoff = SVAL(inbuf, smb_dsoff);
5220         unsigned int dscnt = SVAL(inbuf, smb_dscnt);
5221         unsigned int psoff = SVAL(inbuf, smb_psoff);
5222         unsigned int pscnt = SVAL(inbuf, smb_pscnt);
5223         unsigned int tran_call = SVAL(inbuf, smb_setup0);
5224         struct trans_state *state;
5225         NTSTATUS result;
5226
5227         START_PROFILE(SMBtrans2);
5228
5229         result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
5230         if (!NT_STATUS_IS_OK(result)) {
5231                 DEBUG(2, ("Got invalid trans2 request: %s\n",
5232                           nt_errstr(result)));
5233                 END_PROFILE(SMBtrans2);
5234                 return ERROR_NT(result);
5235         }
5236
5237         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
5238             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
5239                 END_PROFILE(SMBtrans2);
5240                 return ERROR_DOS(ERRSRV,ERRaccess);
5241         }
5242
5243         if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) {
5244                 DEBUG(0, ("talloc failed\n"));
5245                 END_PROFILE(SMBtrans2);
5246                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5247         }
5248
5249         state->cmd = SMBtrans2;
5250
5251         state->mid = SVAL(inbuf, smb_mid);
5252         state->vuid = SVAL(inbuf, smb_uid);
5253         state->setup_count = SVAL(inbuf, smb_suwcnt);
5254         state->total_param = SVAL(inbuf, smb_tpscnt);
5255         state->param = NULL;
5256         state->total_data =  SVAL(inbuf, smb_tdscnt);
5257         state->data = NULL;
5258         state->max_param_return = SVAL(inbuf, smb_mprcnt);
5259         state->max_data_return  = SVAL(inbuf, smb_mdrcnt);
5260         state->max_setup_return = SVAL(inbuf, smb_msrcnt);
5261         state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
5262         state->one_way = BITSETW(inbuf+smb_vwv5,1);
5263
5264         state->call = tran_call;
5265
5266         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5267            is so as a sanity check */
5268         if (state->setup_count != 1) {
5269                 /*
5270                  * Need to have rc=0 for ioctl to get job id for OS/2.
5271                  *  Network printing will fail if function is not successful.
5272                  *  Similar function in reply.c will be used if protocol
5273                  *  is LANMAN1.0 instead of LM1.2X002.
5274                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
5275                  *  outbuf doesn't have to be set(only job id is used).
5276                  */
5277                 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
5278                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5279                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5280                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5281                 } else {
5282                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5283                         DEBUG(2,("Transaction is %d\n",tran_call));
5284                         TALLOC_FREE(state);
5285                         END_PROFILE(SMBtrans2);
5286                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5287                 }
5288         }
5289
5290         if ((dscnt > state->total_data) || (pscnt > state->total_param))
5291                 goto bad_param;
5292
5293         if (state->total_data) {
5294                 /* Can't use talloc here, the core routines do realloc on the
5295                  * params and data. */
5296                 state->data = (char *)SMB_MALLOC(state->total_data);
5297                 if (state->data == NULL) {
5298                         DEBUG(0,("reply_trans2: data malloc fail for %u "
5299                                  "bytes !\n", (unsigned int)state->total_data));
5300                         TALLOC_FREE(state);
5301                         END_PROFILE(SMBtrans2);
5302                         return(ERROR_DOS(ERRDOS,ERRnomem));
5303                 }
5304                 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
5305                         goto bad_param;
5306                 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
5307                     (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
5308                         goto bad_param;
5309
5310                 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
5311         }
5312
5313         if (state->total_param) {
5314                 /* Can't use talloc here, the core routines do realloc on the
5315                  * params and data. */
5316                 state->param = (char *)SMB_MALLOC(state->total_param);
5317                 if (state->param == NULL) {
5318                         DEBUG(0,("reply_trans: param malloc fail for %u "
5319                                  "bytes !\n", (unsigned int)state->total_param));
5320                         SAFE_FREE(state->data);
5321                         TALLOC_FREE(state);
5322                         END_PROFILE(SMBtrans2);
5323                         return(ERROR_DOS(ERRDOS,ERRnomem));
5324                 } 
5325                 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
5326                         goto bad_param;
5327                 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
5328                     (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
5329                         goto bad_param;
5330
5331                 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
5332         }
5333
5334         state->received_data  = dscnt;
5335         state->received_param = pscnt;
5336
5337         if ((state->received_param == state->total_param) &&
5338             (state->received_data == state->total_data)) {
5339
5340                 outsize = handle_trans2(conn, state, inbuf, outbuf,
5341                                         size, bufsize);
5342                 SAFE_FREE(state->data);
5343                 SAFE_FREE(state->param);
5344                 TALLOC_FREE(state);
5345                 END_PROFILE(SMBtrans2);
5346                 return outsize;
5347         }
5348
5349         DLIST_ADD(conn->pending_trans, state);
5350
5351         /* We need to send an interim response then receive the rest
5352            of the parameter/data bytes */
5353         outsize = set_message(outbuf,0,0,False);
5354         show_msg(outbuf);
5355         END_PROFILE(SMBtrans2);
5356         return outsize;
5357
5358   bad_param:
5359
5360         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5361         SAFE_FREE(state->data);
5362         SAFE_FREE(state->param);
5363         TALLOC_FREE(state);
5364         END_PROFILE(SMBtrans2);
5365         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5366 }
5367
5368
5369 /****************************************************************************
5370  Reply to a SMBtranss2
5371  ****************************************************************************/
5372
5373 int reply_transs2(connection_struct *conn,
5374                   char *inbuf,char *outbuf,int size,int bufsize)
5375 {
5376         int outsize = 0;
5377         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5378         struct trans_state *state;
5379
5380         START_PROFILE(SMBtranss2);
5381
5382         show_msg(inbuf);
5383
5384         for (state = conn->pending_trans; state != NULL;
5385              state = state->next) {
5386                 if (state->mid == SVAL(inbuf,smb_mid)) {
5387                         break;
5388                 }
5389         }
5390
5391         if ((state == NULL) || (state->cmd != SMBtrans2)) {
5392                 END_PROFILE(SMBtranss2);
5393                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5394         }
5395
5396         /* Revise state->total_param and state->total_data in case they have
5397            changed downwards */
5398
5399         if (SVAL(inbuf, smb_tpscnt) < state->total_param)
5400                 state->total_param = SVAL(inbuf, smb_tpscnt);
5401         if (SVAL(inbuf, smb_tdscnt) < state->total_data)
5402                 state->total_data = SVAL(inbuf, smb_tdscnt);
5403
5404         pcnt = SVAL(inbuf, smb_spscnt);
5405         poff = SVAL(inbuf, smb_spsoff);
5406         pdisp = SVAL(inbuf, smb_spsdisp);
5407
5408         dcnt = SVAL(inbuf, smb_sdscnt);
5409         doff = SVAL(inbuf, smb_sdsoff);
5410         ddisp = SVAL(inbuf, smb_sdsdisp);
5411
5412         state->received_param += pcnt;
5413         state->received_data += dcnt;
5414                 
5415         if ((state->received_data > state->total_data) ||
5416             (state->received_param > state->total_param))
5417                 goto bad_param;
5418
5419         if (pcnt) {
5420                 if (pdisp+pcnt > state->total_param)
5421                         goto bad_param;
5422                 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
5423                         goto bad_param;
5424                 if (pdisp > state->total_param)
5425                         goto bad_param;
5426                 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
5427                     (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
5428                         goto bad_param;
5429                 if (state->param + pdisp < state->param)
5430                         goto bad_param;
5431
5432                 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
5433                        pcnt);
5434         }
5435
5436         if (dcnt) {
5437                 if (ddisp+dcnt > state->total_data)
5438                         goto bad_param;
5439                 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
5440                         goto bad_param;
5441                 if (ddisp > state->total_data)
5442                         goto bad_param;
5443                 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
5444                     (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
5445                         goto bad_param;
5446                 if (state->data + ddisp < state->data)
5447                         goto bad_param;
5448
5449                 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
5450                        dcnt);      
5451         }
5452
5453         if ((state->received_param < state->total_param) ||
5454             (state->received_data < state->total_data)) {
5455                 END_PROFILE(SMBtranss2);
5456                 return -1;
5457         }
5458
5459         /* construct_reply_common has done us the favor to pre-fill the
5460          * command field with SMBtranss2 which is wrong :-)
5461          */
5462         SCVAL(outbuf,smb_com,SMBtrans2);
5463
5464         outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
5465
5466         DLIST_REMOVE(conn->pending_trans, state);
5467         SAFE_FREE(state->data);
5468         SAFE_FREE(state->param);
5469         TALLOC_FREE(state);
5470
5471         if (outsize == 0) {
5472                 END_PROFILE(SMBtranss2);
5473                 return(ERROR_DOS(ERRSRV,ERRnosupport));
5474         }
5475         
5476         END_PROFILE(SMBtranss2);
5477         return(outsize);
5478
5479   bad_param:
5480
5481         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5482         DLIST_REMOVE(conn->pending_trans, state);
5483         SAFE_FREE(state->data);
5484         SAFE_FREE(state->param);
5485         TALLOC_FREE(state);
5486         END_PROFILE(SMBtranss2);
5487         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5488 }