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