r21063: All case statements are now NTSTATUS returning
[tprouty/samba.git] / source / 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 SMB_INFO_SET_EA.
3746 ****************************************************************************/
3747
3748 static NTSTATUS smb_info_set_ea(connection_struct *conn,
3749                                 const char *pdata,
3750                                 int total_data,
3751                                 files_struct *fsp,
3752                                 const char *fname)
3753 {
3754         struct ea_list *ea_list = NULL;
3755         TALLOC_CTX *ctx = NULL;
3756         NTSTATUS status = NT_STATUS_OK;
3757
3758         if (total_data < 10) {
3759
3760                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
3761                    length. They seem to have no effect. Bug #3212. JRA */
3762
3763                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
3764                         /* We're done. We only get EA info in this call. */
3765                         return NT_STATUS_OK;
3766                 }
3767
3768                 return NT_STATUS_INVALID_PARAMETER;
3769         }
3770
3771         if (IVAL(pdata,0) > total_data) {
3772                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
3773                         IVAL(pdata,0), (unsigned int)total_data));
3774                 return NT_STATUS_INVALID_PARAMETER;
3775         }
3776
3777         ctx = talloc_init("SMB_INFO_SET_EA");
3778         if (!ctx) {
3779                 return NT_STATUS_NO_MEMORY;
3780         }
3781         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
3782         if (!ea_list) {
3783                 talloc_destroy(ctx);
3784                 return NT_STATUS_INVALID_PARAMETER;
3785         }
3786         status = set_ea(conn, fsp, fname, ea_list);
3787         talloc_destroy(ctx);
3788
3789         return status;
3790 }
3791
3792 /****************************************************************************
3793  Deal with SMB_SET_FILE_DISPOSITION_INFO.
3794 ****************************************************************************/
3795
3796 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
3797                                 const char *pdata,
3798                                 int total_data,
3799                                 files_struct *fsp,
3800                                 int dosmode)
3801 {
3802         NTSTATUS status = NT_STATUS_OK;
3803         BOOL delete_on_close;
3804
3805         if (total_data < 1) {
3806                 return NT_STATUS_INVALID_PARAMETER;
3807         }
3808
3809         if (fsp == NULL) {
3810                 return NT_STATUS_INVALID_HANDLE;
3811         }
3812
3813         delete_on_close = (CVAL(pdata,0) ? True : False);
3814
3815         status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
3816  
3817         if (!NT_STATUS_IS_OK(status)) {
3818                 return status;
3819         }
3820
3821         /* The set is across all open files on this dev/inode pair. */
3822         if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
3823                 return NT_STATUS_ACCESS_DENIED;
3824         }
3825         return NT_STATUS_OK;
3826 }
3827
3828 /****************************************************************************
3829  Deal with SMB_FILE_POSITION_INFORMATION.
3830 ****************************************************************************/
3831
3832 static NTSTATUS smb_file_position_information(connection_struct *conn,
3833                                 const char *pdata,
3834                                 int total_data,
3835                                 files_struct *fsp)
3836 {
3837         SMB_BIG_UINT position_information;
3838
3839         if (total_data < 8) {
3840                 return NT_STATUS_INVALID_PARAMETER;
3841         }
3842
3843         if (fsp == NULL) {
3844                 /* Ignore on pathname based set. */
3845                 return NT_STATUS_OK;
3846         }
3847
3848         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
3849 #ifdef LARGE_SMB_OFF_T
3850         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
3851 #else /* LARGE_SMB_OFF_T */
3852         if (IVAL(pdata,4) != 0) {
3853                 /* more than 32 bits? */
3854                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3855         }
3856 #endif /* LARGE_SMB_OFF_T */
3857
3858         DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
3859                 fsp->fsp_name, (double)position_information ));
3860         fsp->fh->position_information = position_information;
3861         return NT_STATUS_OK;
3862 }
3863
3864 /****************************************************************************
3865  Deal with SMB_FILE_MODE_INFORMATION.
3866 ****************************************************************************/
3867
3868 static NTSTATUS smb_file_mode_information(connection_struct *conn,
3869                                 const char *pdata,
3870                                 int total_data)
3871 {
3872         uint32 mode;
3873
3874         if (total_data < 4) {
3875                 return NT_STATUS_INVALID_PARAMETER;
3876         }
3877         mode = IVAL(pdata,0);
3878         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
3879                 return NT_STATUS_INVALID_PARAMETER;
3880         }
3881         return NT_STATUS_OK;
3882 }
3883
3884 /****************************************************************************
3885  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
3886 ****************************************************************************/
3887
3888 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
3889                                 char *inbuf,
3890                                 const char *pdata,
3891                                 int total_data,
3892                                 const char *fname)
3893 {
3894         pstring link_target;
3895         const char *newname = fname;
3896         NTSTATUS status = NT_STATUS_OK;
3897
3898         /* Set a symbolic link. */
3899         /* Don't allow this if follow links is false. */
3900
3901         if (total_data == 0) {
3902                 return NT_STATUS_INVALID_PARAMETER;
3903         }
3904
3905         if (!lp_symlinks(SNUM(conn))) {
3906                 return NT_STATUS_ACCESS_DENIED;
3907         }
3908
3909         srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
3910
3911         /* !widelinks forces the target path to be within the share. */
3912         /* This means we can interpret the target as a pathname. */
3913         if (!lp_widelinks(SNUM(conn))) {
3914                 pstring rel_name;
3915                 char *last_dirp = NULL;
3916
3917                 unix_format(link_target);
3918                 if (*link_target == '/') {
3919                         /* No absolute paths allowed. */
3920                         return NT_STATUS_ACCESS_DENIED;
3921                 }
3922                 pstrcpy(rel_name, newname);
3923                 last_dirp = strrchr_m(rel_name, '/');
3924                 if (last_dirp) {
3925                         last_dirp[1] = '\0';
3926                 } else {
3927                         pstrcpy(rel_name, "./");
3928                 }
3929                 pstrcat(rel_name, link_target);
3930
3931                 status = check_name(conn, rel_name);
3932                 if (!NT_STATUS_IS_OK(status)) {
3933                         return status;
3934                 }
3935         }
3936
3937         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
3938                         newname, link_target ));
3939
3940         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
3941                 return map_nt_error_from_unix(errno);
3942         }
3943
3944         return NT_STATUS_OK;
3945 }
3946
3947 /****************************************************************************
3948  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
3949 ****************************************************************************/
3950
3951 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
3952                                 char *inbuf,
3953                                 const char *pdata,
3954                                 int total_data,
3955                                 pstring fname)
3956 {
3957         pstring oldname;
3958         NTSTATUS status = NT_STATUS_OK;
3959
3960         /* Set a hard link. */
3961         if (total_data == 0) {
3962                 return NT_STATUS_INVALID_PARAMETER;
3963         }
3964
3965         srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
3966         if (!NT_STATUS_IS_OK(status)) {
3967                 return status;
3968         }
3969
3970         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
3971                 fname, oldname));
3972
3973         return hardlink_internals(conn, oldname, fname);
3974 }
3975
3976 /****************************************************************************
3977  Deal with SMB_FILE_RENAME_INFORMATION.
3978 ****************************************************************************/
3979
3980 static NTSTATUS smb_file_rename_information(connection_struct *conn,
3981                                 char *inbuf,
3982                                 char *outbuf,
3983                                 const char *pdata,
3984                                 int total_data,
3985                                 files_struct *fsp,
3986                                 pstring fname)
3987 {
3988         BOOL overwrite;
3989         /* uint32 root_fid; */  /* Not used */
3990         uint32 len;
3991         pstring newname;
3992         pstring base_name;
3993         NTSTATUS status = NT_STATUS_OK;
3994         char *p;
3995
3996         if (total_data < 13) {
3997                 return NT_STATUS_INVALID_PARAMETER;
3998         }
3999
4000         overwrite = (CVAL(pdata,0) ? True : False);
4001         /* root_fid = IVAL(pdata,4); */
4002         len = IVAL(pdata,8);
4003
4004         if (len > (total_data - 12) || (len == 0)) {
4005                 return NT_STATUS_INVALID_PARAMETER;
4006         }
4007
4008         srvstr_get_path(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status);
4009         if (!NT_STATUS_IS_OK(status)) {
4010                 return status;
4011         }
4012
4013         /* Check the new name has no '/' characters. */
4014         if (strchr_m(newname, '/')) {
4015                 return NT_STATUS_NOT_SUPPORTED;
4016         }
4017
4018         RESOLVE_DFSPATH_STATUS(newname, conn, inbuf, outbuf);
4019
4020         /* Create the base directory. */
4021         pstrcpy(base_name, fname);
4022         p = strrchr_m(base_name, '/');
4023         if (p) {
4024                 *p = '\0';
4025         }
4026         /* Append the new name. */
4027         pstrcat(base_name, "/");
4028         pstrcat(base_name, newname);
4029
4030         if (fsp) {
4031                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4032                         fsp->fnum, fsp->fsp_name, base_name ));
4033                 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4034         } else {
4035                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4036                         fname, newname ));
4037                 status = rename_internals(conn, fname, base_name, 0, overwrite, False);
4038         }
4039
4040         return status;
4041 }
4042
4043 /****************************************************************************
4044  Deal with SMB_SET_POSIX_ACL.
4045 ****************************************************************************/
4046
4047 #if defined(HAVE_POSIX_ACLS)
4048 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4049                                 const char *pdata,
4050                                 int total_data,
4051                                 files_struct *fsp,
4052                                 SMB_STRUCT_STAT *psbuf,
4053                                 const char *fname)
4054 {
4055         uint16 posix_acl_version;
4056         uint16 num_file_acls;
4057         uint16 num_def_acls;
4058         BOOL valid_file_acls = True;
4059         BOOL valid_def_acls = True;
4060
4061         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4062                 return NT_STATUS_INVALID_PARAMETER;
4063         }
4064         posix_acl_version = SVAL(pdata,0);
4065         num_file_acls = SVAL(pdata,2);
4066         num_def_acls = SVAL(pdata,4);
4067
4068         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4069                 valid_file_acls = False;
4070                 num_file_acls = 0;
4071         }
4072
4073         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4074                 valid_def_acls = False;
4075                 num_def_acls = 0;
4076         }
4077
4078         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4079                 return NT_STATUS_INVALID_PARAMETER;
4080         }
4081
4082         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4083                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4084                 return NT_STATUS_INVALID_PARAMETER;
4085         }
4086
4087         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4088                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4089                 return map_nt_error_from_unix(errno);
4090         }
4091
4092         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4093                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
4094                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4095                 return map_nt_error_from_unix(errno);
4096         }
4097         return NT_STATUS_OK;
4098 }
4099 #endif
4100
4101 /****************************************************************************
4102  Deal with SMB_SET_POSIX_LOCK.
4103 ****************************************************************************/
4104
4105 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4106                                 char *inbuf,
4107                                 int length,
4108                                 const char *pdata,
4109                                 int total_data,
4110                                 files_struct *fsp)
4111 {
4112         SMB_BIG_UINT count;
4113         SMB_BIG_UINT offset;
4114         uint32 lock_pid;
4115         BOOL blocking_lock = False;
4116         enum brl_type lock_type;
4117         NTSTATUS status = NT_STATUS_OK;
4118
4119         if (fsp == NULL || fsp->fh->fd == -1) {
4120                 return NT_STATUS_INVALID_HANDLE;
4121         }
4122
4123         if (total_data != POSIX_LOCK_DATA_SIZE) {
4124                 return NT_STATUS_INVALID_PARAMETER;
4125         }
4126
4127         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4128                 case POSIX_LOCK_TYPE_READ:
4129                         lock_type = READ_LOCK;
4130                         break;
4131                 case POSIX_LOCK_TYPE_WRITE:
4132                         /* Return the right POSIX-mappable error code for files opened read-only. */
4133                         if (!fsp->can_write) {
4134                                 return NT_STATUS_INVALID_HANDLE;
4135                         }
4136                         lock_type = WRITE_LOCK;
4137                         break;
4138                 case POSIX_LOCK_TYPE_UNLOCK:
4139                         lock_type = UNLOCK_LOCK;
4140                         break;
4141                 default:
4142                         return NT_STATUS_INVALID_PARAMETER;
4143         }
4144
4145         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4146                 blocking_lock = False;
4147         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4148                 blocking_lock = True;
4149         } else {
4150                 return NT_STATUS_INVALID_PARAMETER;
4151         }
4152
4153         if (!lp_blocking_locks(SNUM(conn))) { 
4154                 blocking_lock = False;
4155         }
4156
4157         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4158 #if defined(HAVE_LONGLONG)
4159         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4160                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4161         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4162                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4163 #else /* HAVE_LONGLONG */
4164         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4165         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4166 #endif /* HAVE_LONGLONG */
4167
4168         if (lock_type == UNLOCK_LOCK) {
4169                 status = do_unlock(fsp,
4170                                 lock_pid,
4171                                 count,
4172                                 offset,
4173                                 POSIX_LOCK);
4174         } else {
4175                 struct byte_range_lock *br_lck = do_lock(fsp,
4176                                                         lock_pid,
4177                                                         count,
4178                                                         offset,
4179                                                         lock_type,
4180                                                         POSIX_LOCK,
4181                                                         blocking_lock,
4182                                                         &status);
4183
4184                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4185                         /*
4186                          * A blocking lock was requested. Package up
4187                          * this smb into a queued request and push it
4188                          * onto the blocking lock queue.
4189                          */
4190                         if(push_blocking_lock_request(br_lck,
4191                                                 inbuf, length,
4192                                                 fsp,
4193                                                 -1, /* infinite timeout. */
4194                                                 0,
4195                                                 lock_pid,
4196                                                 lock_type,
4197                                                 POSIX_LOCK,
4198                                                 offset,
4199                                                 count)) {
4200                                 TALLOC_FREE(br_lck);
4201                                 return status;
4202                         }
4203                 }
4204                 TALLOC_FREE(br_lck);
4205         }
4206
4207         return status;
4208 }
4209
4210 /****************************************************************************
4211  Deal with SMB_INFO_STANDARD.
4212 ****************************************************************************/
4213
4214 static NTSTATUS smb_set_info_standard(const char *pdata,
4215                                         int total_data,
4216                                         struct utimbuf *p_tvs)
4217 {
4218         if (total_data < 12) {
4219                 return NT_STATUS_INVALID_PARAMETER;
4220         }
4221
4222         /* access time */
4223         p_tvs->actime = srv_make_unix_date2(pdata+l1_fdateLastAccess);
4224         /* write time */
4225         p_tvs->modtime = srv_make_unix_date2(pdata+l1_fdateLastWrite);
4226         return NT_STATUS_OK;
4227 }
4228
4229 /****************************************************************************
4230  Deal with SMB_SET_FILE_BASIC_INFO.
4231 ****************************************************************************/
4232
4233 static NTSTATUS smb_set_file_basic_info(const char *pdata,
4234                                         int total_data,
4235                                         struct utimbuf *p_tvs,
4236                                         int *p_dosmode)
4237 {
4238         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4239         time_t write_time;
4240         time_t changed_time;
4241
4242         if (total_data < 36) {
4243                 return NT_STATUS_INVALID_PARAMETER;
4244         }
4245
4246         /* Ignore create time at offset pdata. */
4247
4248         /* access time */
4249         p_tvs->actime = convert_timespec_to_time_t(interpret_long_date(pdata+8));
4250
4251         write_time = convert_timespec_to_time_t(interpret_long_date(pdata+16));
4252         changed_time = convert_timespec_to_time_t(interpret_long_date(pdata+24));
4253
4254         p_tvs->modtime = MIN(write_time, changed_time);
4255
4256         if (write_time > p_tvs->modtime && write_time != (time_t)-1) {
4257                 p_tvs->modtime = write_time;
4258         }
4259         /* Prefer a defined time to an undefined one. */
4260         if (null_mtime(p_tvs->modtime)) {
4261                 p_tvs->modtime = null_mtime(write_time) ? changed_time : write_time;
4262         }
4263
4264         /* attributes */
4265         *p_dosmode = IVAL(pdata,32);
4266         return NT_STATUS_OK;
4267 }
4268
4269 /****************************************************************************
4270  Deal with SMB_SET_FILE_ALLOCATION_INFO.
4271 ****************************************************************************/
4272
4273 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4274                                         const char *pdata,
4275                                         int total_data,
4276                                         files_struct *fsp,
4277                                         const char *fname,
4278                                         SMB_STRUCT_STAT *psbuf,
4279                                         SMB_OFF_T *p_size)
4280 {
4281         SMB_BIG_UINT allocation_size;
4282
4283         if (total_data < 8) {
4284                 return NT_STATUS_INVALID_PARAMETER;
4285         }
4286
4287         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
4288 #ifdef LARGE_SMB_OFF_T
4289         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4290 #else /* LARGE_SMB_OFF_T */
4291         if (IVAL(pdata,4) != 0) {
4292                 /* more than 32 bits? */
4293                 return NT_STATUS_INVALID_PARAMETER;
4294         }
4295 #endif /* LARGE_SMB_OFF_T */
4296
4297         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
4298                         fname, (double)allocation_size ));
4299
4300         if (allocation_size) {
4301                 allocation_size = smb_roundup(conn, allocation_size);
4302         }
4303
4304         if(allocation_size != get_file_size(*psbuf)) {
4305                 int ret = -1;
4306                 SMB_STRUCT_STAT new_sbuf;
4307  
4308                 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
4309                         fname, (double)allocation_size ));
4310  
4311                 if (fsp && fsp->fh->fd != -1) {
4312                         /* Open file. */
4313                         ret = vfs_allocate_file_space(fsp, allocation_size);
4314                         if (ret == -1) {
4315                                 return map_nt_error_from_unix(errno);
4316                         }
4317                         if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&new_sbuf) != 0) {
4318                                 DEBUG(3,("smb_set_file_allocation_info: fstat of fnum %d failed (%s)\n",
4319                                                         fsp->fnum, strerror(errno)));
4320                                 return map_nt_error_from_unix(errno);
4321                         }
4322                 } else {
4323                         /* Pathname or stat or directory file. */
4324                         files_struct *new_fsp = NULL;
4325                         NTSTATUS status;
4326
4327                         status = open_file_ntcreate(conn, fname, psbuf,
4328                                                 FILE_WRITE_DATA,
4329                                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4330                                                 FILE_OPEN,
4331                                                 0,
4332                                                 FILE_ATTRIBUTE_NORMAL,
4333                                                 FORCE_OPLOCK_BREAK_TO_NONE,
4334                                                 NULL, &new_fsp);
4335  
4336                         if (!NT_STATUS_IS_OK(status)) {
4337                                 /* NB. We check for open_was_deferred in the caller. */
4338                                 return status;
4339                         }
4340                         ret = vfs_allocate_file_space(new_fsp, allocation_size);
4341                         if (ret == -1) {
4342                                 status = map_nt_error_from_unix(errno);
4343                                 close_file(new_fsp,NORMAL_CLOSE);
4344                                 return status;
4345                         }
4346                         if (SMB_VFS_FSTAT(new_fsp,new_fsp->fh->fd,&new_sbuf) != 0) {
4347                                 DEBUG(3,("smb_set_file_allocation_info: fstat of fnum %d failed (%s)\n",
4348                                                 new_fsp->fnum, strerror(errno)));
4349                                 status = map_nt_error_from_unix(errno);
4350                                 close_file(new_fsp,NORMAL_CLOSE);
4351                                 return status;
4352                         }
4353                         close_file(new_fsp,NORMAL_CLOSE);
4354                 }
4355
4356                 /* Allocate can truncate size... */
4357                 *p_size = get_file_size(new_sbuf);
4358         }
4359         return NT_STATUS_OK;
4360 }
4361
4362 /****************************************************************************
4363  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4364 ****************************************************************************/
4365
4366 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4367                                         const char *pdata,
4368                                         int total_data,
4369                                         const char *fname,
4370                                         SMB_OFF_T *p_size)
4371 {
4372         if (total_data < 8) {
4373                 return NT_STATUS_INVALID_PARAMETER;
4374         }
4375
4376         *p_size = IVAL(pdata,0);
4377 #ifdef LARGE_SMB_OFF_T
4378         *p_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4379 #else /* LARGE_SMB_OFF_T */
4380         if (IVAL(pdata,4) != 0) {
4381                 /* more than 32 bits? */
4382                 return NT_STATUS_INVALID_PARAMETER;
4383         }
4384 #endif /* LARGE_SMB_OFF_T */
4385         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
4386                 "file %s to %.0f\n", fname, (double)*p_size ));
4387         return NT_STATUS_OK;
4388 }
4389
4390 /****************************************************************************
4391  Deal with SMB_SET_FILE_UNIX_BASIC.
4392 ****************************************************************************/
4393
4394 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
4395                                         const char *pdata,
4396                                         int total_data,
4397                                         files_struct *fsp,
4398                                         const char *fname,
4399                                         SMB_STRUCT_STAT *psbuf,
4400                                         SMB_OFF_T *p_size,
4401                                         struct utimbuf *p_tvs,
4402                                         mode_t *p_unixmode,
4403                                         int *p_dosmode)
4404 {
4405         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
4406         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
4407         uint32 raw_unixmode;
4408         BOOL delete_on_fail = False;
4409         NTSTATUS status = NT_STATUS_OK;
4410
4411         if (total_data < 100) {
4412                 return NT_STATUS_INVALID_PARAMETER;
4413         }
4414
4415         set_owner = VALID_STAT(*psbuf) ? psbuf->st_uid : (uid_t)SMB_UID_NO_CHANGE;
4416         set_grp = VALID_STAT(*psbuf) ? psbuf->st_gid : (gid_t)SMB_GID_NO_CHANGE;
4417
4418         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
4419            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
4420                 *p_size=IVAL(pdata,0); /* first 8 Bytes are size */
4421 #ifdef LARGE_SMB_OFF_T
4422                 *p_size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
4423 #else /* LARGE_SMB_OFF_T */
4424                 if (IVAL(pdata,4) != 0) {
4425                         /* more than 32 bits? */
4426                         return NT_STATUS_INVALID_PARAMETER;
4427                 }
4428 #endif /* LARGE_SMB_OFF_T */
4429         }
4430
4431         pdata+=24;          /* ctime & st_blocks are not changed */
4432         p_tvs->actime = convert_timespec_to_time_t(interpret_long_date(pdata)); /* access_time */
4433         p_tvs->modtime = convert_timespec_to_time_t(interpret_long_date(pdata+8)); /* modification_time */
4434         pdata+=16;
4435         set_owner = (uid_t)IVAL(pdata,0);
4436         pdata += 8;
4437         set_grp = (gid_t)IVAL(pdata,0);
4438         pdata += 8;
4439         raw_unixmode = IVAL(pdata,28);
4440         *p_unixmode = unix_perms_from_wire(conn, psbuf, raw_unixmode);
4441         *p_dosmode = 0; /* Ensure dos mode change doesn't override this. */
4442
4443         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
4444 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
4445                 fname, (double)*p_size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
4446
4447         if (!VALID_STAT(*psbuf)) {
4448
4449                 /*
4450                  * The only valid use of this is to create character and block
4451                  * devices, and named pipes. This is deprecated (IMHO) and 
4452                  * a new info level should be used for mknod. JRA.
4453                  */
4454
4455                 uint32 file_type = IVAL(pdata,0);
4456 #if defined(HAVE_MAKEDEV)
4457                 uint32 dev_major = IVAL(pdata,4);
4458                 uint32 dev_minor = IVAL(pdata,12);
4459 #endif
4460
4461                 SMB_DEV_T dev = (SMB_DEV_T)0;
4462
4463                 if (raw_unixmode == SMB_MODE_NO_CHANGE) {
4464                         return NT_STATUS_INVALID_PARAMETER;
4465                 }
4466
4467 #if defined(HAVE_MAKEDEV)
4468                 dev = makedev(dev_major, dev_minor);
4469 #endif
4470
4471                 switch (file_type) {
4472 #if defined(S_IFIFO)
4473                         case UNIX_TYPE_FIFO:
4474                                 *p_unixmode |= S_IFIFO;
4475                                 break;
4476 #endif
4477 #if defined(S_IFSOCK)
4478                         case UNIX_TYPE_SOCKET:
4479                                 *p_unixmode |= S_IFSOCK;
4480                                 break;
4481 #endif
4482 #if defined(S_IFCHR)
4483                         case UNIX_TYPE_CHARDEV:
4484                                 *p_unixmode |= S_IFCHR;
4485                                 break;
4486 #endif
4487 #if defined(S_IFBLK)
4488                         case UNIX_TYPE_BLKDEV:
4489                                 *p_unixmode |= S_IFBLK;
4490                                 break;
4491 #endif
4492                         default:
4493                                 return NT_STATUS_INVALID_PARAMETER;
4494                 }
4495
4496                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
4497 0%o for file %s\n", (double)dev, *p_unixmode, fname ));
4498
4499                 /* Ok - do the mknod. */
4500                 if (SMB_VFS_MKNOD(conn, fname, *p_unixmode, dev) != 0) {
4501                         return map_nt_error_from_unix(errno);
4502                 }
4503
4504                 /* If any of the other "set" calls fail we
4505                  * don't want to end up with a half-constructed mknod.
4506                  */
4507
4508                 delete_on_fail = True;
4509
4510                 if (lp_inherit_perms(SNUM(conn))) {
4511                         inherit_access_acl(
4512                                 conn, parent_dirname(fname),
4513                                 fname, *p_unixmode);
4514                 }
4515
4516                 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
4517                         status = map_nt_error_from_unix(errno);
4518                         SMB_VFS_UNLINK(conn,fname);
4519                         return status;
4520                 }
4521
4522                 /* Ensure we don't try and change anything else. */
4523                 raw_unixmode = SMB_MODE_NO_CHANGE;
4524                 *p_size = get_file_size(*psbuf);
4525                 p_tvs->modtime = psbuf->st_mtime;
4526                 p_tvs->actime = psbuf->st_atime;
4527         }
4528
4529         /*
4530          * Deal with the UNIX specific mode set.
4531          */
4532
4533         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
4534                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
4535                         (unsigned int)*p_unixmode, fname ));
4536                 if (SMB_VFS_CHMOD(conn,fname,*p_unixmode) != 0) {
4537                         return map_nt_error_from_unix(errno);
4538                 }
4539         }
4540
4541         /*
4542          * Deal with the UNIX specific uid set.
4543          */
4544
4545         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
4546                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
4547                         (unsigned int)set_owner, fname ));
4548                 if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
4549                         status = map_nt_error_from_unix(errno);
4550                         if (delete_on_fail) {
4551                                 SMB_VFS_UNLINK(conn,fname);
4552                         }
4553                         return status;
4554                 }
4555         }
4556
4557         /*
4558          * Deal with the UNIX specific gid set.
4559          */
4560
4561         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
4562                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
4563                         (unsigned int)set_owner, fname ));
4564                 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
4565                         status = map_nt_error_from_unix(errno);
4566                         if (delete_on_fail) {
4567                                 SMB_VFS_UNLINK(conn,fname);
4568                         }
4569                         return status;
4570                 }
4571         }
4572         return NT_STATUS_OK;
4573 }
4574
4575 /****************************************************************************
4576  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
4577 ****************************************************************************/
4578
4579 static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
4580                                         unsigned int tran_call,
4581                                         char **pparams, int total_params, char **ppdata, int total_data,
4582                                         unsigned int max_data_bytes)
4583 {
4584         char *params = *pparams;
4585         char *pdata = *ppdata;
4586         uint16 info_level;
4587         int dosmode=0;
4588         SMB_OFF_T size=0;
4589         struct utimbuf tvs;
4590         SMB_STRUCT_STAT sbuf;
4591         pstring fname;
4592         int fd = -1;
4593         files_struct *fsp = NULL;
4594         mode_t unixmode = 0;
4595         NTSTATUS status = NT_STATUS_OK;
4596
4597         if (!params) {
4598                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4599         }
4600
4601         ZERO_STRUCT(sbuf);
4602         ZERO_STRUCT(tvs);
4603
4604         if (tran_call == TRANSACT2_SETFILEINFO) {
4605                 if (total_params < 4) {
4606                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4607                 }
4608
4609                 fsp = file_fsp(params,0);
4610                 info_level = SVAL(params,2);    
4611
4612                 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
4613                         /*
4614                          * This is actually a SETFILEINFO on a directory
4615                          * handle (returned from an NT SMB). NT5.0 seems
4616                          * to do this call. JRA.
4617                          */
4618                         pstrcpy(fname, fsp->fsp_name);
4619                         if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
4620                                 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
4621                                 return UNIXERROR(ERRDOS,ERRbadpath);
4622                         }
4623                 } else if (fsp && fsp->print_file) {
4624                         /*
4625                          * Doing a DELETE_ON_CLOSE should cancel a print job.
4626                          */
4627                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
4628                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
4629
4630                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
4631         
4632                                 SSVAL(params,0,0);
4633                                 send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
4634                                 return(-1);
4635                         } else
4636                                 return (UNIXERROR(ERRDOS,ERRbadpath));
4637             } else {
4638                         /*
4639                          * Original code - this is an open file.
4640                          */
4641                         CHECK_FSP(fsp,conn);
4642
4643                         pstrcpy(fname, fsp->fsp_name);
4644                         fd = fsp->fh->fd;
4645
4646                         if (SMB_VFS_FSTAT(fsp,fd,&sbuf) != 0) {
4647                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
4648                                 return(UNIXERROR(ERRDOS,ERRbadfid));
4649                         }
4650                 }
4651         } else {
4652                 /* set path info */
4653                 if (total_params < 7) {
4654                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4655                 }
4656
4657                 info_level = SVAL(params,0);    
4658                 srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
4659                 if (!NT_STATUS_IS_OK(status)) {
4660                         return ERROR_NT(status);
4661                 }
4662                 status = unix_convert(conn, fname, False, NULL, &sbuf);
4663                 if (!NT_STATUS_IS_OK(status)) {
4664                         return ERROR_NT(status);
4665                 }
4666
4667                 /*
4668                  * For CIFS UNIX extensions the target name may not exist.
4669                  */
4670
4671                 if(!VALID_STAT(sbuf) && !INFO_LEVEL_IS_UNIX(info_level)) {
4672                         DEBUG(3,("call_trans2setfilepathinfo: stat of %s failed (%s)\n", fname, strerror(errno)));
4673                         return UNIXERROR(ERRDOS,ERRbadpath);
4674                 }    
4675
4676                 status = check_name(conn, fname);
4677                 if (!NT_STATUS_IS_OK(status)) {
4678                         return ERROR_NT(status);
4679                 }
4680
4681         }
4682
4683         if (!CAN_WRITE(conn))
4684                 return ERROR_DOS(ERRSRV,ERRaccess);
4685
4686         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4687                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4688         }
4689
4690         if (VALID_STAT(sbuf)) {
4691                 unixmode = sbuf.st_mode;
4692         }
4693
4694         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
4695                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
4696
4697         /* Realloc the parameter size */
4698         *pparams = (char *)SMB_REALLOC(*pparams,2);
4699         if (*pparams == NULL) {
4700                 return ERROR_NT(NT_STATUS_NO_MEMORY);
4701         }
4702         params = *pparams;
4703
4704         SSVAL(params,0,0);
4705
4706         if (fsp && fsp->pending_modtime) {
4707                 /* the pending modtime overrides the current modtime */
4708                 sbuf.st_mtime = fsp->pending_modtime;
4709         }
4710
4711         size = get_file_size(sbuf);
4712         tvs.modtime = sbuf.st_mtime;
4713         tvs.actime = sbuf.st_atime;
4714         dosmode = dos_mode(conn,fname,&sbuf);
4715         unixmode = sbuf.st_mode;
4716
4717         switch (info_level) {
4718
4719                 case SMB_INFO_STANDARD:
4720                 {
4721                         status = smb_set_info_standard(pdata,
4722                                                         total_data,
4723                                                         &tvs);
4724                         if (!NT_STATUS_IS_OK(status)) {
4725                                 return ERROR_NT(status);
4726                         }
4727                         break;
4728                 }
4729
4730                 case SMB_INFO_SET_EA:
4731                 {
4732                         status = smb_info_set_ea(conn,
4733                                                 pdata,
4734                                                 total_data,
4735                                                 fsp,
4736                                                 fname);
4737                         if (!NT_STATUS_IS_OK(status)) {
4738                                 return ERROR_NT(status);
4739                         }
4740                         goto out;
4741                 }
4742
4743                 case SMB_SET_FILE_BASIC_INFO:
4744                 case SMB_FILE_BASIC_INFORMATION:
4745                 {
4746                         status = smb_set_file_basic_info(pdata,
4747                                                         total_data,
4748                                                         &tvs,
4749                                                         &dosmode);
4750                         if (!NT_STATUS_IS_OK(status)) {
4751                                 return ERROR_NT(status);
4752                         }
4753                         break;
4754                 }
4755
4756                 case SMB_FILE_ALLOCATION_INFORMATION:
4757                 case SMB_SET_FILE_ALLOCATION_INFO:
4758                 {
4759                         status = smb_set_file_allocation_info(conn,
4760                                                                 pdata,
4761                                                                 total_data,
4762                                                                 fsp,
4763                                                                 fname,
4764                                                                 &sbuf,
4765                                                                 &size);
4766                         if (!NT_STATUS_IS_OK(status)) {
4767                                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4768                                         /* We have re-scheduled this call. */
4769                                         return -1;
4770                                 }
4771                                 return ERROR_NT(status);
4772                         }
4773                         break;
4774                 }
4775
4776                 case SMB_FILE_END_OF_FILE_INFORMATION:
4777                 case SMB_SET_FILE_END_OF_FILE_INFO:
4778                 {
4779                         status = smb_set_file_end_of_file_info(conn,
4780                                                                 pdata,
4781                                                                 total_data,
4782                                                                 fname,
4783                                                                 &size);
4784                         if (!NT_STATUS_IS_OK(status)) {
4785                                 return ERROR_NT(status);
4786                         }
4787                         break;
4788                 }
4789
4790                 case SMB_FILE_DISPOSITION_INFORMATION:
4791                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
4792                 {
4793 #if 0
4794                         /* JRA - We used to just ignore this on a path ? 
4795                          * Shouldn't this be invalid level on a pathname
4796                          * based call ?
4797                          */
4798                         if (tran_call != TRANSACT2_SETFILEINFO) {
4799                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4800                         }
4801 #endif
4802                         status = smb_set_file_disposition_info(conn,
4803                                                 pdata,
4804                                                 total_data,
4805                                                 fsp,
4806                                                 dosmode);
4807                         if (!NT_STATUS_IS_OK(status)) {
4808                                 return ERROR_NT(status);
4809                         }
4810                         goto out;
4811                 }
4812
4813                 case SMB_FILE_POSITION_INFORMATION:
4814                 {
4815                         status = smb_file_position_information(conn,
4816                                                 pdata,
4817                                                 total_data,
4818                                                 fsp);
4819                         if (!NT_STATUS_IS_OK(status)) {
4820                                 return ERROR_NT(status);
4821                         }
4822                         goto out;
4823                 }
4824
4825                 /* From tridge Samba4 : 
4826                  * MODE_INFORMATION in setfileinfo (I have no
4827                  * idea what "mode information" on a file is - it takes a value of 0,
4828                  * 2, 4 or 6. What could it be?).
4829                  */
4830
4831                 case SMB_FILE_MODE_INFORMATION:
4832                 {
4833                         status = smb_file_mode_information(conn,
4834                                                 pdata,
4835                                                 total_data);
4836                         if (!NT_STATUS_IS_OK(status)) {
4837                                 return ERROR_NT(status);
4838                         }
4839                         goto out;
4840                 }
4841
4842                 /*
4843                  * CIFS UNIX extensions.
4844                  */
4845
4846                 case SMB_SET_FILE_UNIX_BASIC:
4847                 {
4848                         if (tran_call == TRANSACT2_SETFILEINFO) {
4849                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4850                         }
4851
4852                         status = smb_set_file_unix_basic(conn,
4853                                                         pdata,
4854                                                         total_data,
4855                                                         fsp,
4856                                                         fname,
4857                                                         &sbuf,
4858                                                         &size,
4859                                                         &tvs,
4860                                                         &unixmode,
4861                                                         &dosmode);
4862                         if (!NT_STATUS_IS_OK(status)) {
4863                                 return ERROR_NT(status);
4864                         }
4865                         break;
4866                 }
4867
4868                 case SMB_SET_FILE_UNIX_LINK:
4869                 {
4870                         if (tran_call != TRANSACT2_SETPATHINFO) {
4871                                 /* We must have a pathname for this. */
4872                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4873                         }
4874                         status = smb_set_file_unix_link(conn,
4875                                                 inbuf,
4876                                                 pdata,
4877                                                 total_data,
4878                                                 fname);
4879                         if (!NT_STATUS_IS_OK(status)) {
4880                                 return ERROR_NT(status);
4881                         }
4882                         goto out;
4883                 }
4884
4885                 case SMB_SET_FILE_UNIX_HLINK:
4886                 {
4887                         if (tran_call != TRANSACT2_SETPATHINFO) {
4888                                 /* We must have a pathname for this. */
4889                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4890                         }
4891                         status = smb_set_file_unix_hlink(conn,
4892                                                 inbuf,
4893                                                 pdata,
4894                                                 total_data,
4895                                                 fname);
4896                         if (!NT_STATUS_IS_OK(status)) {
4897                                 return ERROR_NT(status);
4898                         }
4899                         goto out;
4900                 }
4901
4902                 case SMB_FILE_RENAME_INFORMATION:
4903                 {
4904                         status = smb_file_rename_information(conn,
4905                                                         inbuf,
4906                                                         outbuf,
4907                                                         pdata,
4908                                                         total_data,
4909                                                         fsp,
4910                                                         fname);
4911                         if (!NT_STATUS_IS_OK(status)) {
4912                                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
4913                                         /* We have re-scheduled this call. */
4914                                         return -1;
4915                                 }
4916                                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4917                                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
4918                                 }
4919                                 return ERROR_NT(status);
4920                         }
4921                         goto out;
4922                 }
4923
4924 #if defined(HAVE_POSIX_ACLS)
4925                 case SMB_SET_POSIX_ACL:
4926                 {
4927                         status = smb_set_posix_acl(conn,
4928                                                 pdata,
4929                                                 total_data,
4930                                                 fsp,
4931                                                 &sbuf,
4932                                                 fname);
4933                         if (!NT_STATUS_IS_OK(status)) {
4934                                 return ERROR_NT(status);
4935                         }
4936                         goto out;
4937                 }
4938 #endif
4939
4940                 case SMB_SET_POSIX_LOCK:
4941                 {
4942                         status = smb_set_posix_lock(conn,
4943                                                 inbuf,
4944                                                 length,
4945                                                 pdata,
4946                                                 total_data,
4947                                                 fsp);
4948                         if (!NT_STATUS_IS_OK(status)) {
4949                                 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
4950                                         /* We have re-scheduled this call. */
4951                                         return -1;
4952                                 }
4953                                 return ERROR_NT(status);
4954                         }
4955                         goto out;
4956                 }
4957
4958                 default:
4959                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4960         }
4961
4962         /* get some defaults (no modifications) if any info is zero or -1. */
4963         if (null_mtime(tvs.actime)) {
4964                 tvs.actime = sbuf.st_atime;
4965         }
4966
4967         if (null_mtime(tvs.modtime)) {
4968                 tvs.modtime = sbuf.st_mtime;
4969         }
4970
4971         DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
4972         DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
4973         DEBUG(6,("size: %.0f ", (double)size));
4974
4975         if (dosmode) {
4976                 if (S_ISDIR(sbuf.st_mode)) {
4977                         dosmode |= aDIR;
4978                 } else {
4979                         dosmode &= ~aDIR;
4980                 }
4981         }
4982
4983         DEBUG(6,("dosmode: %x\n"  , dosmode));
4984
4985         if(!((info_level == SMB_SET_FILE_END_OF_FILE_INFO) ||
4986                 (info_level == SMB_SET_FILE_ALLOCATION_INFO) ||
4987                 (info_level == SMB_FILE_ALLOCATION_INFORMATION) ||
4988                 (info_level == SMB_FILE_END_OF_FILE_INFORMATION))) {
4989
4990                 /*
4991                  * Only do this test if we are not explicitly
4992                  * changing the size of a file.
4993                  */
4994                 if (!size)
4995                         size = get_file_size(sbuf);
4996         }
4997
4998         /*
4999          * Try and set the times, size and mode of this file -
5000          * if they are different from the current values
5001          */
5002
5003         /* check the mode isn't different, before changing it */
5004         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
5005
5006                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting dos mode %x\n", fname, dosmode ));
5007
5008                 if(file_set_dosmode(conn, fname, dosmode, &sbuf, False)) {
5009                         DEBUG(2,("file_set_dosmode of %s failed (%s)\n", fname, strerror(errno)));
5010                         return(UNIXERROR(ERRDOS,ERRnoaccess));
5011                 }
5012         }
5013
5014         /* Now the size. */
5015         if (size != get_file_size(sbuf)) {
5016
5017                 int ret;
5018
5019                 DEBUG(10,("call_trans2setfilepathinfo: file %s : setting new size to %.0f\n",
5020                         fname, (double)size ));
5021
5022                 if (fd == -1) {
5023                         files_struct *new_fsp = NULL;
5024
5025                         status = open_file_ntcreate(conn, fname, &sbuf,
5026                                                 FILE_WRITE_DATA,
5027                                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5028                                                 FILE_OPEN,
5029                                                 0,
5030                                                 FILE_ATTRIBUTE_NORMAL,
5031                                                 FORCE_OPLOCK_BREAK_TO_NONE,
5032                                                 NULL, &new_fsp);
5033         
5034                         if (!NT_STATUS_IS_OK(status)) {
5035                                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
5036                                         /* We have re-scheduled this call. */
5037                                         return -1;
5038                                 }
5039                                 return(UNIXERROR(ERRDOS,ERRnoaccess));
5040                         }
5041                         ret = vfs_set_filelen(new_fsp, size);
5042                         close_file(new_fsp,NORMAL_CLOSE);
5043                 } else {
5044                         ret = vfs_set_filelen(fsp, size);
5045                 }
5046
5047                 if (ret == -1) {
5048                         return (UNIXERROR(ERRHRD,ERRdiskfull));
5049                 }
5050         }
5051
5052         /*
5053          * Finally the times.
5054          */
5055         if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
5056                 if(fsp != NULL) {
5057                         /*
5058                          * This was a setfileinfo on an open file.
5059                          * NT does this a lot. We also need to 
5060                          * set the time here, as it can be read by 
5061                          * FindFirst/FindNext and with the patch for bug #2045
5062                          * in smbd/fileio.c it ensures that this timestamp is
5063                          * kept sticky even after a write. We save the request
5064                          * away and will set it on file close and after a write. JRA.
5065                          */
5066
5067                         if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) {
5068                                 DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
5069                                 fsp_set_pending_modtime(fsp, tvs.modtime);
5070                         }
5071
5072                 }
5073                 DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
5074
5075                 if(file_utime(conn, fname, &tvs)!=0) {
5076                         return(UNIXERROR(ERRDOS,ERRnoaccess));
5077                 }
5078         }
5079
5080   out:
5081
5082         SSVAL(params,0,0);
5083         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5084   
5085         return -1;
5086 }
5087
5088 /****************************************************************************
5089  Reply to a TRANS2_MKDIR (make directory with extended attributes).
5090 ****************************************************************************/
5091
5092 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5093                                         char **pparams, int total_params, char **ppdata, int total_data,
5094                                         unsigned int max_data_bytes)
5095 {
5096         char *params = *pparams;
5097         char *pdata = *ppdata;
5098         pstring directory;
5099         SMB_STRUCT_STAT sbuf;
5100         NTSTATUS status = NT_STATUS_OK;
5101         struct ea_list *ea_list = NULL;
5102
5103         if (!CAN_WRITE(conn))
5104                 return ERROR_DOS(ERRSRV,ERRaccess);
5105
5106         if (total_params < 5) {
5107                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5108         }
5109
5110         srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
5111         if (!NT_STATUS_IS_OK(status)) {
5112                 return ERROR_NT(status);
5113         }
5114
5115         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
5116
5117         status = unix_convert(conn, directory, False, NULL, &sbuf);
5118         if (!NT_STATUS_IS_OK(status)) {
5119                 return ERROR_NT(status);
5120         }
5121
5122         /* Any data in this call is an EA list. */
5123         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
5124                 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
5125         }
5126
5127         /*
5128          * OS/2 workplace shell seems to send SET_EA requests of "null"
5129          * length (4 bytes containing IVAL 4).
5130          * They seem to have no effect. Bug #3212. JRA.
5131          */
5132
5133         if (total_data != 4) {
5134                 if (total_data < 10) {
5135                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5136                 }
5137
5138                 if (IVAL(pdata,0) > total_data) {
5139                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
5140                                 IVAL(pdata,0), (unsigned int)total_data));
5141                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5142                 }
5143
5144                 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
5145                                        total_data - 4);
5146                 if (!ea_list) {
5147                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5148                 }
5149         } else if (IVAL(pdata,0) != 4) {
5150                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5151         }
5152
5153         status = check_name(conn, directory);
5154         if (!NT_STATUS_IS_OK(status)) {
5155                 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
5156                 return ERROR_NT(status);
5157         }
5158
5159         status = create_directory(conn, directory);
5160
5161         if (!NT_STATUS_IS_OK(status)) {
5162                 return ERROR_NT(status);
5163         }
5164   
5165         /* Try and set any given EA. */
5166         if (ea_list) {
5167                 status = set_ea(conn, NULL, directory, ea_list);
5168                 if (!NT_STATUS_IS_OK(status)) {
5169                         return ERROR_NT(status);
5170                 }
5171         }
5172
5173         /* Realloc the parameter and data sizes */
5174         *pparams = (char *)SMB_REALLOC(*pparams,2);
5175         if(*pparams == NULL) {
5176                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5177         }
5178         params = *pparams;
5179
5180         SSVAL(params,0,0);
5181
5182         send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5183   
5184         return(-1);
5185 }
5186
5187 /****************************************************************************
5188  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
5189  We don't actually do this - we just send a null response.
5190 ****************************************************************************/
5191
5192 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5193                                         char **pparams, int total_params, char **ppdata, int total_data,
5194                                         unsigned int max_data_bytes)
5195 {
5196         static uint16 fnf_handle = 257;
5197         char *params = *pparams;
5198         uint16 info_level;
5199
5200         if (total_params < 6) {
5201                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5202         }
5203
5204         info_level = SVAL(params,4);
5205         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
5206
5207         switch (info_level) {
5208                 case 1:
5209                 case 2:
5210                         break;
5211                 default:
5212                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5213         }
5214
5215         /* Realloc the parameter and data sizes */
5216         *pparams = (char *)SMB_REALLOC(*pparams,6);
5217         if (*pparams == NULL) {
5218                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5219         }
5220         params = *pparams;
5221
5222         SSVAL(params,0,fnf_handle);
5223         SSVAL(params,2,0); /* No changes */
5224         SSVAL(params,4,0); /* No EA errors */
5225
5226         fnf_handle++;
5227
5228         if(fnf_handle == 0)
5229                 fnf_handle = 257;
5230
5231         send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
5232   
5233         return(-1);
5234 }
5235
5236 /****************************************************************************
5237  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
5238  changes). Currently this does nothing.
5239 ****************************************************************************/
5240
5241 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
5242                                         char **pparams, int total_params, char **ppdata, int total_data,
5243                                         unsigned int max_data_bytes)
5244 {
5245         char *params = *pparams;
5246
5247         DEBUG(3,("call_trans2findnotifynext\n"));
5248
5249         /* Realloc the parameter and data sizes */
5250         *pparams = (char *)SMB_REALLOC(*pparams,4);
5251         if (*pparams == NULL) {
5252                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5253         }
5254         params = *pparams;
5255
5256         SSVAL(params,0,0); /* No changes */
5257         SSVAL(params,2,0); /* No EA errors */
5258
5259         send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
5260   
5261         return(-1);
5262 }
5263
5264 /****************************************************************************
5265  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
5266 ****************************************************************************/
5267
5268 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
5269                                         char **pparams, int total_params, char **ppdata, int total_data,
5270                                         unsigned int max_data_bytes)
5271 {
5272         char *params = *pparams;
5273         pstring pathname;
5274         int reply_size = 0;
5275         int max_referral_level;
5276
5277         DEBUG(10,("call_trans2getdfsreferral\n"));
5278
5279         if (total_params < 3) {
5280                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5281         }
5282
5283         max_referral_level = SVAL(params,0);
5284
5285         if(!lp_host_msdfs())
5286                 return ERROR_DOS(ERRDOS,ERRbadfunc);
5287
5288         srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
5289         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata)) < 0)
5290                 return UNIXERROR(ERRDOS,ERRbadfile);
5291     
5292         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
5293         send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
5294
5295         return(-1);
5296 }
5297
5298 #define LMCAT_SPL       0x53
5299 #define LMFUNC_GETJOBID 0x60
5300
5301 /****************************************************************************
5302  Reply to a TRANS2_IOCTL - used for OS/2 printing.
5303 ****************************************************************************/
5304
5305 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
5306                                         char **pparams, int total_params, char **ppdata, int total_data,
5307                                         unsigned int max_data_bytes)
5308 {
5309         char *pdata = *ppdata;
5310         files_struct *fsp = file_fsp(inbuf,smb_vwv15);
5311
5312         /* check for an invalid fid before proceeding */
5313         
5314         if (!fsp)                                
5315                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
5316
5317         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5318                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5319                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
5320                 if (*ppdata == NULL) {
5321                         return ERROR_NT(NT_STATUS_NO_MEMORY);
5322                 }
5323                 pdata = *ppdata;
5324
5325                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
5326                         CAN ACCEPT THIS IN UNICODE. JRA. */
5327
5328                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
5329                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
5330                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
5331                 send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
5332                 return(-1);
5333         } else {
5334                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
5335                 return ERROR_DOS(ERRSRV,ERRerror);
5336         }
5337 }
5338
5339 /****************************************************************************
5340  Reply to a SMBfindclose (stop trans2 directory search).
5341 ****************************************************************************/
5342
5343 int reply_findclose(connection_struct *conn,
5344                     char *inbuf,char *outbuf,int length,int bufsize)
5345 {
5346         int outsize = 0;
5347         int dptr_num=SVALS(inbuf,smb_vwv0);
5348         START_PROFILE(SMBfindclose);
5349
5350         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
5351
5352         dptr_close(&dptr_num);
5353
5354         outsize = set_message(outbuf,0,0,False);
5355
5356         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
5357
5358         END_PROFILE(SMBfindclose);
5359         return(outsize);
5360 }
5361
5362 /****************************************************************************
5363  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
5364 ****************************************************************************/
5365
5366 int reply_findnclose(connection_struct *conn, 
5367                      char *inbuf,char *outbuf,int length,int bufsize)
5368 {
5369         int outsize = 0;
5370         int dptr_num= -1;
5371         START_PROFILE(SMBfindnclose);
5372         
5373         dptr_num = SVAL(inbuf,smb_vwv0);
5374
5375         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
5376
5377         /* We never give out valid handles for a 
5378            findnotifyfirst - so any dptr_num is ok here. 
5379            Just ignore it. */
5380
5381         outsize = set_message(outbuf,0,0,False);
5382
5383         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
5384
5385         END_PROFILE(SMBfindnclose);
5386         return(outsize);
5387 }
5388
5389 int handle_trans2(connection_struct *conn,
5390                   struct trans_state *state,
5391                   char *inbuf, char *outbuf, int size, int bufsize)
5392 {
5393         int outsize;
5394
5395         if (Protocol >= PROTOCOL_NT1) {
5396                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
5397         }
5398
5399         /* Now we must call the relevant TRANS2 function */
5400         switch(state->call)  {
5401         case TRANSACT2_OPEN:
5402         {
5403                 START_PROFILE(Trans2_open);
5404                 outsize = call_trans2open(
5405                         conn, inbuf, outbuf, bufsize, 
5406                         &state->param, state->total_param,
5407                         &state->data, state->total_data,
5408                         state->max_data_return);
5409                 END_PROFILE(Trans2_open);
5410                 break;
5411         }
5412
5413         case TRANSACT2_FINDFIRST:
5414         {
5415                 START_PROFILE(Trans2_findfirst);
5416                 outsize = call_trans2findfirst(
5417                         conn, inbuf, outbuf, bufsize,
5418                         &state->param, state->total_param,
5419                         &state->data, state->total_data,
5420                         state->max_data_return);
5421                 END_PROFILE(Trans2_findfirst);
5422                 break;
5423         }
5424
5425         case TRANSACT2_FINDNEXT:
5426         {
5427                 START_PROFILE(Trans2_findnext);
5428                 outsize = call_trans2findnext(
5429                         conn, inbuf, outbuf, size, bufsize, 
5430                         &state->param, state->total_param,
5431                         &state->data, state->total_data,
5432                         state->max_data_return);
5433                 END_PROFILE(Trans2_findnext);
5434                 break;
5435         }
5436
5437         case TRANSACT2_QFSINFO:
5438         {
5439                 START_PROFILE(Trans2_qfsinfo);
5440                 outsize = call_trans2qfsinfo(
5441                         conn, inbuf, outbuf, size, bufsize,
5442                         &state->param, state->total_param,
5443                         &state->data, state->total_data,
5444                         state->max_data_return);
5445                 END_PROFILE(Trans2_qfsinfo);
5446             break;
5447         }
5448
5449         case TRANSACT2_SETFSINFO:
5450         {
5451                 START_PROFILE(Trans2_setfsinfo);
5452                 outsize = call_trans2setfsinfo(
5453                         conn, inbuf, outbuf, size, bufsize, 
5454                         &state->param, state->total_param,
5455                         &state->data, state->total_data,
5456                         state->max_data_return);
5457                 END_PROFILE(Trans2_setfsinfo);
5458                 break;
5459         }
5460
5461         case TRANSACT2_QPATHINFO:
5462         case TRANSACT2_QFILEINFO:
5463         {
5464                 START_PROFILE(Trans2_qpathinfo);
5465                 outsize = call_trans2qfilepathinfo(
5466                         conn, inbuf, outbuf, size, bufsize, state->call,
5467                         &state->param, state->total_param,
5468                         &state->data, state->total_data,
5469                         state->max_data_return);
5470                 END_PROFILE(Trans2_qpathinfo);
5471                 break;
5472         }
5473
5474         case TRANSACT2_SETPATHINFO:
5475         case TRANSACT2_SETFILEINFO:
5476         {
5477                 START_PROFILE(Trans2_setpathinfo);
5478                 outsize = call_trans2setfilepathinfo(
5479                         conn, inbuf, outbuf, size, bufsize, state->call,
5480                         &state->param, state->total_param,
5481                         &state->data, state->total_data,
5482                         state->max_data_return);
5483                 END_PROFILE(Trans2_setpathinfo);
5484                 break;
5485         }
5486
5487         case TRANSACT2_FINDNOTIFYFIRST:
5488         {
5489                 START_PROFILE(Trans2_findnotifyfirst);
5490                 outsize = call_trans2findnotifyfirst(
5491                         conn, inbuf, outbuf, size, bufsize, 
5492                         &state->param, state->total_param,
5493                         &state->data, state->total_data,
5494                         state->max_data_return);
5495                 END_PROFILE(Trans2_findnotifyfirst);
5496                 break;
5497         }
5498
5499         case TRANSACT2_FINDNOTIFYNEXT:
5500         {
5501                 START_PROFILE(Trans2_findnotifynext);
5502                 outsize = call_trans2findnotifynext(
5503                         conn, inbuf, outbuf, size, bufsize, 
5504                         &state->param, state->total_param,
5505                         &state->data, state->total_data,
5506                         state->max_data_return);
5507                 END_PROFILE(Trans2_findnotifynext);
5508                 break;
5509         }
5510
5511         case TRANSACT2_MKDIR:
5512         {
5513                 START_PROFILE(Trans2_mkdir);
5514                 outsize = call_trans2mkdir(
5515                         conn, inbuf, outbuf, size, bufsize,
5516                         &state->param, state->total_param,
5517                         &state->data, state->total_data,
5518                         state->max_data_return);
5519                 END_PROFILE(Trans2_mkdir);
5520                 break;
5521         }
5522
5523         case TRANSACT2_GET_DFS_REFERRAL:
5524         {
5525                 START_PROFILE(Trans2_get_dfs_referral);
5526                 outsize = call_trans2getdfsreferral(
5527                         conn, inbuf, outbuf, size, bufsize,
5528                         &state->param, state->total_param,
5529                         &state->data, state->total_data,
5530                         state->max_data_return);
5531                 END_PROFILE(Trans2_get_dfs_referral);
5532                 break;
5533         }
5534
5535         case TRANSACT2_IOCTL:
5536         {
5537                 START_PROFILE(Trans2_ioctl);
5538                 outsize = call_trans2ioctl(
5539                         conn, inbuf, outbuf, size, bufsize,
5540                         &state->param, state->total_param,
5541                         &state->data, state->total_data,
5542                         state->max_data_return);
5543                 END_PROFILE(Trans2_ioctl);
5544                 break;
5545         }
5546
5547         default:
5548                 /* Error in request */
5549                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
5550                 outsize = ERROR_DOS(ERRSRV,ERRerror);
5551         }
5552
5553         return outsize;
5554 }
5555
5556 /****************************************************************************
5557  Reply to a SMBtrans2.
5558  ****************************************************************************/
5559
5560 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
5561                  int size, int bufsize)
5562 {
5563         int outsize = 0;
5564         unsigned int dsoff = SVAL(inbuf, smb_dsoff);
5565         unsigned int dscnt = SVAL(inbuf, smb_dscnt);
5566         unsigned int psoff = SVAL(inbuf, smb_psoff);
5567         unsigned int pscnt = SVAL(inbuf, smb_pscnt);
5568         unsigned int tran_call = SVAL(inbuf, smb_setup0);
5569         struct trans_state *state;
5570         NTSTATUS result;
5571
5572         START_PROFILE(SMBtrans2);
5573
5574         result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
5575         if (!NT_STATUS_IS_OK(result)) {
5576                 DEBUG(2, ("Got invalid trans2 request: %s\n",
5577                           nt_errstr(result)));
5578                 END_PROFILE(SMBtrans2);
5579                 return ERROR_NT(result);
5580         }
5581
5582         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
5583             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
5584                 END_PROFILE(SMBtrans2);
5585                 return ERROR_DOS(ERRSRV,ERRaccess);
5586         }
5587
5588         if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
5589                 DEBUG(0, ("talloc failed\n"));
5590                 END_PROFILE(SMBtrans2);
5591                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5592         }
5593
5594         state->cmd = SMBtrans2;
5595
5596         state->mid = SVAL(inbuf, smb_mid);
5597         state->vuid = SVAL(inbuf, smb_uid);
5598         state->setup_count = SVAL(inbuf, smb_suwcnt);
5599         state->setup = NULL;
5600         state->total_param = SVAL(inbuf, smb_tpscnt);
5601         state->param = NULL;
5602         state->total_data =  SVAL(inbuf, smb_tdscnt);
5603         state->data = NULL;
5604         state->max_param_return = SVAL(inbuf, smb_mprcnt);
5605         state->max_data_return  = SVAL(inbuf, smb_mdrcnt);
5606         state->max_setup_return = SVAL(inbuf, smb_msrcnt);
5607         state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
5608         state->one_way = BITSETW(inbuf+smb_vwv5,1);
5609
5610         state->call = tran_call;
5611
5612         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
5613            is so as a sanity check */
5614         if (state->setup_count != 1) {
5615                 /*
5616                  * Need to have rc=0 for ioctl to get job id for OS/2.
5617                  *  Network printing will fail if function is not successful.
5618                  *  Similar function in reply.c will be used if protocol
5619                  *  is LANMAN1.0 instead of LM1.2X002.
5620                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
5621                  *  outbuf doesn't have to be set(only job id is used).
5622                  */
5623                 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
5624                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
5625                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
5626                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
5627                 } else {
5628                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
5629                         DEBUG(2,("Transaction is %d\n",tran_call));
5630                         TALLOC_FREE(state);
5631                         END_PROFILE(SMBtrans2);
5632                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5633                 }
5634         }
5635
5636         if ((dscnt > state->total_data) || (pscnt > state->total_param))
5637                 goto bad_param;
5638
5639         if (state->total_data) {
5640                 /* Can't use talloc here, the core routines do realloc on the
5641                  * params and data. */
5642                 state->data = (char *)SMB_MALLOC(state->total_data);
5643                 if (state->data == NULL) {
5644                         DEBUG(0,("reply_trans2: data malloc fail for %u "
5645                                  "bytes !\n", (unsigned int)state->total_data));
5646                         TALLOC_FREE(state);
5647                         END_PROFILE(SMBtrans2);
5648                         return(ERROR_DOS(ERRDOS,ERRnomem));
5649                 }
5650                 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
5651                         goto bad_param;
5652                 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
5653                     (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
5654                         goto bad_param;
5655
5656                 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
5657         }
5658
5659         if (state->total_param) {
5660                 /* Can't use talloc here, the core routines do realloc on the
5661                  * params and data. */
5662                 state->param = (char *)SMB_MALLOC(state->total_param);
5663                 if (state->param == NULL) {
5664                         DEBUG(0,("reply_trans: param malloc fail for %u "
5665                                  "bytes !\n", (unsigned int)state->total_param));
5666                         SAFE_FREE(state->data);
5667                         TALLOC_FREE(state);
5668                         END_PROFILE(SMBtrans2);
5669                         return(ERROR_DOS(ERRDOS,ERRnomem));
5670                 } 
5671                 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
5672                         goto bad_param;
5673                 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
5674                     (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
5675                         goto bad_param;
5676
5677                 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
5678         }
5679
5680         state->received_data  = dscnt;
5681         state->received_param = pscnt;
5682
5683         if ((state->received_param == state->total_param) &&
5684             (state->received_data == state->total_data)) {
5685
5686                 outsize = handle_trans2(conn, state, inbuf, outbuf,
5687                                         size, bufsize);
5688                 SAFE_FREE(state->data);
5689                 SAFE_FREE(state->param);
5690                 TALLOC_FREE(state);
5691                 END_PROFILE(SMBtrans2);
5692                 return outsize;
5693         }
5694
5695         DLIST_ADD(conn->pending_trans, state);
5696
5697         /* We need to send an interim response then receive the rest
5698            of the parameter/data bytes */
5699         outsize = set_message(outbuf,0,0,False);
5700         show_msg(outbuf);
5701         END_PROFILE(SMBtrans2);
5702         return outsize;
5703
5704   bad_param:
5705
5706         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
5707         SAFE_FREE(state->data);
5708         SAFE_FREE(state->param);
5709         TALLOC_FREE(state);
5710         END_PROFILE(SMBtrans2);
5711         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5712 }
5713
5714
5715 /****************************************************************************
5716  Reply to a SMBtranss2
5717  ****************************************************************************/
5718
5719 int reply_transs2(connection_struct *conn,
5720                   char *inbuf,char *outbuf,int size,int bufsize)
5721 {
5722         int outsize = 0;
5723         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
5724         struct trans_state *state;
5725
5726         START_PROFILE(SMBtranss2);
5727
5728         show_msg(inbuf);
5729
5730         for (state = conn->pending_trans; state != NULL;
5731              state = state->next) {
5732                 if (state->mid == SVAL(inbuf,smb_mid)) {
5733                         break;
5734                 }
5735         }
5736
5737         if ((state == NULL) || (state->cmd != SMBtrans2)) {
5738                 END_PROFILE(SMBtranss2);
5739                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5740         }
5741
5742         /* Revise state->total_param and state->total_data in case they have
5743            changed downwards */
5744
5745         if (SVAL(inbuf, smb_tpscnt) < state->total_param)
5746                 state->total_param = SVAL(inbuf, smb_tpscnt);
5747         if (SVAL(inbuf, smb_tdscnt) < state->total_data)
5748                 state->total_data = SVAL(inbuf, smb_tdscnt);
5749
5750         pcnt = SVAL(inbuf, smb_spscnt);
5751         poff = SVAL(inbuf, smb_spsoff);
5752         pdisp = SVAL(inbuf, smb_spsdisp);
5753
5754         dcnt = SVAL(inbuf, smb_sdscnt);
5755         doff = SVAL(inbuf, smb_sdsoff);
5756         ddisp = SVAL(inbuf, smb_sdsdisp);
5757
5758         state->received_param += pcnt;
5759         state->received_data += dcnt;
5760                 
5761         if ((state->received_data > state->total_data) ||
5762             (state->received_param > state->total_param))
5763                 goto bad_param;
5764
5765         if (pcnt) {
5766                 if (pdisp+pcnt > state->total_param)
5767                         goto bad_param;
5768                 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
5769                         goto bad_param;
5770                 if (pdisp > state->total_param)
5771                         goto bad_param;
5772                 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
5773                     (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
5774                         goto bad_param;
5775                 if (state->param + pdisp < state->param)
5776                         goto bad_param;
5777
5778                 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
5779                        pcnt);
5780         }
5781
5782         if (dcnt) {
5783                 if (ddisp+dcnt > state->total_data)
5784                         goto bad_param;
5785                 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
5786                         goto bad_param;
5787                 if (ddisp > state->total_data)
5788                         goto bad_param;
5789                 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
5790                     (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
5791                         goto bad_param;
5792                 if (state->data + ddisp < state->data)
5793                         goto bad_param;
5794
5795                 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
5796                        dcnt);      
5797         }
5798
5799         if ((state->received_param < state->total_param) ||
5800             (state->received_data < state->total_data)) {
5801                 END_PROFILE(SMBtranss2);
5802                 return -1;
5803         }
5804
5805         /* construct_reply_common has done us the favor to pre-fill the
5806          * command field with SMBtranss2 which is wrong :-)
5807          */
5808         SCVAL(outbuf,smb_com,SMBtrans2);
5809
5810         outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
5811
5812         DLIST_REMOVE(conn->pending_trans, state);
5813         SAFE_FREE(state->data);
5814         SAFE_FREE(state->param);
5815         TALLOC_FREE(state);
5816
5817         if (outsize == 0) {
5818                 END_PROFILE(SMBtranss2);
5819                 return(ERROR_DOS(ERRSRV,ERRnosupport));
5820         }
5821         
5822         END_PROFILE(SMBtranss2);
5823         return(outsize);
5824
5825   bad_param:
5826
5827         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
5828         DLIST_REMOVE(conn->pending_trans, state);
5829         SAFE_FREE(state->data);
5830         SAFE_FREE(state->param);
5831         TALLOC_FREE(state);
5832         END_PROFILE(SMBtranss2);
5833         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5834 }