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