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