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