r21057: More refactoring into functions.
[amitay/samba.git] / source3 / smbd / trans2.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB transaction2 handling
4    Copyright (C) Jeremy Allison                 1994-2003
5    Copyright (C) Stefan (metze) Metzmacher      2003
6    Copyright (C) Volker Lendecke                2005
7    Copyright (C) Steve French                   2005
8
9    Extensively modified by Andrew Tridgell, 1995
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 #include "includes.h"
27
28 extern int max_send;
29 extern enum protocol_types Protocol;
30 extern int smb_read_error;
31 extern uint32 global_client_caps;
32 extern struct current_user current_user;
33
34 #define get_file_size(sbuf) ((sbuf).st_size)
35 #define DIR_ENTRY_SAFETY_MARGIN 4096
36
37 /********************************************************************
38  Roundup a value to the nearest allocation roundup size boundary.
39  Only do this for Windows clients.
40 ********************************************************************/
41
42 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
43 {
44         SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
45
46         /* Only roundup for Windows clients. */
47         enum remote_arch_types ra_type = get_remote_arch();
48         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
49                 val = SMB_ROUNDUP(val,rval);
50         }
51         return val;
52 }
53
54 /********************************************************************
55  Given a stat buffer return the allocated size on disk, taking into
56  account sparse files.
57 ********************************************************************/
58
59 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
60 {
61         SMB_BIG_UINT ret;
62
63         if(S_ISDIR(sbuf->st_mode)) {
64                 return 0;
65         }
66
67 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
68         ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
69 #else
70         ret = (SMB_BIG_UINT)get_file_size(*sbuf);
71 #endif
72
73         if (fsp && fsp->initial_allocation_size)
74                 ret = MAX(ret,fsp->initial_allocation_size);
75
76         return smb_roundup(conn, ret);
77 }
78
79 /****************************************************************************
80  Utility functions for dealing with extended attributes.
81 ****************************************************************************/
82
83 static const char *prohibited_ea_names[] = {
84         SAMBA_POSIX_INHERITANCE_EA_NAME,
85         SAMBA_XATTR_DOS_ATTRIB,
86         NULL
87 };
88
89 /****************************************************************************
90  Refuse to allow clients to overwrite our private xattrs.
91 ****************************************************************************/
92
93 static BOOL samba_private_attr_name(const char *unix_ea_name)
94 {
95         int i;
96
97         for (i = 0; prohibited_ea_names[i]; i++) {
98                 if (strequal( prohibited_ea_names[i], unix_ea_name))
99                         return True;
100         }
101         return False;
102 }
103
104 /****************************************************************************
105  Get one EA value. Fill in a struct ea_struct.
106 ****************************************************************************/
107
108 static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
109                                 const char *fname, char *ea_name, struct ea_struct *pea)
110 {
111         /* Get the value of this xattr. Max size is 64k. */
112         size_t attr_size = 256;
113         char *val = NULL;
114         ssize_t sizeret;
115
116  again:
117
118         val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
119         if (!val) {
120                 return False;
121         }
122
123         if (fsp && fsp->fh->fd != -1) {
124                 sizeret = SMB_VFS_FGETXATTR(fsp, fsp->fh->fd, ea_name, val, attr_size);
125         } else {
126                 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
127         }
128
129         if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
130                 attr_size = 65536;
131                 goto again;
132         }
133
134         if (sizeret == -1) {
135                 return False;
136         }
137
138         DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
139         dump_data(10, val, sizeret);
140
141         pea->flags = 0;
142         if (strnequal(ea_name, "user.", 5)) {
143                 pea->name = &ea_name[5];
144         } else {
145                 pea->name = ea_name;
146         }
147         pea->value.data = (unsigned char *)val;
148         pea->value.length = (size_t)sizeret;
149         return True;
150 }
151
152 /****************************************************************************
153  Return a linked list of the total EA's. Plus the total size
154 ****************************************************************************/
155
156 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
157                                         const char *fname, size_t *pea_total_len)
158 {
159         /* Get a list of all xattrs. Max namesize is 64k. */
160         size_t ea_namelist_size = 1024;
161         char *ea_namelist;
162         char *p;
163         ssize_t sizeret;
164         int i;
165         struct ea_list *ea_list_head = NULL;
166
167         *pea_total_len = 0;
168
169         if (!lp_ea_support(SNUM(conn))) {
170                 return NULL;
171         }
172
173         for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6;
174              ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) {
175
176                 if (!ea_namelist) {
177                         return NULL;
178                 }
179
180                 if (fsp && fsp->fh->fd != -1) {
181                         sizeret = SMB_VFS_FLISTXATTR(fsp, fsp->fh->fd, ea_namelist, ea_namelist_size);
182                 } else {
183                         sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size);
184                 }
185
186                 if (sizeret == -1 && errno == ERANGE) {
187                         ea_namelist_size *= 2;
188                 } else {
189                         break;
190                 }
191         }
192
193         if (sizeret == -1)
194                 return NULL;
195
196         DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret ));
197
198         if (sizeret) {
199                 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) {
200                         struct ea_list *listp;
201
202                         if (strnequal(p, "system.", 7) || samba_private_attr_name(p))
203                                 continue;
204                 
205                         listp = TALLOC_P(mem_ctx, struct ea_list);
206                         if (!listp)
207                                 return NULL;
208
209                         if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) {
210                                 return NULL;
211                         }
212
213                         {
214                                 fstring dos_ea_name;
215                                 push_ascii_fstring(dos_ea_name, listp->ea.name);
216                                 *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
217                                 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n",
218                                         (unsigned int)*pea_total_len, dos_ea_name,
219                                         (unsigned int)listp->ea.value.length ));
220                         }
221                         DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
222                 }
223                 /* Add on 4 for total length. */
224                 if (*pea_total_len) {
225                         *pea_total_len += 4;
226                 }
227         }
228
229         DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len));
230         return ea_list_head;
231 }
232
233 /****************************************************************************
234  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
235  that was filled.
236 ****************************************************************************/
237
238 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
239         connection_struct *conn, struct ea_list *ea_list)
240 {
241         unsigned int ret_data_size = 4;
242         char *p = pdata;
243
244         SMB_ASSERT(total_data_size >= 4);
245
246         if (!lp_ea_support(SNUM(conn))) {
247                 SIVAL(pdata,4,0);
248                 return 4;
249         }
250
251         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
252                 size_t dos_namelen;
253                 fstring dos_ea_name;
254                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
255                 dos_namelen = strlen(dos_ea_name);
256                 if (dos_namelen > 255 || dos_namelen == 0) {
257                         break;
258                 }
259                 if (ea_list->ea.value.length > 65535) {
260                         break;
261                 }
262                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
263                         break;
264                 }
265
266                 /* We know we have room. */
267                 SCVAL(p,0,ea_list->ea.flags);
268                 SCVAL(p,1,dos_namelen);
269                 SSVAL(p,2,ea_list->ea.value.length);
270                 fstrcpy(p+4, dos_ea_name);
271                 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
272
273                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
274                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
275         }
276
277         ret_data_size = PTR_DIFF(p, pdata);
278         DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
279         SIVAL(pdata,0,ret_data_size);
280         return ret_data_size;
281 }
282
283 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
284 {
285         size_t total_ea_len = 0;
286         TALLOC_CTX *mem_ctx = NULL;
287
288         if (!lp_ea_support(SNUM(conn))) {
289                 return 0;
290         }
291         mem_ctx = talloc_init("estimate_ea_size");
292         (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
293         talloc_destroy(mem_ctx);
294         return total_ea_len;
295 }
296
297 /****************************************************************************
298  Ensure the EA name is case insensitive by matching any existing EA name.
299 ****************************************************************************/
300
301 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
302 {
303         size_t total_ea_len;
304         TALLOC_CTX *mem_ctx = talloc_init("canonicalize_ea_name");
305         struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
306
307         for (; ea_list; ea_list = ea_list->next) {
308                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
309                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
310                                 &unix_ea_name[5], ea_list->ea.name));
311                         safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
312                         break;
313                 }
314         }
315         talloc_destroy(mem_ctx);
316 }
317
318 /****************************************************************************
319  Set or delete an extended attribute.
320 ****************************************************************************/
321
322 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
323 {
324         if (!lp_ea_support(SNUM(conn))) {
325                 return NT_STATUS_EAS_NOT_SUPPORTED;
326         }
327
328         for (;ea_list; ea_list = ea_list->next) {
329                 int ret;
330                 fstring unix_ea_name;
331
332                 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
333                 fstrcat(unix_ea_name, ea_list->ea.name);
334
335                 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
336
337                 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
338
339                 if (samba_private_attr_name(unix_ea_name)) {
340                         DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
341                         return NT_STATUS_ACCESS_DENIED;
342                 }
343
344                 if (ea_list->ea.value.length == 0) {
345                         /* Remove the attribute. */
346                         if (fsp && (fsp->fh->fd != -1)) {
347                                 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
348                                         unix_ea_name, fsp->fsp_name));
349                                 ret = SMB_VFS_FREMOVEXATTR(fsp, fsp->fh->fd, unix_ea_name);
350                         } else {
351                                 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
352                                         unix_ea_name, fname));
353                                 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
354                         }
355 #ifdef ENOATTR
356                         /* Removing a non existent attribute always succeeds. */
357                         if (ret == -1 && errno == ENOATTR) {
358                                 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
359                                                 unix_ea_name));
360                                 ret = 0;
361                         }
362 #endif
363                 } else {
364                         if (fsp && (fsp->fh->fd != -1)) {
365                                 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
366                                         unix_ea_name, fsp->fsp_name));
367                                 ret = SMB_VFS_FSETXATTR(fsp, fsp->fh->fd, unix_ea_name,
368                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
369                         } else {
370                                 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
371                                         unix_ea_name, fname));
372                                 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
373                                                         ea_list->ea.value.data, ea_list->ea.value.length, 0);
374                         }
375                 }
376
377                 if (ret == -1) {
378 #ifdef ENOTSUP
379                         if (errno == ENOTSUP) {
380                                 return NT_STATUS_EAS_NOT_SUPPORTED;
381                         }
382 #endif
383                         return map_nt_error_from_unix(errno);
384                 }
385
386         }
387         return NT_STATUS_OK;
388 }
389 /****************************************************************************
390  Read a list of EA names from an incoming data buffer. Create an ea_list with them.
391 ****************************************************************************/
392
393 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
394 {
395         struct ea_list *ea_list_head = NULL;
396         size_t offset = 0;
397
398         while (offset + 2 < data_size) {
399                 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
400                 unsigned int namelen = CVAL(pdata,offset);
401
402                 offset++; /* Go past the namelen byte. */
403
404                 /* integer wrap paranioa. */
405                 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
406                                 (offset > data_size) || (namelen > data_size) ||
407                                 (offset + namelen >= data_size)) {
408                         break;
409                 }
410                 /* Ensure the name is null terminated. */
411                 if (pdata[offset + namelen] != '\0') {
412                         return NULL;
413                 }
414                 pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset]);
415                 if (!eal->ea.name) {
416                         return NULL;
417                 }
418
419                 offset += (namelen + 1); /* Go past the name + terminating zero. */
420                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
421                 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
422         }
423
424         return ea_list_head;
425 }
426
427 /****************************************************************************
428  Read one EA list entry from the buffer.
429 ****************************************************************************/
430
431 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
432 {
433         struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
434         uint16 val_len;
435         unsigned int namelen;
436
437         if (!eal) {
438                 return NULL;
439         }
440
441         if (data_size < 6) {
442                 return NULL;
443         }
444
445         eal->ea.flags = CVAL(pdata,0);
446         namelen = CVAL(pdata,1);
447         val_len = SVAL(pdata,2);
448
449         if (4 + namelen + 1 + val_len > data_size) {
450                 return NULL;
451         }
452
453         /* Ensure the name is null terminated. */
454         if (pdata[namelen + 4] != '\0') {
455                 return NULL;
456         }
457         pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4);
458         if (!eal->ea.name) {
459                 return NULL;
460         }
461
462         eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
463         if (!eal->ea.value.data) {
464                 return NULL;
465         }
466
467         memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
468
469         /* Ensure we're null terminated just in case we print the value. */
470         eal->ea.value.data[val_len] = '\0';
471         /* But don't count the null. */
472         eal->ea.value.length--;
473
474         if (pbytes_used) {
475                 *pbytes_used = 4 + namelen + 1 + val_len;
476         }
477
478         DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
479         dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
480
481         return eal;
482 }
483
484 /****************************************************************************
485  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
486 ****************************************************************************/
487
488 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
489 {
490         struct ea_list *ea_list_head = NULL;
491         size_t offset = 0;
492         size_t bytes_used = 0;
493
494         while (offset < data_size) {
495                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
496
497                 if (!eal) {
498                         return NULL;
499                 }
500
501                 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
502                 offset += bytes_used;
503         }
504
505         return ea_list_head;
506 }
507
508 /****************************************************************************
509  Count the total EA size needed.
510 ****************************************************************************/
511
512 static size_t ea_list_size(struct ea_list *ealist)
513 {
514         fstring dos_ea_name;
515         struct ea_list *listp;
516         size_t ret = 0;
517
518         for (listp = ealist; listp; listp = listp->next) {
519                 push_ascii_fstring(dos_ea_name, listp->ea.name);
520                 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
521         }
522         /* Add on 4 for total length. */
523         if (ret) {
524                 ret += 4;
525         }
526
527         return ret;
528 }
529
530 /****************************************************************************
531  Return a union of EA's from a file list and a list of names.
532  The TALLOC context for the two lists *MUST* be identical as we steal
533  memory from one list to add to another. JRA.
534 ****************************************************************************/
535
536 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
537 {
538         struct ea_list *nlistp, *flistp;
539
540         for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
541                 for (flistp = file_list; flistp; flistp = flistp->next) {
542                         if (strequal(nlistp->ea.name, flistp->ea.name)) {
543                                 break;
544                         }
545                 }
546
547                 if (flistp) {
548                         /* Copy the data from this entry. */
549                         nlistp->ea.flags = flistp->ea.flags;
550                         nlistp->ea.value = flistp->ea.value;
551                 } else {
552                         /* Null entry. */
553                         nlistp->ea.flags = 0;
554                         ZERO_STRUCT(nlistp->ea.value);
555                 }
556         }
557
558         *total_ea_len = ea_list_size(name_list);
559         return name_list;
560 }
561
562 /****************************************************************************
563   Send the required number of replies back.
564   We assume all fields other than the data fields are
565   set correctly for the type of call.
566   HACK ! Always assumes smb_setup field is zero.
567 ****************************************************************************/
568
569 int send_trans2_replies(char *outbuf,
570                         int bufsize,
571                         char *params, 
572                         int paramsize,
573                         char *pdata,
574                         int datasize,
575                         int max_data_bytes)
576 {
577         /* As we are using a protocol > LANMAN1 then the max_send
578          variable must have been set in the sessetupX call.
579          This takes precedence over the max_xmit field in the
580          global struct. These different max_xmit variables should
581          be merged as this is now too confusing */
582
583         int data_to_send = datasize;
584         int params_to_send = paramsize;
585         int useable_space;
586         char *pp = params;
587         char *pd = pdata;
588         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
589         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
590         int data_alignment_offset = 0;
591
592         /* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
593         
594         set_message(outbuf,10,0,True);
595
596         /* Modify the data_to_send and datasize and set the error if
597            we're trying to send more than max_data_bytes. We still send
598            the part of the packet(s) that fit. Strange, but needed
599            for OS/2. */
600
601         if (max_data_bytes > 0 && datasize > max_data_bytes) {
602                 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
603                         max_data_bytes, datasize ));
604                 datasize = data_to_send = max_data_bytes;
605                 error_packet_set(outbuf,ERRDOS,ERRbufferoverflow,STATUS_BUFFER_OVERFLOW,__LINE__,__FILE__);
606         }
607
608         /* If there genuinely are no parameters or data to send just send the empty packet */
609
610         if(params_to_send == 0 && data_to_send == 0) {
611                 show_msg(outbuf);
612                 if (!send_smb(smbd_server_fd(),outbuf))
613                         exit_server_cleanly("send_trans2_replies: send_smb failed.");
614                 return 0;
615         }
616
617         /* When sending params and data ensure that both are nicely aligned */
618         /* Only do this alignment when there is also data to send - else
619                 can cause NT redirector problems. */
620
621         if (((params_to_send % 4) != 0) && (data_to_send != 0))
622                 data_alignment_offset = 4 - (params_to_send % 4);
623
624         /* Space is bufsize minus Netbios over TCP header minus SMB header */
625         /* The alignment_offset is to align the param bytes on an even byte
626                 boundary. NT 4.0 Beta needs this to work correctly. */
627
628         useable_space = bufsize - ((smb_buf(outbuf)+ alignment_offset+data_alignment_offset) - outbuf);
629
630         /* useable_space can never be more than max_send minus the alignment offset. */
631
632         useable_space = MIN(useable_space, max_send - (alignment_offset+data_alignment_offset));
633
634         while (params_to_send || data_to_send) {
635                 /* Calculate whether we will totally or partially fill this packet */
636
637                 total_sent_thistime = params_to_send + data_to_send + alignment_offset + data_alignment_offset;
638
639                 /* We can never send more than useable_space */
640                 /*
641                  * Note that 'useable_space' does not include the alignment offsets,
642                  * but we must include the alignment offsets in the calculation of
643                  * the length of the data we send over the wire, as the alignment offsets
644                  * are sent here. Fix from Marc_Jacobsen@hp.com.
645                  */
646
647                 total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
648
649                 set_message(outbuf, 10, total_sent_thistime, True);
650
651                 /* Set total params and data to be sent */
652                 SSVAL(outbuf,smb_tprcnt,paramsize);
653                 SSVAL(outbuf,smb_tdrcnt,datasize);
654
655                 /* Calculate how many parameters and data we can fit into
656                  * this packet. Parameters get precedence
657                  */
658
659                 params_sent_thistime = MIN(params_to_send,useable_space);
660                 data_sent_thistime = useable_space - params_sent_thistime;
661                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
662
663                 SSVAL(outbuf,smb_prcnt, params_sent_thistime);
664
665                 /* smb_proff is the offset from the start of the SMB header to the
666                         parameter bytes, however the first 4 bytes of outbuf are
667                         the Netbios over TCP header. Thus use smb_base() to subtract
668                         them from the calculation */
669
670                 SSVAL(outbuf,smb_proff,((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
671
672                 if(params_sent_thistime == 0)
673                         SSVAL(outbuf,smb_prdisp,0);
674                 else
675                         /* Absolute displacement of param bytes sent in this packet */
676                         SSVAL(outbuf,smb_prdisp,pp - params);
677
678                 SSVAL(outbuf,smb_drcnt, data_sent_thistime);
679                 if(data_sent_thistime == 0) {
680                         SSVAL(outbuf,smb_droff,0);
681                         SSVAL(outbuf,smb_drdisp, 0);
682                 } else {
683                         /* The offset of the data bytes is the offset of the
684                                 parameter bytes plus the number of parameters being sent this time */
685                         SSVAL(outbuf,smb_droff,((smb_buf(outbuf)+alignment_offset) - 
686                                 smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
687                         SSVAL(outbuf,smb_drdisp, pd - pdata);
688                 }
689
690                 /* Copy the param bytes into the packet */
691
692                 if(params_sent_thistime)
693                         memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
694
695                 /* Copy in the data bytes */
696                 if(data_sent_thistime)
697                         memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
698                                 data_alignment_offset,pd,data_sent_thistime);
699
700                 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
701                         params_sent_thistime, data_sent_thistime, useable_space));
702                 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
703                         params_to_send, data_to_send, paramsize, datasize));
704
705                 /* Send the packet */
706                 show_msg(outbuf);
707                 if (!send_smb(smbd_server_fd(),outbuf))
708                         exit_server_cleanly("send_trans2_replies: send_smb failed.");
709
710                 pp += params_sent_thistime;
711                 pd += data_sent_thistime;
712
713                 params_to_send -= params_sent_thistime;
714                 data_to_send -= data_sent_thistime;
715
716                 /* Sanity check */
717                 if(params_to_send < 0 || data_to_send < 0) {
718                         DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
719                                 params_to_send, data_to_send));
720                         return -1;
721                 }
722         }
723
724         return 0;
725 }
726
727 /****************************************************************************
728  Reply to a TRANSACT2_OPEN.
729 ****************************************************************************/
730
731 static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,  
732                                 char **pparams, int total_params, char **ppdata, int total_data,
733                                 unsigned int max_data_bytes)
734 {
735         char *params = *pparams;
736         char *pdata = *ppdata;
737         int deny_mode;
738         int32 open_attr;
739         BOOL oplock_request;
740 #if 0
741         BOOL return_additional_info;
742         int16 open_sattr;
743         time_t open_time;
744 #endif
745         int open_ofun;
746         uint32 open_size;
747         char *pname;
748         pstring fname;
749         SMB_OFF_T size=0;
750         int fattr=0,mtime=0;
751         SMB_INO_T inode = 0;
752         SMB_STRUCT_STAT sbuf;
753         int smb_action = 0;
754         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                                 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                                 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                                 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                                 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                                 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                                 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                                 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  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
4113 ****************************************************************************/
4114
4115 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4116                                         unsigned int tran_call,
4117                                         char **pparams, int total_params, char **ppdata, int total_data,
4118                                         unsigned int max_data_bytes)
4119 {
4120         char *params = *pparams;
4121         char *pdata = *ppdata;
4122         uint16 info_level;
4123         int dosmode=0;
4124         SMB_OFF_T size=0;
4125         struct utimbuf tvs;
4126         SMB_STRUCT_STAT sbuf;
4127         pstring fname;
4128         int fd = -1;
4129         files_struct *fsp = NULL;
4130         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
4131         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
4132         mode_t unixmode = 0;
4133         NTSTATUS status = NT_STATUS_OK;
4134
4135         if (!params)
4136                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4137
4138         ZERO_STRUCT(sbuf);
4139         ZERO_STRUCT(tvs);
4140
4141         if (tran_call == TRANSACT2_SETFILEINFO) {
4142                 if (total_params < 4) {
4143                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4144                 }
4145
4146                 fsp = file_fsp(params,0);
4147                 info_level = SVAL(params,2);    
4148
4149                 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
4150                         /*
4151                          * This is actually a SETFILEINFO on a directory
4152                          * handle (returned from an NT SMB). NT5.0 seems
4153                          * to do this call. JRA.
4154                          */
4155                         pstrcpy(fname, fsp->fsp_name);
4156                         if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
4157                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
4158                                 return UNIXERROR(ERRDOS,ERRbadpath);
4159                         }
4160                 } else if (fsp && fsp->print_file) {
4161                         /*
4162                          * Doing a DELETE_ON_CLOSE should cancel a print job.
4163                          */
4164                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
4165                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
4166
4167                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
4168         
4169                                 SSVAL(params,0,0);
4170                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4171                                 return(-1);
4172                         } else
4173                                 return (UNIXERROR(ERRDOS,ERRbadpath));
4174             } else {
4175                         /*
4176                          * Original code - this is an open file.
4177                          */
4178                         CHECK_FSP(fsp,conn);
4179
4180                         pstrcpy(fname, fsp->fsp_name);
4181                         fd = fsp->fh->fd;
4182
4183                         if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
4184                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
4185                                 return(UNIXERROR(ERRDOS,ERRbadfid));
4186                         }
4187                 }
4188         } else {
4189                 /* set path info */
4190                 if (total_params < 7) {
4191                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4192                 }
4193
4194                 info_level = SVAL(params,0);    
4195                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
4196                 if (!NT_STATUS_IS_OK(status)) {
4197                         return ERROR_NT(status);
4198                 }
4199                 status = unix_convert(conn, fname, False, NULL, &sbuf);
4200                 if (!NT_STATUS_IS_OK(status)) {
4201                         return ERROR_NT(status);
4202                 }
4203
4204                 /*
4205                  * For CIFS UNIX extensions the target name may not exist.
4206                  */
4207
4208                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
4209                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
4210                         return UNIXERROR(ERRDOS,ERRbadpath);
4211                 }    
4212
4213                 status = check_name(conn, fname);
4214                 if (!NT_STATUS_IS_OK(status)) {
4215                         return ERROR_NT(status);
4216                 }
4217
4218         }
4219
4220         if (!CAN_WRITE(conn))
4221                 return ERROR_DOS(ERRSRV,ERRaccess);
4222
4223         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4224                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4225         }
4226
4227         if (VALID_STAT(sbuf))
4228                 unixmode = sbuf.st_mode;
4229
4230         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
4231                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
4232
4233         /* Realloc the parameter size */
4234         *pparams = (char *)SMB_REALLOC(*pparams,2);
4235         if (*pparams == NULL) {
4236                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4237         }
4238         params = *pparams;
4239
4240         SSVAL(params,0,0);
4241
4242         if (fsp && fsp->pending_modtime) {
4243                 /* the pending modtime overrides the current modtime */
4244                 sbuf.st_mtime = fsp->pending_modtime;
4245         }
4246
4247         size = get_file_size(sbuf);
4248         tvs.modtime = sbuf.st_mtime;
4249         tvs.actime = sbuf.st_atime;
4250         dosmode = dos_mode(conn,fname,&sbuf);
4251         unixmode = sbuf.st_mode;
4252
4253         set_owner = VALID_STAT(sbuf) ? sbuf.st_uid : (uid_t)SMB_UID_NO_CHANGE;
4254         set_grp = VALID_STAT(sbuf) ? sbuf.st_gid : (gid_t)SMB_GID_NO_CHANGE;
4255
4256         switch (info_level) {
4257                 case SMB_INFO_STANDARD:
4258                 {
4259                         if (total_data < 12) {
4260                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4261                         }
4262
4263                         /* access time */
4264                         tvs.actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
4265                         /* write time */
4266                         tvs.modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
4267                         break;
4268                 }
4269
4270                 case SMB_INFO_SET_EA:
4271                         return smb_info_set_ea(conn,
4272                                                 outbuf,
4273                                                 bufsize,
4274                                                 params,
4275                                                 *ppdata,
4276                                                 total_data,
4277                                                 max_data_bytes,
4278                                                 fsp,
4279                                                 fname);
4280
4281                 case SMB_SET_FILE_BASIC_INFO:
4282                 case SMB_FILE_BASIC_INFORMATION:
4283                 {
4284                         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4285                         time_t write_time;
4286                         time_t changed_time;
4287
4288                         if (total_data < 36) {
4289                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4290                         }
4291
4292                         /* Ignore create time at offset pdata. */
4293
4294                         /* access time */
4295                         tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata+8));
4296
4297                         write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16));
4298                         changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24));
4299
4300                         tvs.modtime = MIN(write_time, changed_time);
4301
4302                         if (write_time > tvs.modtime && write_time != (time_t)-1) {
4303                                 tvs.modtime = write_time;
4304                         }
4305                         /* Prefer a defined time to an undefined one. */
4306                         if (null_mtime(tvs.modtime)) {
4307                                 tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
4308                         }
4309
4310                         /* attributes */
4311                         dosmode = IVAL(pdata,32);
4312                         break;
4313                 }
4314
4315                 case SMB_FILE_ALLOCATION_INFORMATION:
4316                 case SMB_SET_FILE_ALLOCATION_INFO:
4317                 {
4318                         int ret = -1;
4319                         SMB_BIG_UINT allocation_size;
4320
4321                         if (total_data < 8) {
4322                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4323                         }
4324
4325                         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4326 #ifdef LARGE_SMB_OFF_T
4327                         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4328 #else /* LARGE_SMB_OFF_T */
4329                         if (IVAL(pdata,4) != 0) {
4330                                 /* more than 32 bits? */
4331                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4332                         }
4333 #endif /* LARGE_SMB_OFF_T */
4334                         DEBUG(10,("call_trans2setfilepathinfo: Set file allocation info for file %s to %.0f\n",
4335                                         fname, (double)allocation_size ));
4336
4337                         if (allocation_size) {
4338                                 allocation_size = smb_roundup(conn, allocation_size);
4339                         }
4340
4341                         if(allocation_size != get_file_size(sbuf)) {
4342                                 SMB_STRUCT_STAT new_sbuf;
4343  
4344                                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new allocation size to %.0f\n",
4345                                         fname, (double)allocation_size ));
4346  
4347                                 if (fd == -1) {
4348                                         files_struct *new_fsp = NULL;
4349  
4350                                         status = open_file_ntcreate(conn, fname, &sbuf,
4351                                                                         FILE_WRITE_DATA,
4352                                                                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4353                                                                         FILE_OPEN,
4354                                                                         0,
4355                                                                         FILE_ATTRIBUTE_NORMAL,
4356                                                                         FORCE_OPLOCK_BREAK_TO_NONE,
4357                                                                         NULL, &new_fsp);
4358  
4359                                         if (!NT_STATUS_IS_OK(status)) {
4360                                                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4361                                                         /* We have re-scheduled this call. */
4362                                                         return -1;
4363                                                 }
4364                                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4365                                         }
4366                                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
4367                                         if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
4368                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4369                                                                         new_fsp->fnum, strerror(errno)));
4370                                                 ret = -1;
4371                                         }
4372                                         close_file(new_fsp,NORMAL_CLOSE);
4373                                 } else {
4374                                         ret = vfs_allocate_file_space(fsp, allocation_size);
4375                                         if (SMB_VFS_FSTAT(fsp,fd,&new_sbuf) != 0) {
4376                                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",
4377                                                                         fsp->fnum, strerror(errno)));
4378                                                 ret = -1;
4379                                         }
4380                                 }
4381                                 if (ret == -1)
4382                                         return ERROR_NT(NT_STATUS_DISK_FULL);
4383
4384                                 /* Allocate can truncate size... */
4385                                 size = get_file_size(new_sbuf);
4386                         }
4387
4388                         break;
4389                 }
4390
4391                 case SMB_FILE_END_OF_FILE_INFORMATION:
4392                 case SMB_SET_FILE_END_OF_FILE_INFO:
4393                 {
4394                         if (total_data < 8) {
4395                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4396                         }
4397
4398                         size = IVAL(pdata,0);
4399 #ifdef LARGE_SMB_OFF_T
4400                         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4401 #else /* LARGE_SMB_OFF_T */
4402                         if (IVAL(pdata,4) != 0) {
4403                                 /* more than 32 bits? */
4404                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4405                         }
4406 #endif /* LARGE_SMB_OFF_T */
4407                         DEBUG(10,("call_trans2setfilepathinfo: Set end of file info for file %s to %.0f\n", fname, (double)size ));
4408                         break;
4409                 }
4410
4411                 case SMB_FILE_DISPOSITION_INFORMATION:
4412                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
4413                 {
4414 #if 0
4415                         /* JRA - We used to just ignore this on a path ? 
4416                          * Shouldn't this be invalid level on a pathname
4417                          * based call ?
4418                          */
4419                         if (tran_call != TRANSACT2_SETFILEINFO) {
4420                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4421                         }
4422 #endif
4423                         return smb_set_file_disposition_info(conn,
4424                                                 outbuf,
4425                                                 bufsize,
4426                                                 params,
4427                                                 *ppdata,
4428                                                 total_data,
4429                                                 max_data_bytes,
4430                                                 fsp,
4431                                                 dosmode);
4432                 }
4433
4434                 case SMB_FILE_POSITION_INFORMATION:
4435                 {
4436                         return smb_file_position_information(conn,
4437                                                 outbuf,
4438                                                 bufsize,
4439                                                 params,
4440                                                 *ppdata,
4441                                                 total_data,
4442                                                 max_data_bytes,
4443                                                 fsp);
4444                 }
4445
4446                 /* From tridge Samba4 : 
4447                  * MODE_INFORMATION in setfileinfo (I have no
4448                  * idea what "mode information" on a file is - it takes a value of 0,
4449                  * 2, 4 or 6. What could it be?).
4450                  */
4451
4452                 case SMB_FILE_MODE_INFORMATION:
4453                 {
4454                         return smb_file_mode_information(conn,
4455                                                 outbuf,
4456                                                 bufsize,
4457                                                 params,
4458                                                 *ppdata,
4459                                                 total_data,
4460                                                 max_data_bytes);
4461                 }
4462
4463                 /*
4464                  * CIFS UNIX extensions.
4465                  */
4466
4467                 case SMB_SET_FILE_UNIX_BASIC:
4468                 {
4469                         uint32 raw_unixmode;
4470                         BOOL delete_on_fail = False;
4471
4472                         if (total_data < 100) {
4473                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4474                         }
4475
4476                         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4477                            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4478                                 size=IVAL(pdata,0); /* first 8 Bytes are size */
4479 #ifdef LARGE_SMB_OFF_T
4480                                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4481 #else /* LARGE_SMB_OFF_T */
4482                                 if (IVAL(pdata,4) != 0) {
4483                                         /* more than 32 bits? */
4484                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4485                                 }
4486 #endif /* LARGE_SMB_OFF_T */
4487                         }
4488                         pdata+=24;          /* ctime & st_blocks are not changed */
4489                         tvs.actime = convert_timespec_to_time_t(interpret_long_date(pdata)); /* access_time */
4490                         tvs.modtime = convert_timespec_to_time_t(interpret_long_date(pdata+8)); /* modification_time */
4491                         pdata+=16;
4492                         set_owner = (uid_t)IVAL(pdata,0);
4493                         pdata += 8;
4494                         set_grp = (gid_t)IVAL(pdata,0);
4495                         pdata += 8;
4496                         raw_unixmode = IVAL(pdata,28);
4497                         unixmode = unix_perms_from_wire(conn, &sbuf, raw_unixmode);
4498                         dosmode = 0; /* Ensure dos mode change doesn't override this. */
4499
4500                         DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC: name = %s \
4501 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4502                                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4503
4504                         if (!VALID_STAT(sbuf)) {
4505
4506                                 /*
4507                                  * The only valid use of this is to create character and block
4508                                  * devices, and named pipes. This is deprecated (IMHO) and 
4509                                  * a new info level should be used for mknod. JRA.
4510                                  */
4511
4512                                 uint32 file_type = IVAL(pdata,0);
4513 #if defined(HAVE_MAKEDEV)
4514                                 uint32 dev_major = IVAL(pdata,4);
4515                                 uint32 dev_minor = IVAL(pdata,12);
4516 #endif
4517
4518                                 SMB_DEV_T dev = (SMB_DEV_T)0;
4519
4520                                 if (tran_call == TRANSACT2_SETFILEINFO)
4521                                         return(ERROR_DOS(ERRDOS,ERRnoaccess));
4522
4523                                 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4524                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4525                                 }
4526
4527 #if defined(HAVE_MAKEDEV)
4528                                 dev = makedev(dev_major, dev_minor);
4529 #endif
4530
4531                                 switch (file_type) {
4532 #if defined(S_IFIFO)
4533                                         case UNIX_TYPE_FIFO:
4534                                                 unixmode |= S_IFIFO;
4535                                                 break;
4536 #endif
4537 #if defined(S_IFSOCK)
4538                                         case UNIX_TYPE_SOCKET:
4539                                                 unixmode |= S_IFSOCK;
4540                                                 break;
4541 #endif
4542 #if defined(S_IFCHR)
4543                                         case UNIX_TYPE_CHARDEV:
4544                                                 unixmode |= S_IFCHR;
4545                                                 break;
4546 #endif
4547 #if defined(S_IFBLK)
4548                                         case UNIX_TYPE_BLKDEV:
4549                                                 unixmode |= S_IFBLK;
4550                                                 break;
4551 #endif
4552                                         default:
4553                                                 return(ERROR_DOS(ERRDOS,ERRnoaccess));
4554                                 }
4555
4556                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4557 0%o for file %s\n", (double)dev, unixmode, fname ));
4558
4559                                 /* Ok - do the mknod. */
4560                                 if (SMB_VFS_MKNOD(conn,fname, unixmode, dev) != 0) {
4561                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4562                                 }
4563
4564                                 /* If any of the other "set" calls fail we
4565                                  * don't want to end up with a half-constructed mknod.
4566                                  */
4567
4568                                 delete_on_fail = True;
4569
4570                                 if (lp_inherit_perms(SNUM(conn))) {
4571                                         inherit_access_acl(
4572                                                 conn, parent_dirname(fname),
4573                                                 fname, unixmode);
4574                                 }
4575
4576                                 if (SMB_VFS_STAT(conn, fname, &sbuf) != 0) {
4577                                         int saved_errno = errno;
4578                                         SMB_VFS_UNLINK(conn,fname);
4579                                         errno = saved_errno;
4580                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4581                                 }
4582
4583                                 /* Ensure we don't try and change anything else. */
4584                                 raw_unixmode = SMB_MODE_NO_CHANGE;
4585                                 size = get_file_size(sbuf);
4586                                 tvs.modtime = sbuf.st_mtime;
4587                                 tvs.actime = sbuf.st_atime;
4588                         }
4589
4590                         /*
4591                          * Deal with the UNIX specific mode set.
4592                          */
4593
4594                         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4595                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4596                                         (unsigned int)unixmode, fname ));
4597                                 if (SMB_VFS_CHMOD(conn,fname,unixmode) != 0)
4598                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4599                         }
4600
4601                         /*
4602                          * Deal with the UNIX specific uid set.
4603                          */
4604
4605                         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (sbuf.st_uid != set_owner)) {
4606                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4607                                         (unsigned int)set_owner, fname ));
4608                                 if (SMB_VFS_CHOWN(conn,fname,set_owner, (gid_t)-1) != 0) {
4609                                         if (delete_on_fail) {
4610                                                 int saved_errno = errno;
4611                                                 SMB_VFS_UNLINK(conn,fname);
4612                                                 errno = saved_errno;
4613                                         }
4614                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4615                                 }
4616                         }
4617
4618                         /*
4619                          * Deal with the UNIX specific gid set.
4620                          */
4621
4622                         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (sbuf.st_gid != set_grp)) {
4623                                 DEBUG(10,("call_trans2setfilepathinfo: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4624                                         (unsigned int)set_owner, fname ));
4625                                 if (SMB_VFS_CHOWN(conn,fname,(uid_t)-1, set_grp) != 0) {
4626                                         if (delete_on_fail) {
4627                                                 int saved_errno = errno;
4628                                                 SMB_VFS_UNLINK(conn,fname);
4629                                                 errno = saved_errno;
4630                                         }
4631                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4632                                 }
4633                         }
4634                         break;
4635                 }
4636
4637                 case SMB_SET_FILE_UNIX_LINK:
4638                 {
4639                         if (tran_call != TRANSACT2_SETPATHINFO) {
4640                                 /* We must have a pathname for this. */
4641                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4642                         }
4643                         return smb_set_file_unix_link(conn,
4644                                                 inbuf,
4645                                                 outbuf,
4646                                                 bufsize,
4647                                                 params,
4648                                                 *ppdata,
4649                                                 total_data,
4650                                                 max_data_bytes,
4651                                                 fname);
4652                 }
4653
4654                 case SMB_SET_FILE_UNIX_HLINK:
4655                 {
4656                         if (tran_call != TRANSACT2_SETPATHINFO) {
4657                                 /* We must have a pathname for this. */
4658                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4659                         }
4660                         return smb_set_file_unix_hlink(conn,
4661                                                 inbuf,
4662                                                 outbuf,
4663                                                 bufsize,
4664                                                 params,
4665                                                 *ppdata,
4666                                                 total_data,
4667                                                 max_data_bytes,
4668                                                 fname);
4669                 }
4670
4671                 case SMB_FILE_RENAME_INFORMATION:
4672                 {
4673                         return smb_file_rename_information(conn,
4674                                                         inbuf,
4675                                                         outbuf,
4676                                                         bufsize,
4677                                                         params,
4678                                                         pdata,
4679                                                         total_data,
4680                                                         max_data_bytes,
4681                                                         fsp,
4682                                                         fname);
4683                 }
4684
4685 #if defined(HAVE_POSIX_ACLS)
4686                 case SMB_SET_POSIX_ACL:
4687                 {
4688                         uint16 posix_acl_version;
4689                         uint16 num_file_acls;
4690                         uint16 num_def_acls;
4691                         BOOL valid_file_acls = True;
4692                         BOOL valid_def_acls = True;
4693
4694                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4695                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4696                         }
4697                         posix_acl_version = SVAL(pdata,0);
4698                         num_file_acls = SVAL(pdata,2);
4699                         num_def_acls = SVAL(pdata,4);
4700
4701                         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4702                                 valid_file_acls = False;
4703                                 num_file_acls = 0;
4704                         }
4705
4706                         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4707                                 valid_def_acls = False;
4708                                 num_def_acls = 0;
4709                         }
4710
4711                         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4712                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4713                         }
4714
4715                         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4716                                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4717                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4718                         }
4719
4720                         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4721                                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4722                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4723                         }
4724
4725                         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, &sbuf, num_def_acls,
4726                                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
4727                                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4728                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4729                         }
4730
4731                         SSVAL(params,0,0);
4732                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4733                         return(-1);
4734                 }
4735 #endif
4736
4737                 case SMB_SET_POSIX_LOCK:
4738                 {
4739                         SMB_BIG_UINT count;
4740                         SMB_BIG_UINT offset;
4741                         uint32 lock_pid;
4742                         BOOL blocking_lock = False;
4743                         enum brl_type lock_type;
4744
4745                         if (fsp == NULL || fsp->fh->fd == -1) {
4746                                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4747                         }
4748
4749                         if (total_data != POSIX_LOCK_DATA_SIZE) {
4750                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4751                         }
4752
4753                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4754                                 case POSIX_LOCK_TYPE_READ:
4755                                         lock_type = READ_LOCK;
4756                                         break;
4757                                 case POSIX_LOCK_TYPE_WRITE:
4758                                         /* Return the right POSIX-mappable error code for files opened read-only. */
4759                                         if (!fsp->can_write) {
4760                                                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
4761                                         }
4762                                         lock_type = WRITE_LOCK;
4763                                         break;
4764                                 case POSIX_LOCK_TYPE_UNLOCK:
4765                                         lock_type = UNLOCK_LOCK;
4766                                         break;
4767                                 default:
4768                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4769                         }
4770
4771                         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4772                                 blocking_lock = False;
4773                         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4774                                 blocking_lock = True;
4775                         } else {
4776                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4777                         }
4778
4779                         if (!lp_blocking_locks(SNUM(conn))) { 
4780                                 blocking_lock = False;
4781                         }
4782
4783                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4784 #if defined(HAVE_LONGLONG)
4785                         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4786                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4787                         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4788                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4789 #else /* HAVE_LONGLONG */
4790                         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4791                         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4792 #endif /* HAVE_LONGLONG */
4793
4794                         if (lock_type == UNLOCK_LOCK) {
4795                                 status = do_unlock(fsp,
4796                                                 lock_pid,
4797                                                 count,
4798                                                 offset,
4799                                                 POSIX_LOCK);
4800                         } else {
4801                                 struct byte_range_lock *br_lck = do_lock(fsp,
4802                                                                         lock_pid,
4803                                                                         count,
4804                                                                         offset,
4805                                                                         lock_type,
4806                                                                         POSIX_LOCK,
4807                                                                         blocking_lock,
4808                                                                         &status);
4809
4810                                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4811                                         /*
4812                                          * A blocking lock was requested. Package up
4813                                          * this smb into a queued request and push it
4814                                          * onto the blocking lock queue.
4815                                          */
4816                                         if(push_blocking_lock_request(br_lck,
4817                                                                 inbuf, length,
4818                                                                 fsp,
4819                                                                 -1, /* infinite timeout. */
4820                                                                 0,
4821                                                                 lock_pid,
4822                                                                 lock_type,
4823                                                                 POSIX_LOCK,
4824                                                                 offset,
4825                                                                 count)) {
4826                                                 TALLOC_FREE(br_lck);
4827                                                 return -1;
4828                                         }
4829                                 }
4830                                 TALLOC_FREE(br_lck);
4831                         }
4832
4833                         if (!NT_STATUS_IS_OK(status)) {
4834                                 return ERROR_NT(status);
4835                         }
4836
4837                         SSVAL(params,0,0);
4838                         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4839                         return(-1);
4840                 }
4841
4842                 default:
4843                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4844         }
4845
4846         /* get some defaults (no modifications) if any info is zero or -1. */
4847         if (null_mtime(tvs.actime)) {
4848                 tvs.actime = sbuf.st_atime;
4849         }
4850
4851         if (null_mtime(tvs.modtime)) {
4852                 tvs.modtime = sbuf.st_mtime;
4853         }
4854
4855         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4856         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4857         DEBUG(6,("size: %.0f ", (double)size));
4858
4859         if (dosmode) {
4860                 if (S_ISDIR(sbuf.st_mode))
4861                         dosmode |= aDIR;
4862                 else
4863                         dosmode &= ~aDIR;
4864         }
4865
4866         DEBUG(6,("dosmode: %x\n"  , dosmode));
4867
4868         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4869                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4870                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4871                 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4872
4873                 /*
4874                  * Only do this test if we are not explicitly
4875                  * changing the size of a file.
4876                  */
4877                 if (!size)
4878                         size = get_file_size(sbuf);
4879         }
4880
4881         /*
4882          * Try and set the times, size and mode of this file -
4883          * if they are different from the current values
4884          */
4885
4886         /* check the mode isn't different, before changing it */
4887         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
4888
4889                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
4890
4891                 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
4892                         DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
4893                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4894                 }
4895         }
4896
4897         /* Now the size. */
4898         if (size != get_file_size(sbuf)) {
4899
4900                 int ret;
4901
4902                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
4903                         fname, (double)size ));
4904
4905                 if (fd == -1) {
4906                         files_struct *new_fsp = NULL;
4907
4908                         status = open_file_ntcreate(conn, fname, &sbuf,
4909                                                 FILE_WRITE_DATA,
4910                                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4911                                                 FILE_OPEN,
4912                                                 0,
4913                                                 FILE_ATTRIBUTE_NORMAL,
4914                                                 FORCE_OPLOCK_BREAK_TO_NONE,
4915                                                 NULL, &new_fsp);
4916         
4917                         if (!NT_STATUS_IS_OK(status)) {
4918                                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4919                                         /* We have re-scheduled this call. */
4920                                         return -1;
4921                                 }
4922                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
4923                         }
4924                         ret = vfs_set_filelen(new_fsp, size);
4925                         close_file(new_fsp,NORMAL_CLOSE);
4926                 } else {
4927                         ret = vfs_set_filelen(fsp, size);
4928                 }
4929
4930                 if (ret == -1) {
4931                         return (UNIXERROR(ERRHRD,ERRdiskfull));
4932                 }
4933         }
4934
4935         /*
4936          * Finally the times.
4937          */
4938         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
4939                 if(fsp != NULL) {
4940                         /*
4941                          * This was a setfileinfo on an open file.
4942                          * NT does this a lot. We also need to 
4943                          * set the time here, as it can be read by 
4944                          * FindFirst/FindNext and with the patch for bug #2045
4945                          * in smbd/fileio.c it ensures that this timestamp is
4946                          * kept sticky even after a write. We save the request
4947                          * away and will set it on file close and after a write. JRA.
4948                          */
4949
4950                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
4951                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
4952                                 fsp_set_pending_modtime(fsp, tvs.modtime);
4953                         }
4954
4955                 }
4956                 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
4957
4958                 if(file_utime(conn, fname, &tvs)!=0) {
4959                         return(UNIXERROR(ERRDOS,ERRnoaccess));
4960                 }
4961         }
4962
4963         SSVAL(params,0,0);
4964         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4965   
4966         return(-1);
4967 }
4968
4969 /****************************************************************************
4970  Reply to a TRANS2_MKDIR (make directory with extended attributes).
4971 ****************************************************************************/
4972
4973 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4974                                         char **pparams, int total_params, char **ppdata, int total_data,
4975                                         unsigned int max_data_bytes)
4976 {
4977         char *params = *pparams;
4978         char *pdata = *ppdata;
4979         pstring directory;
4980         SMB_STRUCT_STAT sbuf;
4981         NTSTATUS status = NT_STATUS_OK;
4982         struct ea_list *ea_list = NULL;
4983
4984         if (!CAN_WRITE(conn))
4985                 return ERROR_DOS(ERRSRV,ERRaccess);
4986
4987         if (total_params < 5) {
4988                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4989         }
4990
4991         srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
4992         if (!NT_STATUS_IS_OK(status)) {
4993                 return ERROR_NT(status);
4994         }
4995
4996         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
4997
4998         status = unix_convert(conn, directory, False, NULL, &sbuf);
4999         if (!NT_STATUS_IS_OK(status)) {
5000                 return ERROR_NT(status);
5001         }
5002
5003         /* Any data in this call is an EA list. */
5004         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
5005                 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
5006         }
5007
5008         /*
5009          * OS/2 workplace shell seems to send SET_EA requests of "null"
5010          * length (4 bytes containing IVAL 4).
5011          * They seem to have no effect. Bug #3212. JRA.
5012          */
5013
5014         if (total_data != 4) {
5015                 if (total_data < 10) {
5016                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5017                 }
5018
5019                 if (IVAL(pdata,0) > total_data) {
5020                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
5021                                 IVAL(pdata,0), (unsigned int)total_data));
5022                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5023                 }
5024
5025                 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
5026                                        total_data - 4);
5027                 if (!ea_list) {
5028                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5029                 }
5030         } else if (IVAL(pdata,0) != 4) {
5031                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5032         }
5033
5034         status = check_name(conn, directory);
5035         if (!NT_STATUS_IS_OK(status)) {
5036                 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
5037                 return ERROR_NT(status);
5038         }
5039
5040         status = create_directory(conn, directory);
5041
5042         if (!NT_STATUS_IS_OK(status)) {
5043                 return ERROR_NT(status);
5044         }
5045   
5046         /* Try and set any given EA. */
5047         if (ea_list) {
5048                 status = set_ea(conn, NULL, directory, ea_list);
5049                 if (!NT_STATUS_IS_OK(status)) {
5050                         return ERROR_NT(status);
5051                 }
5052         }
5053
5054         /* Realloc the parameter and data sizes */
5055         *pparams = (char *)SMB_REALLOC(*pparams,2);
5056         if(*pparams == NULL) {
5057                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5058         }
5059         params = *pparams;
5060
5061         SSVAL(params,0,0);
5062
5063         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5064   
5065         return(-1);
5066 }
5067
5068 /****************************************************************************
5069  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
5070  We don't actually do this - we just send a null response.
5071 ****************************************************************************/
5072
5073 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5074                                         char **pparams, int total_params, char **ppdata, int total_data,
5075                                         unsigned int max_data_bytes)
5076 {
5077         static uint16 fnf_handle = 257;
5078         char *params = *pparams;
5079         uint16 info_level;
5080
5081         if (total_params < 6) {
5082                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5083         }
5084
5085         info_level = SVAL(params,4);
5086         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
5087
5088         switch (info_level) {
5089                 case 1:
5090                 case 2:
5091                         break;
5092                 default:
5093                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5094         }
5095
5096         /* Realloc the parameter and data sizes */
5097         *pparams = (char *)SMB_REALLOC(*pparams,6);
5098         if (*pparams == NULL) {
5099                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5100         }
5101         params = *pparams;
5102
5103         SSVAL(params,0,fnf_handle);
5104         SSVAL(params,2,0); /* No changes */
5105         SSVAL(params,4,0); /* No EA errors */
5106
5107         fnf_handle++;
5108
5109         if(fnf_handle == 0)
5110                 fnf_handle = 257;
5111
5112         send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
5113   
5114         return(-1);
5115 }
5116
5117 /****************************************************************************
5118  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
5119  changes). Currently this does nothing.
5120 ****************************************************************************/
5121
5122 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5123                                         char **pparams, int total_params, char **ppdata, int total_data,
5124                                         unsigned int max_data_bytes)
5125 {
5126         char *params = *pparams;
5127
5128         DEBUG(3,("call_trans2findnotifynext\n"));
5129
5130         /* Realloc the parameter and data sizes */
5131         *pparams = (char *)SMB_REALLOC(*pparams,4);
5132         if (*pparams == NULL) {
5133                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5134         }
5135         params = *pparams;
5136
5137         SSVAL(params,0,0); /* No changes */
5138         SSVAL(params,2,0); /* No EA errors */
5139
5140         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
5141   
5142         return(-1);
5143 }
5144
5145 /****************************************************************************
5146  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
5147 ****************************************************************************/
5148
5149 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
5150                                         char **pparams, int total_params, char **ppdata, int total_data,
5151                                         unsigned int max_data_bytes)
5152 {
5153         char *params = *pparams;
5154         pstring pathname;
5155         int reply_size = 0;
5156         int max_referral_level;
5157
5158         DEBUG(10,("call_trans2getdfsreferral\n"));
5159
5160         if (total_params < 3) {
5161                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5162         }
5163
5164         max_referral_level = SVAL(params,0);
5165
5166         if(!lp_host_msdfs())
5167                 return ERROR_DOS(ERRDOS,ERRbadfunc);
5168
5169         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
5170         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
5171                 return UNIXERROR(ERRDOS,ERRbadfile);
5172     
5173         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
5174         send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
5175
5176         return(-1);
5177 }
5178
5179 #define LMCAT_SPL       0x53
5180 #define LMFUNC_GETJOBID 0x60
5181
5182 /****************************************************************************
5183  Reply to a TRANS2_IOCTL - used for OS/2 printing.
5184 ****************************************************************************/
5185
5186 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
5187                                         char **pparams, int total_params, char **ppdata, int total_data,
5188                                         unsigned int max_data_bytes)
5189 {
5190         char *pdata = *ppdata;
5191         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
5192
5193         /* check for an invalid fid before proceeding */
5194         
5195         if (!fsp)                                
5196                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
5197
5198         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5199                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5200                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
5201                 if (*ppdata == NULL) {
5202                         return ERROR_NT(NT_STATUS_NO_MEMORY);
5203                 }
5204                 pdata = *ppdata;
5205
5206                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5207                         CAN ACCEPT THIS IN UNICODE. JRA. */
5208
5209                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
5210                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
5211                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
5212                 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
5213                 return(-1);
5214         } else {
5215                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5216                 return ERROR_DOS(ERRSRV,ERRerror);
5217         }
5218 }
5219
5220 /****************************************************************************
5221  Reply to a SMBfindclose (stop trans2 directory search).
5222 ****************************************************************************/
5223
5224 int reply_findclose(connection_struct *conn,
5225                     char *inbuf,char *outbuf,int length,int bufsize)
5226 {
5227         int outsize = 0;
5228         int dptr_num=SVALS(inbuf,smb_vwv0);
5229         START_PROFILE(SMBfindclose);
5230
5231         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
5232
5233         dptr_close(&dptr_num);
5234
5235         outsize = set_message(outbuf,0,0,False);
5236
5237         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
5238
5239         END_PROFILE(SMBfindclose);
5240         return(outsize);
5241 }
5242
5243 /****************************************************************************
5244  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
5245 ****************************************************************************/
5246
5247 int reply_findnclose(connection_struct *conn, 
5248                      char *inbuf,char *outbuf,int length,int bufsize)
5249 {
5250         int outsize = 0;
5251         int dptr_num= -1;
5252         START_PROFILE(SMBfindnclose);
5253         
5254         dptr_num = SVAL(inbuf,smb_vwv0);
5255
5256         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
5257
5258         /* We never give out valid handles for a 
5259            findnotifyfirst - so any dptr_num is ok here. 
5260            Just ignore it. */
5261
5262         outsize = set_message(outbuf,0,0,False);
5263
5264         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
5265
5266         END_PROFILE(SMBfindnclose);
5267         return(outsize);
5268 }
5269
5270 int handle_trans2(connection_struct *conn,
5271                   struct trans_state *state,
5272                   char *inbuf, char *outbuf, int size, int bufsize)
5273 {
5274         int outsize;
5275
5276         if (Protocol >= PROTOCOL_NT1) {
5277                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5278         }
5279
5280         /* Now we must call the relevant TRANS2 function */
5281         switch(state->call)  {
5282         case TRANSACT2_OPEN:
5283         {
5284                 START_PROFILE(Trans2_open);
5285                 outsize = call_trans2open(
5286                         conn, inbuf, outbuf, bufsize, 
5287                         &state->param, state->total_param,
5288                         &state->data, state->total_data,
5289                         state->max_data_return);
5290                 END_PROFILE(Trans2_open);
5291                 break;
5292         }
5293
5294         case TRANSACT2_FINDFIRST:
5295         {
5296                 START_PROFILE(Trans2_findfirst);
5297                 outsize = call_trans2findfirst(
5298                         conn, inbuf, outbuf, bufsize,
5299                         &state->param, state->total_param,
5300                         &state->data, state->total_data,
5301                         state->max_data_return);
5302                 END_PROFILE(Trans2_findfirst);
5303                 break;
5304         }
5305
5306         case TRANSACT2_FINDNEXT:
5307         {
5308                 START_PROFILE(Trans2_findnext);
5309                 outsize = call_trans2findnext(
5310                         conn, inbuf, outbuf, size, bufsize, 
5311                         &state->param, state->total_param,
5312                         &state->data, state->total_data,
5313                         state->max_data_return);
5314                 END_PROFILE(Trans2_findnext);
5315                 break;
5316         }
5317
5318         case TRANSACT2_QFSINFO:
5319         {
5320                 START_PROFILE(Trans2_qfsinfo);
5321                 outsize = call_trans2qfsinfo(
5322                         conn, inbuf, outbuf, size, bufsize,
5323                         &state->param, state->total_param,
5324                         &state->data, state->total_data,
5325                         state->max_data_return);
5326                 END_PROFILE(Trans2_qfsinfo);
5327             break;
5328         }
5329
5330         case TRANSACT2_SETFSINFO:
5331         {
5332                 START_PROFILE(Trans2_setfsinfo);
5333                 outsize = call_trans2setfsinfo(
5334                         conn, inbuf, outbuf, size, bufsize, 
5335                         &state->param, state->total_param,
5336                         &state->data, state->total_data,
5337                         state->max_data_return);
5338                 END_PROFILE(Trans2_setfsinfo);
5339                 break;
5340         }
5341
5342         case TRANSACT2_QPATHINFO:
5343         case TRANSACT2_QFILEINFO:
5344         {
5345                 START_PROFILE(Trans2_qpathinfo);
5346                 outsize = call_trans2qfilepathinfo(
5347                         conn, inbuf, outbuf, size, bufsize, state->call,
5348                         &state->param, state->total_param,
5349                         &state->data, state->total_data,
5350                         state->max_data_return);
5351                 END_PROFILE(Trans2_qpathinfo);
5352                 break;
5353         }
5354
5355         case TRANSACT2_SETPATHINFO:
5356         case TRANSACT2_SETFILEINFO:
5357         {
5358                 START_PROFILE(Trans2_setpathinfo);
5359                 outsize = call_trans2setfilepathinfo(
5360                         conn, inbuf, outbuf, size, bufsize, state->call,
5361                         &state->param, state->total_param,
5362                         &state->data, state->total_data,
5363                         state->max_data_return);
5364                 END_PROFILE(Trans2_setpathinfo);
5365                 break;
5366         }
5367
5368         case TRANSACT2_FINDNOTIFYFIRST:
5369         {
5370                 START_PROFILE(Trans2_findnotifyfirst);
5371                 outsize = call_trans2findnotifyfirst(
5372                         conn, inbuf, outbuf, size, bufsize, 
5373                         &state->param, state->total_param,
5374                         &state->data, state->total_data,
5375                         state->max_data_return);
5376                 END_PROFILE(Trans2_findnotifyfirst);
5377                 break;
5378         }
5379
5380         case TRANSACT2_FINDNOTIFYNEXT:
5381         {
5382                 START_PROFILE(Trans2_findnotifynext);
5383                 outsize = call_trans2findnotifynext(
5384                         conn, inbuf, outbuf, size, bufsize, 
5385                         &state->param, state->total_param,
5386                         &state->data, state->total_data,
5387                         state->max_data_return);
5388                 END_PROFILE(Trans2_findnotifynext);
5389                 break;
5390         }
5391
5392         case TRANSACT2_MKDIR:
5393         {
5394                 START_PROFILE(Trans2_mkdir);
5395                 outsize = call_trans2mkdir(
5396                         conn, inbuf, outbuf, size, bufsize,
5397                         &state->param, state->total_param,
5398                         &state->data, state->total_data,
5399                         state->max_data_return);
5400                 END_PROFILE(Trans2_mkdir);
5401                 break;
5402         }
5403
5404         case TRANSACT2_GET_DFS_REFERRAL:
5405         {
5406                 START_PROFILE(Trans2_get_dfs_referral);
5407                 outsize = call_trans2getdfsreferral(
5408                         conn, inbuf, outbuf, size, bufsize,
5409                         &state->param, state->total_param,
5410                         &state->data, state->total_data,
5411                         state->max_data_return);
5412                 END_PROFILE(Trans2_get_dfs_referral);
5413                 break;
5414         }
5415
5416         case TRANSACT2_IOCTL:
5417         {
5418                 START_PROFILE(Trans2_ioctl);
5419                 outsize = call_trans2ioctl(
5420                         conn, inbuf, outbuf, size, bufsize,
5421                         &state->param, state->total_param,
5422                         &state->data, state->total_data,
5423                         state->max_data_return);
5424                 END_PROFILE(Trans2_ioctl);
5425                 break;
5426         }
5427
5428         default:
5429                 /* Error in request */
5430                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5431                 outsize = ERROR_DOS(ERRSRV,ERRerror);
5432         }
5433
5434         return outsize;
5435 }
5436
5437 /****************************************************************************
5438  Reply to a SMBtrans2.
5439  ****************************************************************************/
5440
5441 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
5442                  int size, int bufsize)
5443 {
5444         int outsize = 0;
5445         unsigned int dsoff = SVAL(inbuf, smb_dsoff);
5446         unsigned int dscnt = SVAL(inbuf, smb_dscnt);
5447         unsigned int psoff = SVAL(inbuf, smb_psoff);
5448         unsigned int pscnt = SVAL(inbuf, smb_pscnt);
5449         unsigned int tran_call = SVAL(inbuf, smb_setup0);
5450         struct trans_state *state;
5451         NTSTATUS result;
5452
5453         START_PROFILE(SMBtrans2);
5454
5455         result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
5456         if (!NT_STATUS_IS_OK(result)) {
5457                 DEBUG(2, ("Got invalid trans2 request: %s\n",
5458                           nt_errstr(result)));
5459                 END_PROFILE(SMBtrans2);
5460                 return ERROR_NT(result);
5461         }
5462
5463         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
5464             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
5465                 END_PROFILE(SMBtrans2);
5466                 return ERROR_DOS(ERRSRV,ERRaccess);
5467         }
5468
5469         if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
5470                 DEBUG(0, ("talloc failed\n"));
5471                 END_PROFILE(SMBtrans2);
5472                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5473         }
5474
5475         state->cmd = SMBtrans2;
5476
5477         state->mid = SVAL(inbuf, smb_mid);
5478         state->vuid = SVAL(inbuf, smb_uid);
5479         state->setup_count = SVAL(inbuf, smb_suwcnt);
5480         state->setup = NULL;
5481         state->total_param = SVAL(inbuf, smb_tpscnt);
5482         state->param = NULL;
5483         state->total_data =  SVAL(inbuf, smb_tdscnt);
5484         state->data = NULL;
5485         state->max_param_return = SVAL(inbuf, smb_mprcnt);
5486         state->max_data_return  = SVAL(inbuf, smb_mdrcnt);
5487         state->max_setup_return = SVAL(inbuf, smb_msrcnt);
5488         state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
5489         state->one_way = BITSETW(inbuf+smb_vwv5,1);
5490
5491         state->call = tran_call;
5492
5493         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5494            is so as a sanity check */
5495         if (state->setup_count != 1) {
5496                 /*
5497                  * Need to have rc=0 for ioctl to get job id for OS/2.
5498                  *  Network printing will fail if function is not successful.
5499                  *  Similar function in reply.c will be used if protocol
5500                  *  is LANMAN1.0 instead of LM1.2X002.
5501                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
5502                  *  outbuf doesn't have to be set(only job id is used).
5503                  */
5504                 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
5505                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5506                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5507                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5508                 } else {
5509                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5510                         DEBUG(2,("Transaction is %d\n",tran_call));
5511                         TALLOC_FREE(state);
5512                         END_PROFILE(SMBtrans2);
5513                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5514                 }
5515         }
5516
5517         if ((dscnt > state->total_data) || (pscnt > state->total_param))
5518                 goto bad_param;
5519
5520         if (state->total_data) {
5521                 /* Can't use talloc here, the core routines do realloc on the
5522                  * params and data. */
5523                 state->data = (char *)SMB_MALLOC(state->total_data);
5524                 if (state->data == NULL) {
5525                         DEBUG(0,("reply_trans2: data malloc fail for %u "
5526                                  "bytes !\n", (unsigned int)state->total_data));
5527                         TALLOC_FREE(state);
5528                         END_PROFILE(SMBtrans2);
5529                         return(ERROR_DOS(ERRDOS,ERRnomem));
5530                 }
5531                 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
5532                         goto bad_param;
5533                 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
5534                     (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
5535                         goto bad_param;
5536
5537                 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
5538         }
5539
5540         if (state->total_param) {
5541                 /* Can't use talloc here, the core routines do realloc on the
5542                  * params and data. */
5543                 state->param = (char *)SMB_MALLOC(state->total_param);
5544                 if (state->param == NULL) {
5545                         DEBUG(0,("reply_trans: param malloc fail for %u "
5546                                  "bytes !\n", (unsigned int)state->total_param));
5547                         SAFE_FREE(state->data);
5548                         TALLOC_FREE(state);
5549                         END_PROFILE(SMBtrans2);
5550                         return(ERROR_DOS(ERRDOS,ERRnomem));
5551                 } 
5552                 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
5553                         goto bad_param;
5554                 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
5555                     (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
5556                         goto bad_param;
5557
5558                 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
5559         }
5560
5561         state->received_data  = dscnt;
5562         state->received_param = pscnt;
5563
5564         if ((state->received_param == state->total_param) &&
5565             (state->received_data == state->total_data)) {
5566
5567                 outsize = handle_trans2(conn, state, inbuf, outbuf,
5568                                         size, bufsize);
5569                 SAFE_FREE(state->data);
5570                 SAFE_FREE(state->param);
5571                 TALLOC_FREE(state);
5572                 END_PROFILE(SMBtrans2);
5573                 return outsize;
5574         }
5575
5576         DLIST_ADD(conn->pending_trans, state);
5577
5578         /* We need to send an interim response then receive the rest
5579            of the parameter/data bytes */
5580         outsize = set_message(outbuf,0,0,False);
5581         show_msg(outbuf);
5582         END_PROFILE(SMBtrans2);
5583         return outsize;
5584
5585   bad_param:
5586
5587         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5588         SAFE_FREE(state->data);
5589         SAFE_FREE(state->param);
5590         TALLOC_FREE(state);
5591         END_PROFILE(SMBtrans2);
5592         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5593 }
5594
5595
5596 /****************************************************************************
5597  Reply to a SMBtranss2
5598  ****************************************************************************/
5599
5600 int reply_transs2(connection_struct *conn,
5601                   char *inbuf,char *outbuf,int size,int bufsize)
5602 {
5603         int outsize = 0;
5604         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5605         struct trans_state *state;
5606
5607         START_PROFILE(SMBtranss2);
5608
5609         show_msg(inbuf);
5610
5611         for (state = conn->pending_trans; state != NULL;
5612              state = state->next) {
5613                 if (state->mid == SVAL(inbuf,smb_mid)) {
5614                         break;
5615                 }
5616         }
5617
5618         if ((state == NULL) || (state->cmd != SMBtrans2)) {
5619                 END_PROFILE(SMBtranss2);
5620                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5621         }
5622
5623         /* Revise state->total_param and state->total_data in case they have
5624            changed downwards */
5625
5626         if (SVAL(inbuf, smb_tpscnt) < state->total_param)
5627                 state->total_param = SVAL(inbuf, smb_tpscnt);
5628         if (SVAL(inbuf, smb_tdscnt) < state->total_data)
5629                 state->total_data = SVAL(inbuf, smb_tdscnt);
5630
5631         pcnt = SVAL(inbuf, smb_spscnt);
5632         poff = SVAL(inbuf, smb_spsoff);
5633         pdisp = SVAL(inbuf, smb_spsdisp);
5634
5635         dcnt = SVAL(inbuf, smb_sdscnt);
5636         doff = SVAL(inbuf, smb_sdsoff);
5637         ddisp = SVAL(inbuf, smb_sdsdisp);
5638
5639         state->received_param += pcnt;
5640         state->received_data += dcnt;
5641                 
5642         if ((state->received_data > state->total_data) ||
5643             (state->received_param > state->total_param))
5644                 goto bad_param;
5645
5646         if (pcnt) {
5647                 if (pdisp+pcnt > state->total_param)
5648                         goto bad_param;
5649                 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
5650                         goto bad_param;
5651                 if (pdisp > state->total_param)
5652                         goto bad_param;
5653                 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
5654                     (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
5655                         goto bad_param;
5656                 if (state->param + pdisp < state->param)
5657                         goto bad_param;
5658
5659                 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
5660                        pcnt);
5661         }
5662
5663         if (dcnt) {
5664                 if (ddisp+dcnt > state->total_data)
5665                         goto bad_param;
5666                 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
5667                         goto bad_param;
5668                 if (ddisp > state->total_data)
5669                         goto bad_param;
5670                 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
5671                     (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
5672                         goto bad_param;
5673                 if (state->data + ddisp < state->data)
5674                         goto bad_param;
5675
5676                 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
5677                        dcnt);      
5678         }
5679
5680         if ((state->received_param < state->total_param) ||
5681             (state->received_data < state->total_data)) {
5682                 END_PROFILE(SMBtranss2);
5683                 return -1;
5684         }
5685
5686         /* construct_reply_common has done us the favor to pre-fill the
5687          * command field with SMBtranss2 which is wrong :-)
5688          */
5689         SCVAL(outbuf,smb_com,SMBtrans2);
5690
5691         outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
5692
5693         DLIST_REMOVE(conn->pending_trans, state);
5694         SAFE_FREE(state->data);
5695         SAFE_FREE(state->param);
5696         TALLOC_FREE(state);
5697
5698         if (outsize == 0) {
5699                 END_PROFILE(SMBtranss2);
5700                 return(ERROR_DOS(ERRSRV,ERRnosupport));
5701         }
5702         
5703         END_PROFILE(SMBtranss2);
5704         return(outsize);
5705
5706   bad_param:
5707
5708         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5709         DLIST_REMOVE(conn->pending_trans, state);
5710         SAFE_FREE(state->data);
5711         SAFE_FREE(state->param);
5712         TALLOC_FREE(state);
5713         END_PROFILE(SMBtranss2);
5714         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5715 }