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