r24120: add a file_id_create() hook into the VFS layer
[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 /****************************************************************************
94  Refuse to allow clients to overwrite our private xattrs.
95 ****************************************************************************/
96
97 static BOOL samba_private_attr_name(const char *unix_ea_name)
98 {
99         static const char *prohibited_ea_names[] = {
100                 SAMBA_POSIX_INHERITANCE_EA_NAME,
101                 SAMBA_XATTR_DOS_ATTRIB,
102                 NULL
103         };
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                 srvstr_pull(inbuf, SVAL(inbuf,smb_flg2),
2028                                 resume_name, params+12,
2029                                 sizeof(resume_name), total_params - 12,
2030                                 STR_TERMINATE);
2031
2032                 if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2033                         return ERROR_NT(ntstatus);
2034                 }
2035         }
2036
2037         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2038 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2039 resume_key = %d resume name = %s continue=%d level = %d\n",
2040                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
2041                 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2042
2043         if (!maxentries) {
2044                 /* W2K3 seems to treat zero as 1. */
2045                 maxentries = 1;
2046         }
2047
2048         switch (info_level) {
2049                 case SMB_FIND_INFO_STANDARD:
2050                 case SMB_FIND_EA_SIZE:
2051                 case SMB_FIND_EA_LIST:
2052                 case SMB_FIND_FILE_DIRECTORY_INFO:
2053                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2054                 case SMB_FIND_FILE_NAMES_INFO:
2055                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2056                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2057                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2058                         break;
2059                 case SMB_FIND_FILE_UNIX:
2060                 case SMB_FIND_FILE_UNIX_INFO2:
2061                         if (!lp_unix_extensions()) {
2062                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2063                         }
2064                         break;
2065                 default:
2066                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2067         }
2068
2069         if (info_level == SMB_FIND_EA_LIST) {
2070                 uint32 ea_size;
2071
2072                 if (total_data < 4) {
2073                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2074                 }
2075
2076                 ea_size = IVAL(pdata,0);
2077                 if (ea_size != total_data) {
2078                         DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2079 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2080                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2081                 }
2082                                                                                                                                                      
2083                 if (!lp_ea_support(SNUM(conn))) {
2084                         return ERROR_DOS(ERRDOS,ERReasnotsupported);
2085                 }
2086                                                                                                                                                      
2087                 if ((ea_ctx = talloc_init("findnext_ea_list")) == NULL) {
2088                         return ERROR_NT(NT_STATUS_NO_MEMORY);
2089                 }
2090
2091                 /* Pull out the list of names. */
2092                 ea_list = read_ea_name_list(ea_ctx, pdata + 4, ea_size - 4);
2093                 if (!ea_list) {
2094                         talloc_destroy(ea_ctx);
2095                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2096                 }
2097         }
2098
2099         *ppdata = (char *)SMB_REALLOC(
2100                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2101         if(*ppdata == NULL) {
2102                 talloc_destroy(ea_ctx);
2103                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2104         }
2105
2106         pdata = *ppdata;
2107
2108         /* Realloc the params space */
2109         *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2110         if(*pparams == NULL ) {
2111                 talloc_destroy(ea_ctx);
2112                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2113         }
2114
2115         params = *pparams;
2116
2117         /* Check that the dptr is valid */
2118         if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2119                 talloc_destroy(ea_ctx);
2120                 return ERROR_DOS(ERRDOS,ERRnofiles);
2121         }
2122
2123         string_set(&conn->dirpath,dptr_path(dptr_num));
2124
2125         /* Get the wildcard mask from the dptr */
2126         if((p = dptr_wcard(dptr_num))== NULL) {
2127                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2128                 talloc_destroy(ea_ctx);
2129                 return ERROR_DOS(ERRDOS,ERRnofiles);
2130         }
2131
2132         pstrcpy(mask, p);
2133         pstrcpy(directory,conn->dirpath);
2134
2135         /* Get the attr mask from the dptr */
2136         dirtype = dptr_attr(dptr_num);
2137
2138         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2139                 dptr_num, mask, dirtype, 
2140                 (long)conn->dirptr,
2141                 dptr_TellDir(conn->dirptr)));
2142
2143         /* We don't need to check for VOL here as this is returned by 
2144                 a different TRANS2 call. */
2145
2146         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2147         if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2148                 dont_descend = True;
2149     
2150         p = pdata;
2151         space_remaining = max_data_bytes;
2152         out_of_space = False;
2153
2154         /* 
2155          * Seek to the correct position. We no longer use the resume key but
2156          * depend on the last file name instead.
2157          */
2158
2159         if(*resume_name && !continue_bit) {
2160                 SMB_STRUCT_STAT st;
2161
2162                 long current_pos = 0;
2163                 /*
2164                  * Remember, mangle_map is called by
2165                  * get_lanman2_dir_entry(), so the resume name
2166                  * could be mangled. Ensure we check the unmangled name.
2167                  */
2168
2169                 if (mangle_is_mangled(resume_name, conn->params)) {
2170                         mangle_check_cache(resume_name, sizeof(resume_name)-1,
2171                                            conn->params);
2172                 }
2173
2174                 /*
2175                  * Fix for NT redirector problem triggered by resume key indexes
2176                  * changing between directory scans. We now return a resume key of 0
2177                  * and instead look for the filename to continue from (also given
2178                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2179                  * findfirst/findnext (as is usual) then the directory pointer
2180                  * should already be at the correct place.
2181                  */
2182
2183                 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2184         } /* end if resume_name && !continue_bit */
2185
2186         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2187                 BOOL got_exact_match = False;
2188
2189                 /* this is a heuristic to avoid seeking the dirptr except when 
2190                         absolutely necessary. It allows for a filename of about 40 chars */
2191                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2192                         out_of_space = True;
2193                         finished = False;
2194                 } else {
2195                         finished = !get_lanman2_dir_entry(conn,
2196                                                 inbuf, outbuf,
2197                                                 mask,dirtype,info_level,
2198                                                 requires_resume_key,dont_descend,
2199                                                 &p,pdata,space_remaining, &out_of_space, &got_exact_match,
2200                                                 &last_entry_off, ea_list, ea_ctx);
2201                 }
2202
2203                 if (finished && out_of_space)
2204                         finished = False;
2205
2206                 if (!finished && !out_of_space)
2207                         numentries++;
2208
2209                 /*
2210                  * As an optimisation if we know we aren't looking
2211                  * for a wildcard name (ie. the name matches the wildcard exactly)
2212                  * then we can finish on any (first) match.
2213                  * This speeds up large directory searches. JRA.
2214                  */
2215
2216                 if(got_exact_match)
2217                         finished = True;
2218
2219                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2220         }
2221   
2222         talloc_destroy(ea_ctx);
2223
2224         /* Check if we can close the dirptr */
2225         if(close_after_request || (finished && close_if_end)) {
2226                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2227                 dptr_close(&dptr_num); /* This frees up the saved mask */
2228         }
2229
2230         /* Set up the return parameter block */
2231         SSVAL(params,0,numentries);
2232         SSVAL(params,2,finished);
2233         SSVAL(params,4,0); /* Never an EA error */
2234         SSVAL(params,6,last_entry_off);
2235
2236         send_trans2_replies(inbuf, outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
2237
2238         if ((! *directory) && dptr_path(dptr_num))
2239                 slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
2240
2241         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2242                 smb_fn_name(CVAL(inbuf,smb_com)), 
2243                 mask, directory, dirtype, numentries ) );
2244
2245         return(-1);
2246 }
2247
2248 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2249 {
2250         E_md4hash(lp_servicename(SNUM(conn)),objid);
2251         return objid;
2252 }
2253
2254 /****************************************************************************
2255  Reply to a TRANS2_QFSINFO (query filesystem info).
2256 ****************************************************************************/
2257
2258 static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2259                                         char **pparams, int total_params, char **ppdata, int total_data,
2260                                         unsigned int max_data_bytes)
2261 {
2262         char *pdata;
2263         char *params = *pparams;
2264         uint16 info_level;
2265         int data_len, len;
2266         SMB_STRUCT_STAT st;
2267         const char *vname = volume_label(SNUM(conn));
2268         int snum = SNUM(conn);
2269         char *fstype = lp_fstype(SNUM(conn));
2270         int quota_flag = 0;
2271
2272         if (total_params < 2) {
2273                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2274         }
2275
2276         info_level = SVAL(params,0);
2277
2278         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2279
2280         if(SMB_VFS_STAT(conn,".",&st)!=0) {
2281                 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2282                 return ERROR_DOS(ERRSRV,ERRinvdevice);
2283         }
2284
2285         *ppdata = (char *)SMB_REALLOC(
2286                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2287         if (*ppdata == NULL ) {
2288                 return ERROR_NT(NT_STATUS_NO_MEMORY);
2289         }
2290
2291         pdata = *ppdata;
2292         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2293
2294         switch (info_level) {
2295                 case SMB_INFO_ALLOCATION:
2296                 {
2297                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2298                         data_len = 18;
2299                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2300                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2301                         }
2302
2303                         block_size = lp_block_size(snum);
2304                         if (bsize < block_size) {
2305                                 SMB_BIG_UINT factor = block_size/bsize;
2306                                 bsize = block_size;
2307                                 dsize /= factor;
2308                                 dfree /= factor;
2309                         }
2310                         if (bsize > block_size) {
2311                                 SMB_BIG_UINT factor = bsize/block_size;
2312                                 bsize = block_size;
2313                                 dsize *= factor;
2314                                 dfree *= factor;
2315                         }
2316                         bytes_per_sector = 512;
2317                         sectors_per_unit = bsize/bytes_per_sector;
2318
2319                         DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2320 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2321                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2322
2323                         SIVAL(pdata,l1_idFileSystem,st.st_dev);
2324                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2325                         SIVAL(pdata,l1_cUnit,dsize);
2326                         SIVAL(pdata,l1_cUnitAvail,dfree);
2327                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
2328                         break;
2329                 }
2330
2331                 case SMB_INFO_VOLUME:
2332                         /* Return volume name */
2333                         /* 
2334                          * Add volume serial number - hash of a combination of
2335                          * the called hostname and the service name.
2336                          */
2337                         SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2338                         /*
2339                          * Win2k3 and previous mess this up by sending a name length
2340                          * one byte short. I believe only older clients (OS/2 Win9x) use
2341                          * this call so try fixing this by adding a terminating null to
2342                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2343                          */
2344                         len = srvstr_push(outbuf, pdata+l2_vol_szVolLabel, vname, -1, STR_NOALIGN|STR_TERMINATE);
2345                         SCVAL(pdata,l2_vol_cch,len);
2346                         data_len = l2_vol_szVolLabel + len;
2347                         DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2348                                 (unsigned)st.st_ctime, len, vname));
2349                         break;
2350
2351                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2352                 case SMB_FS_ATTRIBUTE_INFORMATION:
2353
2354
2355 #if defined(HAVE_SYS_QUOTAS)
2356                         quota_flag = FILE_VOLUME_QUOTAS;
2357 #endif
2358
2359                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2360                                 (lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
2361                                 FILE_SUPPORTS_OBJECT_IDS|
2362                                 FILE_UNICODE_ON_DISK|
2363                                 quota_flag); /* FS ATTRIBUTES */
2364
2365                         SIVAL(pdata,4,255); /* Max filename component length */
2366                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2367                                 and will think we can't do long filenames */
2368                         len = srvstr_push(outbuf, pdata+12, fstype, -1, STR_UNICODE);
2369                         SIVAL(pdata,8,len);
2370                         data_len = 12 + len;
2371                         break;
2372
2373                 case SMB_QUERY_FS_LABEL_INFO:
2374                 case SMB_FS_LABEL_INFORMATION:
2375                         len = srvstr_push(outbuf, pdata+4, vname, -1, 0);
2376                         data_len = 4 + len;
2377                         SIVAL(pdata,0,len);
2378                         break;
2379
2380                 case SMB_QUERY_FS_VOLUME_INFO:      
2381                 case SMB_FS_VOLUME_INFORMATION:
2382
2383                         /* 
2384                          * Add volume serial number - hash of a combination of
2385                          * the called hostname and the service name.
2386                          */
2387                         SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^ 
2388                                 (str_checksum(get_local_machine_name())<<16));
2389
2390                         /* Max label len is 32 characters. */
2391                         len = srvstr_push(outbuf, pdata+18, vname, -1, STR_UNICODE);
2392                         SIVAL(pdata,12,len);
2393                         data_len = 18+len;
2394
2395                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n", 
2396                                 (int)strlen(vname),vname, lp_servicename(snum)));
2397                         break;
2398
2399                 case SMB_QUERY_FS_SIZE_INFO:
2400                 case SMB_FS_SIZE_INFORMATION:
2401                 {
2402                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2403                         data_len = 24;
2404                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2405                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2406                         }
2407                         block_size = lp_block_size(snum);
2408                         if (bsize < block_size) {
2409                                 SMB_BIG_UINT factor = block_size/bsize;
2410                                 bsize = block_size;
2411                                 dsize /= factor;
2412                                 dfree /= factor;
2413                         }
2414                         if (bsize > block_size) {
2415                                 SMB_BIG_UINT factor = bsize/block_size;
2416                                 bsize = block_size;
2417                                 dsize *= factor;
2418                                 dfree *= factor;
2419                         }
2420                         bytes_per_sector = 512;
2421                         sectors_per_unit = bsize/bytes_per_sector;
2422                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2423 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2424                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2425                         SBIG_UINT(pdata,0,dsize);
2426                         SBIG_UINT(pdata,8,dfree);
2427                         SIVAL(pdata,16,sectors_per_unit);
2428                         SIVAL(pdata,20,bytes_per_sector);
2429                         break;
2430                 }
2431
2432                 case SMB_FS_FULL_SIZE_INFORMATION:
2433                 {
2434                         SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2435                         data_len = 32;
2436                         if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2437                                 return(UNIXERROR(ERRHRD,ERRgeneral));
2438                         }
2439                         block_size = lp_block_size(snum);
2440                         if (bsize < block_size) {
2441                                 SMB_BIG_UINT factor = block_size/bsize;
2442                                 bsize = block_size;
2443                                 dsize /= factor;
2444                                 dfree /= factor;
2445                         }
2446                         if (bsize > block_size) {
2447                                 SMB_BIG_UINT factor = bsize/block_size;
2448                                 bsize = block_size;
2449                                 dsize *= factor;
2450                                 dfree *= factor;
2451                         }
2452                         bytes_per_sector = 512;
2453                         sectors_per_unit = bsize/bytes_per_sector;
2454                         DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2455 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2456                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2457                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2458                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2459                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2460                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2461                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2462                         break;
2463                 }
2464
2465                 case SMB_QUERY_FS_DEVICE_INFO:
2466                 case SMB_FS_DEVICE_INFORMATION:
2467                         data_len = 8;
2468                         SIVAL(pdata,0,0); /* dev type */
2469                         SIVAL(pdata,4,0); /* characteristics */
2470                         break;
2471
2472 #ifdef HAVE_SYS_QUOTAS
2473                 case SMB_FS_QUOTA_INFORMATION:
2474                 /* 
2475                  * what we have to send --metze:
2476                  *
2477                  * Unknown1:            24 NULL bytes
2478                  * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2479                  * Hard Quota Limit:    8 bytes seems like SMB_BIG_UINT or so
2480                  * Quota Flags:         2 byte :
2481                  * Unknown3:            6 NULL bytes
2482                  *
2483                  * 48 bytes total
2484                  * 
2485                  * details for Quota Flags:
2486                  * 
2487                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2488                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
2489                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2490                  * 0x0001 Enable Quotas: enable quota for this fs
2491                  *
2492                  */
2493                 {
2494                         /* we need to fake up a fsp here,
2495                          * because its not send in this call
2496                          */
2497                         files_struct fsp;
2498                         SMB_NTQUOTA_STRUCT quotas;
2499                         
2500                         ZERO_STRUCT(fsp);
2501                         ZERO_STRUCT(quotas);
2502                         
2503                         fsp.conn = conn;
2504                         fsp.fnum = -1;
2505                         
2506                         /* access check */
2507                         if (current_user.ut.uid != 0) {
2508                                 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2509                                         lp_servicename(SNUM(conn)),conn->user));
2510                                 return ERROR_DOS(ERRDOS,ERRnoaccess);
2511                         }
2512                         
2513                         if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2514                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2515                                 return ERROR_DOS(ERRSRV,ERRerror);
2516                         }
2517
2518                         data_len = 48;
2519
2520                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));          
2521                 
2522                         /* Unknown1 24 NULL bytes*/
2523                         SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2524                         SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2525                         SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2526                 
2527                         /* Default Soft Quota 8 bytes */
2528                         SBIG_UINT(pdata,24,quotas.softlim);
2529
2530                         /* Default Hard Quota 8 bytes */
2531                         SBIG_UINT(pdata,32,quotas.hardlim);
2532         
2533                         /* Quota flag 2 bytes */
2534                         SSVAL(pdata,40,quotas.qflags);
2535                 
2536                         /* Unknown3 6 NULL bytes */
2537                         SSVAL(pdata,42,0);
2538                         SIVAL(pdata,44,0);
2539                         
2540                         break;
2541                 }
2542 #endif /* HAVE_SYS_QUOTAS */
2543                 case SMB_FS_OBJECTID_INFORMATION:
2544                 {
2545                         unsigned char objid[16];
2546                         memcpy(pdata,create_volume_objectid(conn, objid),16);
2547                         data_len = 64;
2548                         break;
2549                 }
2550
2551                 /*
2552                  * Query the version and capabilities of the CIFS UNIX extensions
2553                  * in use.
2554                  */
2555
2556                 case SMB_QUERY_CIFS_UNIX_INFO:
2557                         if (!lp_unix_extensions()) {
2558                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2559                         }
2560                         data_len = 12;
2561                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2562                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2563                         /* We have POSIX ACLs, pathname and locking capability. */
2564                         SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2565                                         CIFS_UNIX_POSIX_ACLS_CAP|
2566                                         CIFS_UNIX_POSIX_PATHNAMES_CAP|
2567                                         CIFS_UNIX_FCNTL_LOCKS_CAP|
2568                                         CIFS_UNIX_EXTATTR_CAP|
2569                                         CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2570                                         /* Ensure we don't do this on signed or sealed data. */
2571                                         (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
2572                                         )));
2573                         break;
2574
2575                 case SMB_QUERY_POSIX_FS_INFO:
2576                 {
2577                         int rc;
2578                         vfs_statvfs_struct svfs;
2579
2580                         if (!lp_unix_extensions()) {
2581                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2582                         }
2583
2584                         rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2585
2586                         if (!rc) {
2587                                 data_len = 56;
2588                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
2589                                 SIVAL(pdata,4,svfs.BlockSize);
2590                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2591                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2592                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2593                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2594                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2595                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2596                                 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2597 #ifdef EOPNOTSUPP
2598                         } else if (rc == EOPNOTSUPP) {
2599                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2600 #endif /* EOPNOTSUPP */
2601                         } else {
2602                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2603                                 return ERROR_DOS(ERRSRV,ERRerror);
2604                         }
2605                         break;
2606                 }
2607
2608                 case SMB_QUERY_POSIX_WHOAMI:
2609                 {
2610                         uint32_t flags = 0;
2611                         uint32_t sid_bytes;
2612                         int i;
2613
2614                         if (!lp_unix_extensions()) {
2615                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2616                         }
2617
2618                         if (max_data_bytes < 40) {
2619                                 return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
2620                         }
2621
2622                         /* We ARE guest if global_sid_Builtin_Guests is
2623                          * in our list of SIDs.
2624                          */
2625                         if (nt_token_check_sid(&global_sid_Builtin_Guests,
2626                                     current_user.nt_user_token)) {
2627                                 flags |= SMB_WHOAMI_GUEST;
2628                         }
2629
2630                         /* We are NOT guest if global_sid_Authenticated_Users
2631                          * is in our list of SIDs.
2632                          */
2633                         if (nt_token_check_sid(&global_sid_Authenticated_Users,
2634                                     current_user.nt_user_token)) {
2635                                 flags &= ~SMB_WHOAMI_GUEST;
2636                         }
2637
2638                         /* NOTE: 8 bytes for UID/GID, irrespective of native
2639                          * platform size. This matches
2640                          * SMB_QUERY_FILE_UNIX_BASIC and friends.
2641                          */
2642                         data_len = 4 /* flags */
2643                             + 4 /* flag mask */
2644                             + 8 /* uid */
2645                             + 8 /* gid */
2646                             + 4 /* ngroups */
2647                             + 4 /* num_sids */
2648                             + 4 /* SID bytes */
2649                             + 4 /* pad/reserved */
2650                             + (current_user.ut.ngroups * 8)
2651                                 /* groups list */
2652                             + (current_user.nt_user_token->num_sids *
2653                                     SID_MAX_SIZE)
2654                                 /* SID list */;
2655
2656                         SIVAL(pdata, 0, flags);
2657                         SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2658                         SBIG_UINT(pdata, 8, (SMB_BIG_UINT)current_user.ut.uid);
2659                         SBIG_UINT(pdata, 16, (SMB_BIG_UINT)current_user.ut.gid);
2660
2661
2662                         if (data_len >= max_data_bytes) {
2663                                 /* Potential overflow, skip the GIDs and SIDs. */
2664
2665                                 SIVAL(pdata, 24, 0); /* num_groups */
2666                                 SIVAL(pdata, 28, 0); /* num_sids */
2667                                 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2668                                 SIVAL(pdata, 36, 0); /* reserved */
2669
2670                                 data_len = 40;
2671                                 break;
2672                         }
2673
2674                         SIVAL(pdata, 24, current_user.ut.ngroups);
2675                         SIVAL(pdata, 28,
2676                                 current_user.nt_user_token->num_sids);
2677
2678                         /* We walk the SID list twice, but this call is fairly
2679                          * infrequent, and I don't expect that it's performance
2680                          * sensitive -- jpeach
2681                          */
2682                         for (i = 0, sid_bytes = 0;
2683                             i < current_user.nt_user_token->num_sids; ++i) {
2684                                 sid_bytes +=
2685                                     sid_size(&current_user.nt_user_token->user_sids[i]);
2686                         }
2687
2688                         /* SID list byte count */
2689                         SIVAL(pdata, 32, sid_bytes);
2690
2691                         /* 4 bytes pad/reserved - must be zero */
2692                         SIVAL(pdata, 36, 0);
2693                         data_len = 40;
2694
2695                         /* GID list */
2696                         for (i = 0; i < current_user.ut.ngroups; ++i) {
2697                                 SBIG_UINT(pdata, data_len,
2698                                         (SMB_BIG_UINT)current_user.ut.groups[i]);
2699                                 data_len += 8;
2700                         }
2701
2702                         /* SID list */
2703                         for (i = 0;
2704                             i < current_user.nt_user_token->num_sids; ++i) {
2705                                 int sid_len =
2706                                     sid_size(&current_user.nt_user_token->user_sids[i]);
2707
2708                                 sid_linearize(pdata + data_len, sid_len,
2709                                     &current_user.nt_user_token->user_sids[i]);
2710                                 data_len += sid_len;
2711                         }
2712
2713                         break;
2714                 }
2715
2716                 case SMB_MAC_QUERY_FS_INFO:
2717                         /*
2718                          * Thursby MAC extension... ONLY on NTFS filesystems
2719                          * once we do streams then we don't need this
2720                          */
2721                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2722                                 data_len = 88;
2723                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
2724                                 break;
2725                         }
2726                         /* drop through */
2727                 default:
2728                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2729         }
2730
2731
2732         send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
2733
2734         DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
2735
2736         return -1;
2737 }
2738
2739 /****************************************************************************
2740  Reply to a TRANS2_SETFSINFO (set filesystem info).
2741 ****************************************************************************/
2742
2743 static int call_trans2setfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
2744                                         char **pparams, int total_params, char **ppdata, int total_data,
2745                                         unsigned int max_data_bytes)
2746 {
2747         char *pdata = *ppdata;
2748         char *params = *pparams;
2749         uint16 info_level;
2750         int outsize;
2751
2752         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
2753
2754         /*  */
2755         if (total_params < 4) {
2756                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
2757                         total_params));
2758                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2759         }
2760
2761         info_level = SVAL(params,2);
2762
2763         switch(info_level) {
2764                 case SMB_SET_CIFS_UNIX_INFO:
2765                         {
2766                                 uint16 client_unix_major;
2767                                 uint16 client_unix_minor;
2768                                 uint32 client_unix_cap_low;
2769                                 uint32 client_unix_cap_high;
2770
2771                                 if (!lp_unix_extensions()) {
2772                                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2773                                 }
2774
2775                                 /* There should be 12 bytes of capabilities set. */
2776                                 if (total_data < 8) {
2777                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2778                                 }
2779                                 client_unix_major = SVAL(pdata,0);
2780                                 client_unix_minor = SVAL(pdata,2);
2781                                 client_unix_cap_low = IVAL(pdata,4);
2782                                 client_unix_cap_high = IVAL(pdata,8);
2783                                 /* Just print these values for now. */
2784                                 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
2785 cap_low = 0x%x, cap_high = 0x%x\n",
2786                                         (unsigned int)client_unix_major,
2787                                         (unsigned int)client_unix_minor,
2788                                         (unsigned int)client_unix_cap_low,
2789                                         (unsigned int)client_unix_cap_high ));
2790
2791                                 /* Here is where we must switch to posix pathname processing... */
2792                                 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
2793                                         lp_set_posix_pathnames();
2794                                         mangle_change_to_posix();
2795                                 }
2796
2797                                 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
2798                                     !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
2799                                         /* Client that knows how to do posix locks,
2800                                          * but not posix open/mkdir operations. Set a
2801                                          * default type for read/write checks. */
2802
2803                                         lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
2804
2805                                 }
2806                                 break;
2807                         }
2808                 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
2809                         {
2810                                 NTSTATUS status;
2811                                 size_t param_len = 0;
2812                                 size_t data_len = total_data;
2813
2814                                 if (!lp_unix_extensions()) {
2815                                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2816                                 }
2817
2818                                 DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
2819
2820                                 status = srv_request_encryption_setup(conn,
2821                                                                         (unsigned char **)ppdata,
2822                                                                         &data_len,
2823                                                                         (unsigned char **)pparams,
2824                                                                         &param_len
2825                                                                         );
2826
2827                                 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
2828                                         error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
2829                                 } else if (!NT_STATUS_IS_OK(status)) {
2830                                         return ERROR_NT(status);
2831                                 }
2832
2833                                 send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
2834
2835                                 if (NT_STATUS_IS_OK(status)) {
2836                                         /* Server-side transport encryption is now *on*. */
2837                                         status = srv_encryption_start(conn);
2838                                         if (!NT_STATUS_IS_OK(status)) {
2839                                                 exit_server_cleanly("Failure in setting up encrypted transport");
2840                                         }
2841                                 }
2842                                 return -1;
2843                         }
2844                 case SMB_FS_QUOTA_INFORMATION:
2845                         {
2846                                 files_struct *fsp = NULL;
2847                                 SMB_NTQUOTA_STRUCT quotas;
2848         
2849                                 ZERO_STRUCT(quotas);
2850
2851                                 /* access check */
2852                                 if ((current_user.ut.uid != 0)||!CAN_WRITE(conn)) {
2853                                         DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
2854                                                 lp_servicename(SNUM(conn)),conn->user));
2855                                         return ERROR_DOS(ERRSRV,ERRaccess);
2856                                 }
2857
2858                                 /* note: normaly there're 48 bytes,
2859                                  * but we didn't use the last 6 bytes for now 
2860                                  * --metze 
2861                                  */
2862                                 fsp = file_fsp(SVAL(params,0));
2863                                 if (!CHECK_NTQUOTA_HANDLE_OK(fsp,conn)) {
2864                                         DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
2865                                         return ERROR_NT(NT_STATUS_INVALID_HANDLE);
2866                                 }
2867
2868                                 if (total_data < 42) {
2869                                         DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
2870                                                 total_data));
2871                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2872                                 }
2873                         
2874                                 /* unknown_1 24 NULL bytes in pdata*/
2875                 
2876                                 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
2877                                 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
2878 #ifdef LARGE_SMB_OFF_T
2879                                 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
2880 #else /* LARGE_SMB_OFF_T */
2881                                 if ((IVAL(pdata,28) != 0)&&
2882                                         ((quotas.softlim != 0xFFFFFFFF)||
2883                                         (IVAL(pdata,28)!=0xFFFFFFFF))) {
2884                                         /* more than 32 bits? */
2885                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2886                                 }
2887 #endif /* LARGE_SMB_OFF_T */
2888                 
2889                                 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
2890                                 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
2891 #ifdef LARGE_SMB_OFF_T
2892                                 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
2893 #else /* LARGE_SMB_OFF_T */
2894                                 if ((IVAL(pdata,36) != 0)&&
2895                                         ((quotas.hardlim != 0xFFFFFFFF)||
2896                                         (IVAL(pdata,36)!=0xFFFFFFFF))) {
2897                                         /* more than 32 bits? */
2898                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
2899                                 }
2900 #endif /* LARGE_SMB_OFF_T */
2901                 
2902                                 /* quota_flags 2 bytes **/
2903                                 quotas.qflags = SVAL(pdata,40);
2904                 
2905                                 /* unknown_2 6 NULL bytes follow*/
2906                 
2907                                 /* now set the quotas */
2908                                 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2909                                         DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2910                                         return ERROR_DOS(ERRSRV,ERRerror);
2911                                 }
2912                         
2913                                 break;
2914                         }
2915                 default:
2916                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
2917                                 info_level));
2918                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
2919                         break;
2920         }
2921
2922         /* 
2923          * sending this reply works fine, 
2924          * but I'm not sure it's the same 
2925          * like windows do...
2926          * --metze
2927          */ 
2928         outsize = set_message(inbuf, outbuf,10,0,True);
2929
2930         return outsize;
2931 }
2932
2933 #if defined(HAVE_POSIX_ACLS)
2934 /****************************************************************************
2935  Utility function to count the number of entries in a POSIX acl.
2936 ****************************************************************************/
2937
2938 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2939 {
2940         unsigned int ace_count = 0;
2941         int entry_id = SMB_ACL_FIRST_ENTRY;
2942         SMB_ACL_ENTRY_T entry;
2943
2944         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2945                 /* get_next... */
2946                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2947                         entry_id = SMB_ACL_NEXT_ENTRY;
2948                 }
2949                 ace_count++;
2950         }
2951         return ace_count;
2952 }
2953
2954 /****************************************************************************
2955  Utility function to marshall a POSIX acl into wire format.
2956 ****************************************************************************/
2957
2958 static BOOL marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2959 {
2960         int entry_id = SMB_ACL_FIRST_ENTRY;
2961         SMB_ACL_ENTRY_T entry;
2962
2963         while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
2964                 SMB_ACL_TAG_T tagtype;
2965                 SMB_ACL_PERMSET_T permset;
2966                 unsigned char perms = 0;
2967                 unsigned int own_grp;
2968
2969                 /* get_next... */
2970                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2971                         entry_id = SMB_ACL_NEXT_ENTRY;
2972                 }
2973
2974                 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
2975                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2976                         return False;
2977                 }
2978
2979                 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
2980                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2981                         return False;
2982                 }
2983
2984                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2985                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2986                 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2987
2988                 SCVAL(pdata,1,perms);
2989
2990                 switch (tagtype) {
2991                         case SMB_ACL_USER_OBJ:
2992                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2993                                 own_grp = (unsigned int)pst->st_uid;
2994                                 SIVAL(pdata,2,own_grp);
2995                                 SIVAL(pdata,6,0);
2996                                 break;
2997                         case SMB_ACL_USER:
2998                                 {
2999                                         uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3000                                         if (!puid) {
3001                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3002                                                 return False;
3003                                         }
3004                                         own_grp = (unsigned int)*puid;
3005                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3006                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3007                                         SIVAL(pdata,2,own_grp);
3008                                         SIVAL(pdata,6,0);
3009                                         break;
3010                                 }
3011                         case SMB_ACL_GROUP_OBJ:
3012                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3013                                 own_grp = (unsigned int)pst->st_gid;
3014                                 SIVAL(pdata,2,own_grp);
3015                                 SIVAL(pdata,6,0);
3016                                 break;
3017                         case SMB_ACL_GROUP:
3018                                 {
3019                                         gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3020                                         if (!pgid) {
3021                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3022                                                 return False;
3023                                         }
3024                                         own_grp = (unsigned int)*pgid;
3025                                         SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3026                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3027                                         SIVAL(pdata,2,own_grp);
3028                                         SIVAL(pdata,6,0);
3029                                         break;
3030                                 }
3031                         case SMB_ACL_MASK:
3032                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3033                                 SIVAL(pdata,2,0xFFFFFFFF);
3034                                 SIVAL(pdata,6,0xFFFFFFFF);
3035                                 break;
3036                         case SMB_ACL_OTHER:
3037                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3038                                 SIVAL(pdata,2,0xFFFFFFFF);
3039                                 SIVAL(pdata,6,0xFFFFFFFF);
3040                                 break;
3041                         default:
3042                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3043                                 return False;
3044                 }
3045                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3046         }
3047
3048         return True;
3049 }
3050 #endif
3051
3052 /****************************************************************************
3053  Store the FILE_UNIX_BASIC info.
3054 ****************************************************************************/
3055
3056 static char *store_file_unix_basic(connection_struct *conn,
3057                                 char *pdata,
3058                                 files_struct *fsp,
3059                                 const SMB_STRUCT_STAT *psbuf)
3060 {
3061         DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3062         DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3063
3064         SOFF_T(pdata,0,get_file_size(*psbuf));             /* File size 64 Bit */
3065         pdata += 8;
3066
3067         SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3068         pdata += 8;
3069
3070         put_long_date_timespec(pdata,get_ctimespec(psbuf));       /* Change Time 64 Bit */
3071         put_long_date_timespec(pdata+8,get_atimespec(psbuf));     /* Last access time 64 Bit */
3072         put_long_date_timespec(pdata+16,get_mtimespec(psbuf));    /* Last modification time 64 Bit */
3073         pdata += 24;
3074
3075         SIVAL(pdata,0,psbuf->st_uid);               /* user id for the owner */
3076         SIVAL(pdata,4,0);
3077         pdata += 8;
3078
3079         SIVAL(pdata,0,psbuf->st_gid);               /* group id of owner */
3080         SIVAL(pdata,4,0);
3081         pdata += 8;
3082
3083         SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3084         pdata += 4;
3085
3086         SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev));   /* Major device number if type is device */
3087         SIVAL(pdata,4,0);
3088         pdata += 8;
3089
3090         SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev));   /* Minor device number if type is device */
3091         SIVAL(pdata,4,0);
3092         pdata += 8;
3093
3094         SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino);   /* inode number */
3095         pdata += 8;
3096                                 
3097         SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode));     /* Standard UNIX file permissions */
3098         SIVAL(pdata,4,0);
3099         pdata += 8;
3100
3101         SIVAL(pdata,0,psbuf->st_nlink);             /* number of hard links */
3102         SIVAL(pdata,4,0);
3103         pdata += 8;
3104
3105         return pdata;
3106 }
3107
3108 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3109  * the chflags(2) (or equivalent) flags.
3110  *
3111  * XXX: this really should be behind the VFS interface. To do this, we would
3112  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3113  * Each VFS module could then implement it's own mapping as appropriate for the
3114  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3115  */
3116 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3117         info2_flags_map[] =
3118 {
3119 #ifdef UF_NODUMP
3120     { UF_NODUMP, EXT_DO_NOT_BACKUP },
3121 #endif
3122
3123 #ifdef UF_IMMUTABLE
3124     { UF_IMMUTABLE, EXT_IMMUTABLE },
3125 #endif
3126
3127 #ifdef UF_APPEND
3128     { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3129 #endif
3130
3131 #ifdef UF_HIDDEN
3132     { UF_HIDDEN, EXT_HIDDEN },
3133 #endif
3134
3135     /* Do not remove. We need to guarantee that this array has at least one
3136      * entry to build on HP-UX.
3137      */
3138     { 0, 0 }
3139
3140 };
3141
3142 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3143                                 uint32 *smb_fflags, uint32 *smb_fmask)
3144 {
3145 #ifdef HAVE_STAT_ST_FLAGS
3146         int i;
3147
3148         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3149             *smb_fmask |= info2_flags_map[i].smb_fflag;
3150             if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3151                     *smb_fflags |= info2_flags_map[i].smb_fflag;
3152             }
3153         }
3154 #endif /* HAVE_STAT_ST_FLAGS */
3155 }
3156
3157 static BOOL map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3158                                 const uint32 smb_fflags,
3159                                 const uint32 smb_fmask,
3160                                 int *stat_fflags)
3161 {
3162 #ifdef HAVE_STAT_ST_FLAGS
3163         uint32 max_fmask = 0;
3164         int i;
3165
3166         *stat_fflags = psbuf->st_flags;
3167
3168         /* For each flags requested in smb_fmask, check the state of the
3169          * corresponding flag in smb_fflags and set or clear the matching
3170          * stat flag.
3171          */
3172
3173         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3174             max_fmask |= info2_flags_map[i].smb_fflag;
3175             if (smb_fmask & info2_flags_map[i].smb_fflag) {
3176                     if (smb_fflags & info2_flags_map[i].smb_fflag) {
3177                             *stat_fflags |= info2_flags_map[i].stat_fflag;
3178                     } else {
3179                             *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3180                     }
3181             }
3182         }
3183
3184         /* If smb_fmask is asking to set any bits that are not supported by
3185          * our flag mappings, we should fail.
3186          */
3187         if ((smb_fmask & max_fmask) != smb_fmask) {
3188                 return False;
3189         }
3190
3191         return True;
3192 #else
3193         return False;
3194 #endif /* HAVE_STAT_ST_FLAGS */
3195 }
3196
3197
3198 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3199  * of file flags and birth (create) time.
3200  */
3201 static char *store_file_unix_basic_info2(connection_struct *conn,
3202                                 char *pdata,
3203                                 files_struct *fsp,
3204                                 const SMB_STRUCT_STAT *psbuf)
3205 {
3206         uint32 file_flags = 0;
3207         uint32 flags_mask = 0;
3208
3209         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3210
3211         /* Create (birth) time 64 bit */
3212         put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3213         pdata += 8;
3214
3215         map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3216         SIVAL(pdata, 0, file_flags); /* flags */
3217         SIVAL(pdata, 4, flags_mask); /* mask */
3218         pdata += 8;
3219
3220         return pdata;
3221 }
3222
3223 /****************************************************************************
3224  Reply to a TRANSACT2_QFILEINFO on a PIPE !
3225 ****************************************************************************/
3226
3227 static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3228                                         unsigned int tran_call,
3229                                         char **pparams, int total_params, char **ppdata, int total_data,
3230                                         unsigned int max_data_bytes)
3231 {
3232         char *params = *pparams;
3233         char *pdata = *ppdata;
3234         unsigned int data_size = 0;
3235         unsigned int param_size = 2;
3236         uint16 info_level;
3237         smb_np_struct *p_pipe = NULL;
3238
3239         if (!params) {
3240                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3241         }
3242
3243         if (total_params < 4) {
3244                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3245         }
3246
3247         p_pipe = get_rpc_pipe_p(SVAL(params,0));
3248         if (p_pipe == NULL) {
3249                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3250         }
3251
3252         info_level = SVAL(params,2);
3253
3254         *pparams = (char *)SMB_REALLOC(*pparams,2);
3255         if (*pparams == NULL) {
3256                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3257         }
3258         params = *pparams;
3259         SSVAL(params,0,0);
3260         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3261         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3262         if (*ppdata == NULL ) {
3263                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3264         }
3265         pdata = *ppdata;
3266
3267         switch (info_level) {
3268                 case SMB_FILE_STANDARD_INFORMATION:
3269                         memset(pdata,24,0);
3270                         SOFF_T(pdata,0,4096LL);
3271                         SIVAL(pdata,16,1);
3272                         SIVAL(pdata,20,1);
3273                         data_size = 24;
3274                         break;
3275
3276                 default:
3277                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3278         }
3279
3280         send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
3281
3282         return(-1);
3283 }
3284
3285 /****************************************************************************
3286  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3287  file name or file id).
3288 ****************************************************************************/
3289
3290 static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
3291                                         unsigned int tran_call,
3292                                         char **pparams, int total_params, char **ppdata, int total_data,
3293                                         unsigned int max_data_bytes)
3294 {
3295         char *params = *pparams;
3296         char *pdata = *ppdata;
3297         uint16 info_level;
3298         int mode=0;
3299         int nlink;
3300         SMB_OFF_T file_size=0;
3301         SMB_BIG_UINT allocation_size=0;
3302         unsigned int data_size = 0;
3303         unsigned int param_size = 2;
3304         SMB_STRUCT_STAT sbuf;
3305         pstring fname, dos_fname;
3306         char *fullpathname;
3307         char *base_name;
3308         char *p;
3309         SMB_OFF_T pos = 0;
3310         BOOL delete_pending = False;
3311         int len;
3312         time_t create_time, mtime, atime;
3313         struct timespec create_time_ts, mtime_ts, atime_ts;
3314         files_struct *fsp = NULL;
3315         struct file_id fileid;
3316         TALLOC_CTX *data_ctx = NULL;
3317         struct ea_list *ea_list = NULL;
3318         uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3319         char *lock_data = NULL;
3320
3321         if (!params)
3322                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3323
3324         ZERO_STRUCT(sbuf);
3325
3326         if (tran_call == TRANSACT2_QFILEINFO) {
3327                 if (total_params < 4) {
3328                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3329                 }
3330
3331                 if (IS_IPC(conn)) {
3332                         return call_trans2qpipeinfo(conn,
3333                                                         inbuf,
3334                                                         outbuf,
3335                                                         length,
3336                                                         bufsize,
3337                                                         tran_call,
3338                                                         pparams,
3339                                                         total_params,
3340                                                         ppdata,
3341                                                         total_data,
3342                                                         max_data_bytes);
3343                 }
3344
3345                 fsp = file_fsp(SVAL(params,0));
3346                 info_level = SVAL(params,2);
3347
3348                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3349
3350                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3351                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3352                 }
3353
3354                 if(fsp && (fsp->fake_file_handle)) {
3355                         /*
3356                          * This is actually for the QUOTA_FAKE_FILE --metze
3357                          */
3358                                                 
3359                         pstrcpy(fname, fsp->fsp_name);
3360                         /* We know this name is ok, it's already passed the checks. */
3361                         
3362                 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3363                         /*
3364                          * This is actually a QFILEINFO on a directory
3365                          * handle (returned from an NT SMB). NT5.0 seems
3366                          * to do this call. JRA.
3367                          */
3368                         /* We know this name is ok, it's already passed the checks. */
3369                         pstrcpy(fname, fsp->fsp_name);
3370                   
3371                         if (INFO_LEVEL_IS_UNIX(info_level)) {
3372                                 /* Always do lstat for UNIX calls. */
3373                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3374                                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3375                                         return UNIXERROR(ERRDOS,ERRbadpath);
3376                                 }
3377                         } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3378                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3379                                 return UNIXERROR(ERRDOS,ERRbadpath);
3380                         }
3381
3382                         fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3383                         delete_pending = get_delete_on_close_flag(fileid);
3384                 } else {
3385                         /*
3386                          * Original code - this is an open file.
3387                          */
3388                         CHECK_FSP(fsp,conn);
3389
3390                         pstrcpy(fname, fsp->fsp_name);
3391                         if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0) {
3392                                 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3393                                 return(UNIXERROR(ERRDOS,ERRbadfid));
3394                         }
3395                         pos = fsp->fh->position_information;
3396                         fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3397                         delete_pending = get_delete_on_close_flag(fileid);
3398                         access_mask = fsp->access_mask;
3399                 }
3400         } else {
3401                 NTSTATUS status = NT_STATUS_OK;
3402
3403                 /* qpathinfo */
3404                 if (total_params < 7) {
3405                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3406                 }
3407
3408                 info_level = SVAL(params,0);
3409
3410                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3411
3412                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3413                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3414                 }
3415
3416                 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, &params[6],
3417                                 sizeof(fname), total_params - 6,
3418                                 STR_TERMINATE, &status);
3419                 if (!NT_STATUS_IS_OK(status)) {
3420                         return ERROR_NT(status);
3421                 }
3422
3423                 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
3424                 if (!NT_STATUS_IS_OK(status)) {
3425                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3426                                 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
3427                         }
3428                         return ERROR_NT(status);
3429                 }
3430
3431                 status = unix_convert(conn, fname, False, NULL, &sbuf);
3432                 if (!NT_STATUS_IS_OK(status)) {
3433                         return ERROR_NT(status);
3434                 }
3435                 status = check_name(conn, fname);
3436                 if (!NT_STATUS_IS_OK(status)) {
3437                         DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3438                         return ERROR_NT(status);
3439                 }
3440
3441                 if (INFO_LEVEL_IS_UNIX(info_level)) {
3442                         /* Always do lstat for UNIX calls. */
3443                         if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3444                                 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3445                                 return UNIXERROR(ERRDOS,ERRbadpath);
3446                         }
3447                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
3448                         DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3449                         return UNIXERROR(ERRDOS,ERRbadpath);
3450                 }
3451
3452                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3453                 delete_pending = get_delete_on_close_flag(fileid);
3454                 if (delete_pending) {
3455                         return ERROR_NT(NT_STATUS_DELETE_PENDING);
3456                 }
3457         }
3458
3459         nlink = sbuf.st_nlink;
3460
3461         if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) {
3462                 /* NTFS does not seem to count ".." */
3463                 nlink -= 1;
3464         }
3465
3466         if ((nlink > 0) && delete_pending) {
3467                 nlink -= 1;
3468         }
3469
3470         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3471                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
3472         }
3473
3474         DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
3475                 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
3476
3477         p = strrchr_m(fname,'/'); 
3478         if (!p)
3479                 base_name = fname;
3480         else
3481                 base_name = p+1;
3482
3483         mode = dos_mode(conn,fname,&sbuf);
3484         if (!mode)
3485                 mode = FILE_ATTRIBUTE_NORMAL;
3486
3487         fullpathname = fname;
3488         if (!(mode & aDIR))
3489                 file_size = get_file_size(sbuf);
3490
3491         /* Pull out any data sent here before we realloc. */
3492         switch (info_level) {
3493                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3494                 {
3495                         /* Pull any EA list from the data portion. */
3496                         uint32 ea_size;
3497
3498                         if (total_data < 4) {
3499                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3500                         }
3501                         ea_size = IVAL(pdata,0);
3502
3503                         if (total_data > 0 && ea_size != total_data) {
3504                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
3505 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3506                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3507                         }
3508
3509                         if (!lp_ea_support(SNUM(conn))) {
3510                                 return ERROR_DOS(ERRDOS,ERReasnotsupported);
3511                         }
3512
3513                         if ((data_ctx = talloc_init("ea_list")) == NULL) {
3514                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3515                         }
3516
3517                         /* Pull out the list of names. */
3518                         ea_list = read_ea_name_list(data_ctx, pdata + 4, ea_size - 4);
3519                         if (!ea_list) {
3520                                 talloc_destroy(data_ctx);
3521                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3522                         }
3523                         break;
3524                 }
3525
3526                 case SMB_QUERY_POSIX_LOCK:
3527                 {
3528                         if (fsp == NULL || fsp->fh->fd == -1) {
3529                                 return ERROR_NT(NT_STATUS_INVALID_HANDLE);
3530                         }
3531
3532                         if (total_data != POSIX_LOCK_DATA_SIZE) {
3533                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
3534                         }
3535
3536                         if ((data_ctx = talloc_init("lock_request")) == NULL) {
3537                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3538                         }
3539
3540                         /* Copy the lock range data. */
3541                         lock_data = (char *)TALLOC_MEMDUP(
3542                                 data_ctx, pdata, total_data);
3543                         if (!lock_data) {
3544                                 talloc_destroy(data_ctx);
3545                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3546                         }
3547                 }
3548                 default:
3549                         break;
3550         }
3551
3552         *pparams = (char *)SMB_REALLOC(*pparams,2);
3553         if (*pparams == NULL) {
3554                 talloc_destroy(data_ctx);
3555                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3556         }
3557         params = *pparams;
3558         SSVAL(params,0,0);
3559         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3560         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
3561         if (*ppdata == NULL ) {
3562                 talloc_destroy(data_ctx);
3563                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3564         }
3565         pdata = *ppdata;
3566
3567         create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
3568         mtime_ts = get_mtimespec(&sbuf);
3569         atime_ts = get_atimespec(&sbuf);
3570
3571         allocation_size = get_allocation_size(conn,fsp,&sbuf);
3572
3573         if (fsp) {
3574                 if (!null_timespec(fsp->pending_modtime)) {
3575                         /* the pending modtime overrides the current modtime */
3576                         mtime_ts = fsp->pending_modtime;
3577                 }
3578         } else {
3579                 files_struct *fsp1;
3580                 /* Do we have this path open ? */
3581                 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3582                 fsp1 = file_find_di_first(fileid);
3583                 if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
3584                         /* the pending modtime overrides the current modtime */
3585                         mtime_ts = fsp1->pending_modtime;
3586                 }
3587                 if (fsp1 && fsp1->initial_allocation_size) {
3588                         allocation_size = get_allocation_size(conn, fsp1, &sbuf);
3589                 }
3590         }
3591
3592         if (lp_dos_filetime_resolution(SNUM(conn))) {
3593                 dos_filetime_timespec(&create_time_ts);
3594                 dos_filetime_timespec(&mtime_ts);
3595                 dos_filetime_timespec(&atime_ts);
3596         }
3597
3598         create_time = convert_timespec_to_time_t(create_time_ts);
3599         mtime = convert_timespec_to_time_t(mtime_ts);
3600         atime = convert_timespec_to_time_t(atime_ts);
3601
3602         /* NT expects the name to be in an exact form of the *full*
3603            filename. See the trans2 torture test */
3604         if (strequal(base_name,".")) {
3605                 pstrcpy(dos_fname, "\\");
3606         } else {
3607                 pstr_sprintf(dos_fname, "\\%s", fname);
3608                 string_replace(dos_fname, '/', '\\');
3609         }
3610
3611         switch (info_level) {
3612                 case SMB_INFO_STANDARD:
3613                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
3614                         data_size = 22;
3615                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3616                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3617                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3618                         SIVAL(pdata,l1_cbFile,(uint32)file_size);
3619                         SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
3620                         SSVAL(pdata,l1_attrFile,mode);
3621                         break;
3622
3623                 case SMB_INFO_QUERY_EA_SIZE:
3624                 {
3625                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3626                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3627                         data_size = 26;
3628                         srv_put_dos_date2(pdata,0,create_time);
3629                         srv_put_dos_date2(pdata,4,atime);
3630                         srv_put_dos_date2(pdata,8,mtime); /* write time */
3631                         SIVAL(pdata,12,(uint32)file_size);
3632                         SIVAL(pdata,16,(uint32)allocation_size);
3633                         SSVAL(pdata,20,mode);
3634                         SIVAL(pdata,22,ea_size);
3635                         break;
3636                 }
3637
3638                 case SMB_INFO_IS_NAME_VALID:
3639                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3640                         if (tran_call == TRANSACT2_QFILEINFO) {
3641                                 /* os/2 needs this ? really ?*/      
3642                                 return ERROR_DOS(ERRDOS,ERRbadfunc); 
3643                         }
3644                         data_size = 0;
3645                         param_size = 0;
3646                         break;
3647                         
3648                 case SMB_INFO_QUERY_EAS_FROM_LIST:
3649                 {
3650                         size_t total_ea_len = 0;
3651                         struct ea_list *ea_file_list = NULL;
3652
3653                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3654
3655                         ea_file_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3656                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3657
3658                         if (!ea_list || (total_ea_len > data_size)) {
3659                                 talloc_destroy(data_ctx);
3660                                 data_size = 4;
3661                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3662                                 break;
3663                         }
3664
3665                         data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3666                         talloc_destroy(data_ctx);
3667                         break;
3668                 }
3669
3670                 case SMB_INFO_QUERY_ALL_EAS:
3671                 {
3672                         /* We have data_size bytes to put EA's into. */
3673                         size_t total_ea_len = 0;
3674
3675                         DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3676
3677                         data_ctx = talloc_init("ea_ctx");
3678                         if (!data_ctx) {
3679                                 return ERROR_NT(NT_STATUS_NO_MEMORY);
3680                         }
3681
3682                         ea_list = get_ea_list_from_file(data_ctx, conn, fsp, fname, &total_ea_len);
3683                         if (!ea_list || (total_ea_len > data_size)) {
3684                                 talloc_destroy(data_ctx);
3685                                 data_size = 4;
3686                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
3687                                 break;
3688                         }
3689
3690                         data_size = fill_ea_buffer(data_ctx, pdata, data_size, conn, ea_list);
3691                         talloc_destroy(data_ctx);
3692                         break;
3693                 }
3694
3695                 case SMB_FILE_BASIC_INFORMATION:
3696                 case SMB_QUERY_FILE_BASIC_INFO:
3697
3698                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3699                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3700                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3701                         } else {
3702                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3703                                 data_size = 40;
3704                                 SIVAL(pdata,36,0);
3705                         }
3706                         put_long_date_timespec(pdata,create_time_ts);
3707                         put_long_date_timespec(pdata+8,atime_ts);
3708                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3709                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3710                         SIVAL(pdata,32,mode);
3711
3712                         DEBUG(5,("SMB_QFBI - "));
3713                         DEBUG(5,("create: %s ", ctime(&create_time)));
3714                         DEBUG(5,("access: %s ", ctime(&atime)));
3715                         DEBUG(5,("write: %s ", ctime(&mtime)));
3716                         DEBUG(5,("change: %s ", ctime(&mtime)));
3717                         DEBUG(5,("mode: %x\n", mode));
3718                         break;
3719
3720                 case SMB_FILE_STANDARD_INFORMATION:
3721                 case SMB_QUERY_FILE_STANDARD_INFO:
3722
3723                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3724                         data_size = 24;
3725                         SOFF_T(pdata,0,allocation_size);
3726                         SOFF_T(pdata,8,file_size);
3727                         SIVAL(pdata,16,nlink);
3728                         SCVAL(pdata,20,delete_pending?1:0);
3729                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3730                         SSVAL(pdata,22,0); /* Padding. */
3731                         break;
3732
3733                 case SMB_FILE_EA_INFORMATION:
3734                 case SMB_QUERY_FILE_EA_INFO:
3735                 {
3736                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3737                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3738                         data_size = 4;
3739                         SIVAL(pdata,0,ea_size);
3740                         break;
3741                 }
3742
3743                 /* Get the 8.3 name - used if NT SMB was negotiated. */
3744                 case SMB_QUERY_FILE_ALT_NAME_INFO:
3745                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3746                 {
3747                         pstring short_name;
3748
3749                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3750                         pstrcpy(short_name,base_name);
3751                         /* Mangle if not already 8.3 */
3752                         if(!mangle_is_8_3(short_name, True, conn->params)) {
3753                                 mangle_map(short_name,True,True,conn->params);
3754                         }
3755                         len = srvstr_push(outbuf, pdata+4, short_name, -1, STR_UNICODE);
3756                         data_size = 4 + len;
3757                         SIVAL(pdata,0,len);
3758                         break;
3759                 }
3760
3761                 case SMB_QUERY_FILE_NAME_INFO:
3762                         /*
3763                           this must be *exactly* right for ACLs on mapped drives to work
3764                          */
3765                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3766                         DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3767                         data_size = 4 + len;
3768                         SIVAL(pdata,0,len);
3769                         break;
3770
3771                 case SMB_FILE_ALLOCATION_INFORMATION:
3772                 case SMB_QUERY_FILE_ALLOCATION_INFO:
3773                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3774                         data_size = 8;
3775                         SOFF_T(pdata,0,allocation_size);
3776                         break;
3777
3778                 case SMB_FILE_END_OF_FILE_INFORMATION:
3779                 case SMB_QUERY_FILE_END_OF_FILEINFO:
3780                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3781                         data_size = 8;
3782                         SOFF_T(pdata,0,file_size);
3783                         break;
3784
3785                 case SMB_QUERY_FILE_ALL_INFO:
3786                 case SMB_FILE_ALL_INFORMATION:
3787                 {
3788                         unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
3789                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3790                         put_long_date_timespec(pdata,create_time_ts);
3791                         put_long_date_timespec(pdata+8,atime_ts);
3792                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3793                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3794                         SIVAL(pdata,32,mode);
3795                         SIVAL(pdata,36,0); /* padding. */
3796                         pdata += 40;
3797                         SOFF_T(pdata,0,allocation_size);
3798                         SOFF_T(pdata,8,file_size);
3799                         SIVAL(pdata,16,nlink);
3800                         SCVAL(pdata,20,delete_pending);
3801                         SCVAL(pdata,21,(mode&aDIR)?1:0);
3802                         SSVAL(pdata,22,0);
3803                         pdata += 24;
3804                         SIVAL(pdata,0,ea_size);
3805                         pdata += 4; /* EA info */
3806                         len = srvstr_push(outbuf, pdata+4, dos_fname, -1, STR_UNICODE);
3807                         SIVAL(pdata,0,len);
3808                         pdata += 4 + len;
3809                         data_size = PTR_DIFF(pdata,(*ppdata));
3810                         break;
3811                 }
3812                 case SMB_FILE_INTERNAL_INFORMATION:
3813                         /* This should be an index number - looks like
3814                            dev/ino to me :-) 
3815
3816                            I think this causes us to fail the IFSKIT
3817                            BasicFileInformationTest. -tpot */
3818
3819                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3820                         SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
3821                         SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
3822                         data_size = 8;
3823                         break;
3824
3825                 case SMB_FILE_ACCESS_INFORMATION:
3826                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3827                         SIVAL(pdata,0,access_mask);
3828                         data_size = 4;
3829                         break;
3830
3831                 case SMB_FILE_NAME_INFORMATION:
3832                         /* Pathname with leading '\'. */
3833                         {
3834                                 size_t byte_len;
3835                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3836                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3837                                 SIVAL(pdata,0,byte_len);
3838                                 data_size = 4 + byte_len;
3839                                 break;
3840                         }
3841
3842                 case SMB_FILE_DISPOSITION_INFORMATION:
3843                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3844                         data_size = 1;
3845                         SCVAL(pdata,0,delete_pending);
3846                         break;
3847
3848                 case SMB_FILE_POSITION_INFORMATION:
3849                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3850                         data_size = 8;
3851                         SOFF_T(pdata,0,pos);
3852                         break;
3853
3854                 case SMB_FILE_MODE_INFORMATION:
3855                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3856                         SIVAL(pdata,0,mode);
3857                         data_size = 4;
3858                         break;
3859
3860                 case SMB_FILE_ALIGNMENT_INFORMATION:
3861                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3862                         SIVAL(pdata,0,0); /* No alignment needed. */
3863                         data_size = 4;
3864                         break;
3865
3866 #if 0
3867                 /*
3868                  * NT4 server just returns "invalid query" to this - if we try to answer
3869                  * it then NTws gets a BSOD! (tridge).
3870                  * W2K seems to want this. JRA.
3871                  */
3872                 case SMB_QUERY_FILE_STREAM_INFO:
3873 #endif
3874                 case SMB_FILE_STREAM_INFORMATION:
3875                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n"));
3876                         if (mode & aDIR) {
3877                                 data_size = 0;
3878                         } else {
3879                                 size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False);
3880                                 SIVAL(pdata,0,0); /* ??? */
3881                                 SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */
3882                                 SOFF_T(pdata,8,file_size);
3883                                 SOFF_T(pdata,16,allocation_size);
3884                                 data_size = 24 + byte_len;
3885                         }
3886                         break;
3887
3888                 case SMB_QUERY_COMPRESSION_INFO:
3889                 case SMB_FILE_COMPRESSION_INFORMATION:
3890                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3891                         SOFF_T(pdata,0,file_size);
3892                         SIVAL(pdata,8,0); /* ??? */
3893                         SIVAL(pdata,12,0); /* ??? */
3894                         data_size = 16;
3895                         break;
3896
3897                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3898                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3899                         put_long_date_timespec(pdata,create_time_ts);
3900                         put_long_date_timespec(pdata+8,atime_ts);
3901                         put_long_date_timespec(pdata+16,mtime_ts); /* write time */
3902                         put_long_date_timespec(pdata+24,mtime_ts); /* change time */
3903                         SOFF_T(pdata,32,allocation_size);
3904                         SOFF_T(pdata,40,file_size);
3905                         SIVAL(pdata,48,mode);
3906                         SIVAL(pdata,52,0); /* ??? */
3907                         data_size = 56;
3908                         break;
3909
3910                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3911                         DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3912                         SIVAL(pdata,0,mode);
3913                         SIVAL(pdata,4,0);
3914                         data_size = 8;
3915                         break;
3916
3917                 /*
3918                  * CIFS UNIX Extensions.
3919                  */
3920
3921                 case SMB_QUERY_FILE_UNIX_BASIC:
3922
3923                         pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
3924                         data_size = PTR_DIFF(pdata,(*ppdata));
3925
3926                         {
3927                                 int i;
3928                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
3929
3930                                 for (i=0; i<100; i++)
3931                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3932                                 DEBUG(4,("\n"));
3933                         }
3934
3935                         break;
3936
3937                 case SMB_QUERY_FILE_UNIX_INFO2:
3938
3939                         pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
3940                         data_size = PTR_DIFF(pdata,(*ppdata));
3941
3942                         {
3943                                 int i;
3944                                 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
3945
3946                                 for (i=0; i<100; i++)
3947                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
3948                                 DEBUG(4,("\n"));
3949                         }
3950
3951                         break;
3952
3953                 case SMB_QUERY_FILE_UNIX_LINK:
3954                         {
3955                                 pstring buffer;
3956
3957                                 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
3958 #ifdef S_ISLNK
3959                                 if(!S_ISLNK(sbuf.st_mode))
3960                                         return(UNIXERROR(ERRSRV,ERRbadlink));
3961 #else
3962                                 return(UNIXERROR(ERRDOS,ERRbadlink));
3963 #endif
3964                                 len = SMB_VFS_READLINK(conn,fullpathname, buffer, sizeof(pstring)-1);     /* read link */
3965                                 if (len == -1)
3966                                         return(UNIXERROR(ERRDOS,ERRnoaccess));
3967                                 buffer[len] = 0;
3968                                 len = srvstr_push(outbuf, pdata, buffer, -1, STR_TERMINATE);
3969                                 pdata += len;
3970                                 data_size = PTR_DIFF(pdata,(*ppdata));
3971
3972                                 break;
3973                         }
3974
3975 #if defined(HAVE_POSIX_ACLS)
3976                 case SMB_QUERY_POSIX_ACL:
3977                         {
3978                                 SMB_ACL_T file_acl = NULL;
3979                                 SMB_ACL_T def_acl = NULL;
3980                                 uint16 num_file_acls = 0;
3981                                 uint16 num_def_acls = 0;
3982
3983                                 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
3984                                         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, fsp->fh->fd);
3985                                 } else {
3986                                         file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
3987                                 }
3988
3989                                 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3990                                         DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
3991                                                 fname ));
3992                                         return ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
3993                                 }
3994
3995                                 if (S_ISDIR(sbuf.st_mode)) {
3996                                         if (fsp && fsp->is_directory) {
3997                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
3998                                         } else {
3999                                                 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4000                                         }
4001                                         def_acl = free_empty_sys_acl(conn, def_acl);
4002                                 }
4003
4004                                 num_file_acls = count_acl_entries(conn, file_acl);
4005                                 num_def_acls = count_acl_entries(conn, def_acl);
4006
4007                                 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4008                                         DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4009                                                 data_size,
4010                                                 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4011                                                         SMB_POSIX_ACL_HEADER_SIZE) ));
4012                                         if (file_acl) {
4013                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4014                                         }
4015                                         if (def_acl) {
4016                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4017                                         }
4018                                         return ERROR_NT(NT_STATUS_BUFFER_TOO_SMALL);
4019                                 }
4020
4021                                 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4022                                 SSVAL(pdata,2,num_file_acls);
4023                                 SSVAL(pdata,4,num_def_acls);
4024                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4025                                         if (file_acl) {
4026                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4027                                         }
4028                                         if (def_acl) {
4029                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4030                                         }
4031                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4032                                 }
4033                                 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4034                                         if (file_acl) {
4035                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4036                                         }
4037                                         if (def_acl) {
4038                                                 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4039                                         }
4040                                         return ERROR_NT(NT_STATUS_INTERNAL_ERROR);
4041                                 }
4042
4043                                 if (file_acl) {
4044                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4045                                 }
4046                                 if (def_acl) {
4047                                         SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4048                                 }
4049                                 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4050                                 break;
4051                         }
4052 #endif
4053
4054
4055                 case SMB_QUERY_POSIX_LOCK:
4056                 {
4057                         NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4058                         SMB_BIG_UINT count;
4059                         SMB_BIG_UINT offset;
4060                         uint32 lock_pid;
4061                         enum brl_type lock_type;
4062
4063                         if (total_data != POSIX_LOCK_DATA_SIZE) {
4064                                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4065                         }
4066
4067                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4068                                 case POSIX_LOCK_TYPE_READ:
4069                                         lock_type = READ_LOCK;
4070                                         break;
4071                                 case POSIX_LOCK_TYPE_WRITE:
4072                                         lock_type = WRITE_LOCK;
4073                                         break;
4074                                 case POSIX_LOCK_TYPE_UNLOCK:
4075                                 default:
4076                                         /* There's no point in asking for an unlock... */
4077                                         talloc_destroy(data_ctx);
4078                                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
4079                         }
4080
4081                         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4082 #if defined(HAVE_LONGLONG)
4083                         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4084                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4085                         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4086                                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4087 #else /* HAVE_LONGLONG */
4088                         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4089                         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4090 #endif /* HAVE_LONGLONG */
4091
4092                         status = query_lock(fsp,
4093                                         &lock_pid,
4094                                         &count,
4095                                         &offset,
4096                                         &lock_type,
4097                                         POSIX_LOCK);
4098
4099                         if (ERROR_WAS_LOCK_DENIED(status)) {
4100                                 /* Here we need to report who has it locked... */
4101                                 data_size = POSIX_LOCK_DATA_SIZE;
4102
4103                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4104                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4105                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4106 #if defined(HAVE_LONGLONG)
4107                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4108                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4109                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4110                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4111 #else /* HAVE_LONGLONG */
4112                                 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4113                                 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4114 #endif /* HAVE_LONGLONG */
4115
4116                         } else if (NT_STATUS_IS_OK(status)) {
4117                                 /* For success we just return a copy of what we sent
4118                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4119                                 data_size = POSIX_LOCK_DATA_SIZE;
4120                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4121                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4122                         } else {
4123                                 return ERROR_NT(status);
4124                         }
4125                         break;
4126                 }
4127
4128                 default:
4129                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
4130         }
4131
4132         send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
4133
4134         return(-1);
4135 }
4136
4137 /****************************************************************************
4138  Set a hard link (called by UNIX extensions and by NT rename with HARD link
4139  code.
4140 ****************************************************************************/
4141
4142 NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring newname)
4143 {
4144         SMB_STRUCT_STAT sbuf1, sbuf2;
4145         pstring last_component_oldname;
4146         pstring last_component_newname;
4147         NTSTATUS status = NT_STATUS_OK;
4148
4149         ZERO_STRUCT(sbuf1);
4150         ZERO_STRUCT(sbuf2);
4151
4152         status = unix_convert(conn, oldname, False, last_component_oldname, &sbuf1);
4153         if (!NT_STATUS_IS_OK(status)) {
4154                 return status;
4155         }
4156
4157         status = check_name(conn, oldname);
4158         if (!NT_STATUS_IS_OK(status)) {
4159                 return status;
4160         }
4161
4162         /* source must already exist. */
4163         if (!VALID_STAT(sbuf1)) {
4164                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4165         }
4166
4167         status = unix_convert(conn, newname, False, last_component_newname, &sbuf2);
4168         if (!NT_STATUS_IS_OK(status)) {
4169                 return status;
4170         }
4171
4172         status = check_name(conn, newname);
4173         if (!NT_STATUS_IS_OK(status)) {
4174                 return status;
4175         }
4176
4177         /* Disallow if newname already exists. */
4178         if (VALID_STAT(sbuf2)) {
4179                 return NT_STATUS_OBJECT_NAME_COLLISION;
4180         }
4181
4182         /* No links from a directory. */
4183         if (S_ISDIR(sbuf1.st_mode)) {
4184                 return NT_STATUS_FILE_IS_A_DIRECTORY;
4185         }
4186
4187         /* Ensure this is within the share. */
4188         status = check_reduced_name(conn, oldname);
4189         if (!NT_STATUS_IS_OK(status)) {
4190                 return status;
4191         }
4192
4193         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4194
4195         if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4196                 status = map_nt_error_from_unix(errno);
4197                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4198                                 nt_errstr(status), newname, oldname));
4199         }
4200
4201         return status;
4202 }
4203
4204 /****************************************************************************
4205  Deal with setting the time from any of the setfilepathinfo functions.
4206 ****************************************************************************/
4207
4208 static NTSTATUS smb_set_file_time(connection_struct *conn,
4209                                 files_struct *fsp,
4210                                 const char *fname,
4211                                 const SMB_STRUCT_STAT *psbuf,
4212                                 struct timespec ts[2])
4213 {
4214         uint32 action =
4215                 FILE_NOTIFY_CHANGE_LAST_ACCESS
4216                 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4217
4218         
4219         if (!VALID_STAT(*psbuf)) {
4220                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4221         }
4222
4223         /* get some defaults (no modifications) if any info is zero or -1. */
4224         if (null_timespec(ts[0])) {
4225                 ts[0] = get_atimespec(psbuf);
4226                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4227         }
4228
4229         if (null_timespec(ts[1])) {
4230                 ts[1] = get_mtimespec(psbuf);
4231                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4232         }
4233
4234         DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4235         DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4236
4237         /*
4238          * Try and set the times of this file if
4239          * they are different from the current values.
4240          */
4241
4242         {
4243                 struct timespec mts = get_mtimespec(psbuf);
4244                 struct timespec ats = get_atimespec(psbuf);
4245                 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4246                         return NT_STATUS_OK;
4247                 }
4248         }
4249
4250         if(fsp != NULL) {
4251                 /*
4252                  * This was a setfileinfo on an open file.
4253                  * NT does this a lot. We also need to 
4254                  * set the time here, as it can be read by 
4255                  * FindFirst/FindNext and with the patch for bug #2045
4256                  * in smbd/fileio.c it ensures that this timestamp is
4257                  * kept sticky even after a write. We save the request
4258                  * away and will set it on file close and after a write. JRA.
4259                  */
4260
4261                 if (!null_timespec(ts[1])) {
4262                         DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4263                                 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4264                         fsp_set_pending_modtime(fsp, ts[1]);
4265                 }
4266
4267         }
4268         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4269
4270         if(file_ntimes(conn, fname, ts)!=0) {
4271                 return map_nt_error_from_unix(errno);
4272         }
4273         if (action != 0) {
4274                 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4275         }
4276         return NT_STATUS_OK;
4277 }
4278
4279 /****************************************************************************
4280  Deal with setting the dosmode from any of the setfilepathinfo functions.
4281 ****************************************************************************/
4282
4283 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4284                                 const char *fname,
4285                                 SMB_STRUCT_STAT *psbuf,
4286                                 uint32 dosmode)
4287 {
4288         if (!VALID_STAT(*psbuf)) {
4289                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4290         }
4291
4292         if (dosmode) {
4293                 if (S_ISDIR(psbuf->st_mode)) {
4294                         dosmode |= aDIR;
4295                 } else {
4296                         dosmode &= ~aDIR;
4297                 }
4298         }
4299
4300         DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4301
4302         /* check the mode isn't different, before changing it */
4303         if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4304
4305                 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4306                                         fname, (unsigned int)dosmode ));
4307
4308                 if(file_set_dosmode(conn, fname, dosmode, psbuf, False)) {
4309                         DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4310                                                 fname, strerror(errno)));
4311                         return map_nt_error_from_unix(errno);
4312                 }
4313         }
4314         return NT_STATUS_OK;
4315 }
4316
4317 /****************************************************************************
4318  Deal with setting the size from any of the setfilepathinfo functions.
4319 ****************************************************************************/
4320
4321 static NTSTATUS smb_set_file_size(connection_struct *conn,
4322                                   struct smb_request *req,
4323                                 files_struct *fsp,
4324                                 const char *fname,
4325                                 SMB_STRUCT_STAT *psbuf,
4326                                 SMB_OFF_T size)
4327 {
4328         NTSTATUS status = NT_STATUS_OK;
4329         files_struct *new_fsp = NULL;
4330
4331         if (!VALID_STAT(*psbuf)) {
4332                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4333         }
4334
4335         DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4336
4337         if (size == get_file_size(*psbuf)) {
4338                 return NT_STATUS_OK;
4339         }
4340
4341         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4342                 fname, (double)size ));
4343
4344         if (fsp && fsp->fh->fd != -1) {
4345                 /* Handle based call. */
4346                 if (vfs_set_filelen(fsp, size) == -1) {
4347                         return map_nt_error_from_unix(errno);
4348                 }
4349                 return NT_STATUS_OK;
4350         }
4351
4352         status = open_file_ntcreate(conn, req, fname, psbuf,
4353                                 FILE_WRITE_DATA,
4354                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
4355                                 FILE_OPEN,
4356                                 0,
4357                                 FILE_ATTRIBUTE_NORMAL,
4358                                 FORCE_OPLOCK_BREAK_TO_NONE,
4359                                 NULL, &new_fsp);
4360         
4361         if (!NT_STATUS_IS_OK(status)) {
4362                 /* NB. We check for open_was_deferred in the caller. */
4363                 return status;
4364         }
4365
4366         if (vfs_set_filelen(new_fsp, size) == -1) {
4367                 status = map_nt_error_from_unix(errno);
4368                 close_file(new_fsp,NORMAL_CLOSE);
4369                 return status;
4370         }
4371
4372         close_file(new_fsp,NORMAL_CLOSE);
4373         return NT_STATUS_OK;
4374 }
4375
4376 /****************************************************************************
4377  Deal with SMB_INFO_SET_EA.
4378 ****************************************************************************/
4379
4380 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4381                                 const char *pdata,
4382                                 int total_data,
4383                                 files_struct *fsp,
4384                                 const char *fname)
4385 {
4386         struct ea_list *ea_list = NULL;
4387         TALLOC_CTX *ctx = NULL;
4388         NTSTATUS status = NT_STATUS_OK;
4389
4390         if (total_data < 10) {
4391
4392                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4393                    length. They seem to have no effect. Bug #3212. JRA */
4394
4395                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4396                         /* We're done. We only get EA info in this call. */
4397                         return NT_STATUS_OK;
4398                 }
4399
4400                 return NT_STATUS_INVALID_PARAMETER;
4401         }
4402
4403         if (IVAL(pdata,0) > total_data) {
4404                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4405                         IVAL(pdata,0), (unsigned int)total_data));
4406                 return NT_STATUS_INVALID_PARAMETER;
4407         }
4408
4409         ctx = talloc_init("SMB_INFO_SET_EA");
4410         if (!ctx) {
4411                 return NT_STATUS_NO_MEMORY;
4412         }
4413         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4414         if (!ea_list) {
4415                 talloc_destroy(ctx);
4416                 return NT_STATUS_INVALID_PARAMETER;
4417         }
4418         status = set_ea(conn, fsp, fname, ea_list);
4419         talloc_destroy(ctx);
4420
4421         return status;
4422 }
4423
4424 /****************************************************************************
4425  Deal with SMB_SET_FILE_DISPOSITION_INFO.
4426 ****************************************************************************/
4427
4428 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4429                                 const char *pdata,
4430                                 int total_data,
4431                                 files_struct *fsp,
4432                                 const char *fname,
4433                                 SMB_STRUCT_STAT *psbuf)
4434 {
4435         NTSTATUS status = NT_STATUS_OK;
4436         BOOL delete_on_close;
4437         uint32 dosmode = 0;
4438
4439         if (total_data < 1) {
4440                 return NT_STATUS_INVALID_PARAMETER;
4441         }
4442
4443         if (fsp == NULL) {
4444                 return NT_STATUS_INVALID_HANDLE;
4445         }
4446
4447         delete_on_close = (CVAL(pdata,0) ? True : False);
4448         dosmode = dos_mode(conn, fname, psbuf);
4449
4450         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4451                 "delete_on_close = %u\n",
4452                 fsp->fsp_name,
4453                 (unsigned int)dosmode,
4454                 (unsigned int)delete_on_close ));
4455
4456         status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
4457  
4458         if (!NT_STATUS_IS_OK(status)) {
4459                 return status;
4460         }
4461
4462         /* The set is across all open files on this dev/inode pair. */
4463         if (!set_delete_on_close(fsp, delete_on_close, &current_user.ut)) {
4464                 return NT_STATUS_ACCESS_DENIED;
4465         }
4466         return NT_STATUS_OK;
4467 }
4468
4469 /****************************************************************************
4470  Deal with SMB_FILE_POSITION_INFORMATION.
4471 ****************************************************************************/
4472
4473 static NTSTATUS smb_file_position_information(connection_struct *conn,
4474                                 const char *pdata,
4475                                 int total_data,
4476                                 files_struct *fsp)
4477 {
4478         SMB_BIG_UINT position_information;
4479
4480         if (total_data < 8) {
4481                 return NT_STATUS_INVALID_PARAMETER;
4482         }
4483
4484         if (fsp == NULL) {
4485                 /* Ignore on pathname based set. */
4486                 return NT_STATUS_OK;
4487         }
4488
4489         position_information = (SMB_BIG_UINT)IVAL(pdata,0);
4490 #ifdef LARGE_SMB_OFF_T
4491         position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
4492 #else /* LARGE_SMB_OFF_T */
4493         if (IVAL(pdata,4) != 0) {
4494                 /* more than 32 bits? */
4495                 return NT_STATUS_INVALID_PARAMETER;
4496         }
4497 #endif /* LARGE_SMB_OFF_T */
4498
4499         DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
4500                 fsp->fsp_name, (double)position_information ));
4501         fsp->fh->position_information = position_information;
4502         return NT_STATUS_OK;
4503 }
4504
4505 /****************************************************************************
4506  Deal with SMB_FILE_MODE_INFORMATION.
4507 ****************************************************************************/
4508
4509 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4510                                 const char *pdata,
4511                                 int total_data)
4512 {
4513         uint32 mode;
4514
4515         if (total_data < 4) {
4516                 return NT_STATUS_INVALID_PARAMETER;
4517         }
4518         mode = IVAL(pdata,0);
4519         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4520                 return NT_STATUS_INVALID_PARAMETER;
4521         }
4522         return NT_STATUS_OK;
4523 }
4524
4525 /****************************************************************************
4526  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
4527 ****************************************************************************/
4528
4529 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
4530                                 char *inbuf,
4531                                 const char *pdata,
4532                                 int total_data,
4533                                 const char *fname)
4534 {
4535         pstring link_target;
4536         const char *newname = fname;
4537         NTSTATUS status = NT_STATUS_OK;
4538
4539         /* Set a symbolic link. */
4540         /* Don't allow this if follow links is false. */
4541
4542         if (total_data == 0) {
4543                 return NT_STATUS_INVALID_PARAMETER;
4544         }
4545
4546         if (!lp_symlinks(SNUM(conn))) {
4547                 return NT_STATUS_ACCESS_DENIED;
4548         }
4549
4550         srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), link_target, pdata,
4551                     sizeof(link_target), total_data, STR_TERMINATE);
4552
4553         /* !widelinks forces the target path to be within the share. */
4554         /* This means we can interpret the target as a pathname. */
4555         if (!lp_widelinks(SNUM(conn))) {
4556                 pstring rel_name;
4557                 char *last_dirp = NULL;
4558
4559                 if (*link_target == '/') {
4560                         /* No absolute paths allowed. */
4561                         return NT_STATUS_ACCESS_DENIED;
4562                 }
4563                 pstrcpy(rel_name, newname);
4564                 last_dirp = strrchr_m(rel_name, '/');
4565                 if (last_dirp) {
4566                         last_dirp[1] = '\0';
4567                 } else {
4568                         pstrcpy(rel_name, "./");
4569                 }
4570                 pstrcat(rel_name, link_target);
4571
4572                 status = check_name(conn, rel_name);
4573                 if (!NT_STATUS_IS_OK(status)) {
4574                         return status;
4575                 }
4576         }
4577
4578         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
4579                         newname, link_target ));
4580
4581         if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
4582                 return map_nt_error_from_unix(errno);
4583         }
4584
4585         return NT_STATUS_OK;
4586 }
4587
4588 /****************************************************************************
4589  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
4590 ****************************************************************************/
4591
4592 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
4593                                 char *inbuf,
4594                                 char *outbuf,
4595                                 const char *pdata,
4596                                 int total_data,
4597                                 pstring fname)
4598 {
4599         pstring oldname;
4600         NTSTATUS status = NT_STATUS_OK;
4601
4602         /* Set a hard link. */
4603         if (total_data == 0) {
4604                 return NT_STATUS_INVALID_PARAMETER;
4605         }
4606
4607         srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), oldname, pdata,
4608                         sizeof(oldname), total_data, STR_TERMINATE, &status);
4609         if (!NT_STATUS_IS_OK(status)) {
4610                 return status;
4611         }
4612
4613         status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, oldname);
4614         if (!NT_STATUS_IS_OK(status)) {
4615                 return status;
4616         }
4617
4618         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
4619                 fname, oldname));
4620
4621         return hardlink_internals(conn, oldname, fname);
4622 }
4623
4624 /****************************************************************************
4625  Deal with SMB_FILE_RENAME_INFORMATION.
4626 ****************************************************************************/
4627
4628 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4629                                             struct smb_request *req,
4630                                 char *inbuf,
4631                                 char *outbuf,
4632                                 const char *pdata,
4633                                 int total_data,
4634                                 files_struct *fsp,
4635                                 pstring fname)
4636 {
4637         BOOL overwrite;
4638         uint32 root_fid;
4639         uint32 len;
4640         pstring newname;
4641         pstring base_name;
4642         BOOL dest_has_wcard = False;
4643         NTSTATUS status = NT_STATUS_OK;
4644         char *p;
4645
4646         if (total_data < 13) {
4647                 return NT_STATUS_INVALID_PARAMETER;
4648         }
4649
4650         overwrite = (CVAL(pdata,0) ? True : False);
4651         root_fid = IVAL(pdata,4);
4652         len = IVAL(pdata,8);
4653
4654         if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4655                 return NT_STATUS_INVALID_PARAMETER;
4656         }
4657
4658         srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, &pdata[12],
4659                               sizeof(newname), len, 0, &status,
4660                               &dest_has_wcard);
4661         if (!NT_STATUS_IS_OK(status)) {
4662                 return status;
4663         }
4664
4665         status = resolve_dfspath_wcard(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, newname, &dest_has_wcard);
4666         if (!NT_STATUS_IS_OK(status)) {
4667                 return status;
4668         }
4669
4670         /* Check the new name has no '/' characters. */
4671         if (strchr_m(newname, '/')) {
4672                 return NT_STATUS_NOT_SUPPORTED;
4673         }
4674
4675         /* Create the base directory. */
4676         pstrcpy(base_name, fname);
4677         p = strrchr_m(base_name, '/');
4678         if (p) {
4679                 p[1] = '\0';
4680         } else {
4681                 pstrcpy(base_name, "./");
4682         }
4683         /* Append the new name. */
4684         pstrcat(base_name, newname);
4685
4686         if (fsp) {
4687                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
4688                         fsp->fnum, fsp->fsp_name, base_name ));
4689                 status = rename_internals_fsp(conn, fsp, base_name, 0, overwrite);
4690         } else {
4691                 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4692                         fname, newname ));
4693                 status = rename_internals(conn, req, fname, base_name, 0,
4694                                           overwrite, False, dest_has_wcard);
4695         }
4696
4697         return status;
4698 }
4699
4700 /****************************************************************************
4701  Deal with SMB_SET_POSIX_ACL.
4702 ****************************************************************************/
4703
4704 #if defined(HAVE_POSIX_ACLS)
4705 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
4706                                 const char *pdata,
4707                                 int total_data,
4708                                 files_struct *fsp,
4709                                 const char *fname,
4710                                 SMB_STRUCT_STAT *psbuf)
4711 {
4712         uint16 posix_acl_version;
4713         uint16 num_file_acls;
4714         uint16 num_def_acls;
4715         BOOL valid_file_acls = True;
4716         BOOL valid_def_acls = True;
4717
4718         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
4719                 return NT_STATUS_INVALID_PARAMETER;
4720         }
4721         posix_acl_version = SVAL(pdata,0);
4722         num_file_acls = SVAL(pdata,2);
4723         num_def_acls = SVAL(pdata,4);
4724
4725         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4726                 valid_file_acls = False;
4727                 num_file_acls = 0;
4728         }
4729
4730         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
4731                 valid_def_acls = False;
4732                 num_def_acls = 0;
4733         }
4734
4735         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
4736                 return NT_STATUS_INVALID_PARAMETER;
4737         }
4738
4739         if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
4740                         (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
4741                 return NT_STATUS_INVALID_PARAMETER;
4742         }
4743
4744         DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
4745                 fname ? fname : fsp->fsp_name,
4746                 (unsigned int)num_file_acls,
4747                 (unsigned int)num_def_acls));
4748
4749         if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
4750                         pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
4751                 return map_nt_error_from_unix(errno);
4752         }
4753
4754         if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
4755                         pdata + SMB_POSIX_ACL_HEADER_SIZE +
4756                         (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
4757                 return map_nt_error_from_unix(errno);
4758         }
4759         return NT_STATUS_OK;
4760 }
4761 #endif
4762
4763 /****************************************************************************
4764  Deal with SMB_SET_POSIX_LOCK.
4765 ****************************************************************************/
4766
4767 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
4768                                 char *inbuf,
4769                                 int length,
4770                                 const char *pdata,
4771                                 int total_data,
4772                                 files_struct *fsp)
4773 {
4774         SMB_BIG_UINT count;
4775         SMB_BIG_UINT offset;
4776         uint32 lock_pid;
4777         BOOL blocking_lock = False;
4778         enum brl_type lock_type;
4779         NTSTATUS status = NT_STATUS_OK;
4780
4781         if (fsp == NULL || fsp->fh->fd == -1) {
4782                 return NT_STATUS_INVALID_HANDLE;
4783         }
4784
4785         if (total_data != POSIX_LOCK_DATA_SIZE) {
4786                 return NT_STATUS_INVALID_PARAMETER;
4787         }
4788
4789         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4790                 case POSIX_LOCK_TYPE_READ:
4791                         lock_type = READ_LOCK;
4792                         break;
4793                 case POSIX_LOCK_TYPE_WRITE:
4794                         /* Return the right POSIX-mappable error code for files opened read-only. */
4795                         if (!fsp->can_write) {
4796                                 return NT_STATUS_INVALID_HANDLE;
4797                         }
4798                         lock_type = WRITE_LOCK;
4799                         break;
4800                 case POSIX_LOCK_TYPE_UNLOCK:
4801                         lock_type = UNLOCK_LOCK;
4802                         break;
4803                 default:
4804                         return NT_STATUS_INVALID_PARAMETER;
4805         }
4806
4807         if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
4808                 blocking_lock = False;
4809         } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
4810                 blocking_lock = True;
4811         } else {
4812                 return NT_STATUS_INVALID_PARAMETER;
4813         }
4814
4815         if (!lp_blocking_locks(SNUM(conn))) { 
4816                 blocking_lock = False;
4817         }
4818
4819         lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4820 #if defined(HAVE_LONGLONG)
4821         offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4822                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4823         count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4824                         ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4825 #else /* HAVE_LONGLONG */
4826         offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4827         count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4828 #endif /* HAVE_LONGLONG */
4829
4830         DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
4831                         "lock_pid = %u, count = %.0f, offset = %.0f\n",
4832                 fsp->fsp_name,
4833                 (unsigned int)lock_type,
4834                 (unsigned int)lock_pid,
4835                 (double)count,
4836                 (double)offset ));
4837
4838         if (lock_type == UNLOCK_LOCK) {
4839                 status = do_unlock(smbd_messaging_context(),
4840                                 fsp,
4841                                 lock_pid,
4842                                 count,
4843                                 offset,
4844                                 POSIX_LOCK);
4845         } else {
4846                 uint32 block_smbpid;
4847
4848                 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
4849                                                         fsp,
4850                                                         lock_pid,
4851                                                         count,
4852                                                         offset,
4853                                                         lock_type,
4854                                                         POSIX_LOCK,
4855                                                         blocking_lock,
4856                                                         &status,
4857                                                         &block_smbpid);
4858
4859                 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
4860                         /*
4861                          * A blocking lock was requested. Package up
4862                          * this smb into a queued request and push it
4863                          * onto the blocking lock queue.
4864                          */
4865                         if(push_blocking_lock_request(br_lck,
4866                                                 inbuf, length,
4867                                                 fsp,
4868                                                 -1, /* infinite timeout. */
4869                                                 0,
4870                                                 lock_pid,
4871                                                 lock_type,
4872                                                 POSIX_LOCK,
4873                                                 offset,
4874                                                 count,
4875                                                 block_smbpid)) {
4876                                 TALLOC_FREE(br_lck);
4877                                 return status;
4878                         }
4879                 }
4880                 TALLOC_FREE(br_lck);
4881         }
4882
4883         return status;
4884 }
4885
4886 /****************************************************************************
4887  Deal with SMB_INFO_STANDARD.
4888 ****************************************************************************/
4889
4890 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4891                                         const char *pdata,
4892                                         int total_data,
4893                                         files_struct *fsp,
4894                                         const char *fname,
4895                                         const SMB_STRUCT_STAT *psbuf)
4896 {
4897         struct timespec ts[2];
4898
4899         if (total_data < 12) {
4900                 return NT_STATUS_INVALID_PARAMETER;
4901         }
4902
4903         /* access time */
4904         ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
4905         /* write time */
4906         ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
4907
4908         DEBUG(10,("smb_set_info_standard: file %s\n",
4909                 fname ? fname : fsp->fsp_name ));
4910
4911         return smb_set_file_time(conn,
4912                                 fsp,
4913                                 fname,
4914                                 psbuf,
4915                                 ts);
4916 }
4917
4918 /****************************************************************************
4919  Deal with SMB_SET_FILE_BASIC_INFO.
4920 ****************************************************************************/
4921
4922 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4923                                         const char *pdata,
4924                                         int total_data,
4925                                         files_struct *fsp,
4926                                         const char *fname,
4927                                         SMB_STRUCT_STAT *psbuf)
4928 {
4929         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4930         struct timespec write_time;
4931         struct timespec changed_time;
4932         uint32 dosmode = 0;
4933         struct timespec ts[2];
4934         NTSTATUS status = NT_STATUS_OK;
4935
4936         if (total_data < 36) {
4937                 return NT_STATUS_INVALID_PARAMETER;
4938         }
4939
4940         /* Set the attributes */
4941         dosmode = IVAL(pdata,32);
4942         status = smb_set_file_dosmode(conn,
4943                                         fname,
4944                                         psbuf,
4945                                         dosmode);
4946         if (!NT_STATUS_IS_OK(status)) {
4947                 return status;
4948         }
4949
4950         /* Ignore create time at offset pdata. */
4951
4952         /* access time */
4953         ts[0] = interpret_long_date(pdata+8);
4954
4955         write_time = interpret_long_date(pdata+16);
4956         changed_time = interpret_long_date(pdata+24);
4957
4958         /* mtime */
4959         ts[1] = timespec_min(&write_time, &changed_time);
4960
4961         if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
4962                 ts[1] = write_time;
4963         }
4964
4965         /* Prefer a defined time to an undefined one. */
4966         if (null_timespec(ts[1])) {
4967                 ts[1] = null_timespec(write_time) ? changed_time : write_time;
4968         }
4969
4970         DEBUG(10,("smb_set_file_basic_info: file %s\n",
4971                 fname ? fname : fsp->fsp_name ));
4972
4973         return smb_set_file_time(conn,
4974                                 fsp,
4975                                 fname,
4976                                 psbuf,
4977                                 ts);
4978 }
4979
4980 /****************************************************************************
4981  Deal with SMB_SET_FILE_ALLOCATION_INFO.
4982 ****************************************************************************/
4983
4984 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4985                                              struct smb_request *req,
4986                                         const char *pdata,
4987                                         int total_data,
4988                                         files_struct *fsp,
4989                                         const char *fname,
4990                                         SMB_STRUCT_STAT *psbuf)
4991 {
4992         SMB_BIG_UINT allocation_size = 0;
4993         NTSTATUS status = NT_STATUS_OK;
4994         files_struct *new_fsp = NULL;
4995
4996         if (!VALID_STAT(*psbuf)) {
4997                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4998         }
4999
5000         if (total_data < 8) {
5001                 return NT_STATUS_INVALID_PARAMETER;
5002         }
5003
5004         allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5005 #ifdef LARGE_SMB_OFF_T
5006         allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5007 #else /* LARGE_SMB_OFF_T */
5008         if (IVAL(pdata,4) != 0) {
5009                 /* more than 32 bits? */
5010                 return NT_STATUS_INVALID_PARAMETER;
5011         }
5012 #endif /* LARGE_SMB_OFF_T */
5013
5014         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5015                         fname, (double)allocation_size ));
5016
5017         if (allocation_size) {
5018                 allocation_size = smb_roundup(conn, allocation_size);
5019         }
5020
5021         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5022                         fname, (double)allocation_size ));
5023
5024         if (fsp && fsp->fh->fd != -1) {
5025                 /* Open file handle. */
5026                 /* Only change if needed. */
5027                 if (allocation_size != get_file_size(*psbuf)) {
5028                         if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5029                                 return map_nt_error_from_unix(errno);
5030                         }
5031                 }
5032                 /* But always update the time. */
5033                 if (null_timespec(fsp->pending_modtime)) {
5034                         /*
5035                          * This is equivalent to a write. Ensure it's seen immediately
5036                          * if there are no pending writes.
5037                          */
5038                         set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
5039                 }
5040                 return NT_STATUS_OK;
5041         }
5042
5043         /* Pathname or stat or directory file. */
5044
5045         status = open_file_ntcreate(conn, req, fname, psbuf,
5046                                 FILE_WRITE_DATA,
5047                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5048                                 FILE_OPEN,
5049                                 0,
5050                                 FILE_ATTRIBUTE_NORMAL,
5051                                 FORCE_OPLOCK_BREAK_TO_NONE,
5052                                 NULL, &new_fsp);
5053
5054         if (!NT_STATUS_IS_OK(status)) {
5055                 /* NB. We check for open_was_deferred in the caller. */
5056                 return status;
5057         }
5058
5059         /* Only change if needed. */
5060         if (allocation_size != get_file_size(*psbuf)) {
5061                 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5062                         status = map_nt_error_from_unix(errno);
5063                         close_file(new_fsp,NORMAL_CLOSE);
5064                         return status;
5065                 }
5066         }
5067
5068         /* Changing the allocation size should set the last mod time. */
5069         /* Don't need to call set_filetime as this will be flushed on
5070          * close. */
5071
5072         fsp_set_pending_modtime(new_fsp, timespec_current());
5073
5074         close_file(new_fsp,NORMAL_CLOSE);
5075         return NT_STATUS_OK;
5076 }
5077
5078 /****************************************************************************
5079  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5080 ****************************************************************************/
5081
5082 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5083                                               struct smb_request *req,
5084                                         const char *pdata,
5085                                         int total_data,
5086                                         files_struct *fsp,
5087                                         const char *fname,
5088                                         SMB_STRUCT_STAT *psbuf)
5089 {
5090         SMB_OFF_T size;
5091
5092         if (total_data < 8) {
5093                 return NT_STATUS_INVALID_PARAMETER;
5094         }
5095
5096         size = IVAL(pdata,0);
5097 #ifdef LARGE_SMB_OFF_T
5098         size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5099 #else /* LARGE_SMB_OFF_T */
5100         if (IVAL(pdata,4) != 0) {
5101                 /* more than 32 bits? */
5102                 return NT_STATUS_INVALID_PARAMETER;
5103         }
5104 #endif /* LARGE_SMB_OFF_T */
5105         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5106                 "file %s to %.0f\n", fname, (double)size ));
5107
5108         return smb_set_file_size(conn, req,
5109                                 fsp,
5110                                 fname,
5111                                 psbuf,
5112                                 size);
5113 }
5114
5115 /****************************************************************************
5116  Allow a UNIX info mknod.
5117 ****************************************************************************/
5118
5119 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5120                                         const char *pdata,
5121                                         int total_data,
5122                                         const char *fname,
5123                                         SMB_STRUCT_STAT *psbuf)
5124 {
5125         uint32 file_type = IVAL(pdata,56);
5126 #if defined(HAVE_MAKEDEV)
5127         uint32 dev_major = IVAL(pdata,60);
5128         uint32 dev_minor = IVAL(pdata,68);
5129 #endif
5130         SMB_DEV_T dev = (SMB_DEV_T)0;
5131         uint32 raw_unixmode = IVAL(pdata,84);
5132         NTSTATUS status;
5133         mode_t unixmode;
5134
5135         if (total_data < 100) {
5136                 return NT_STATUS_INVALID_PARAMETER;
5137         }
5138
5139         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5140         if (!NT_STATUS_IS_OK(status)) {
5141                 return status;
5142         }
5143
5144 #if defined(HAVE_MAKEDEV)
5145         dev = makedev(dev_major, dev_minor);
5146 #endif
5147
5148         switch (file_type) {
5149 #if defined(S_IFIFO)
5150                 case UNIX_TYPE_FIFO:
5151                         unixmode |= S_IFIFO;
5152                         break;
5153 #endif
5154 #if defined(S_IFSOCK)
5155                 case UNIX_TYPE_SOCKET:
5156                         unixmode |= S_IFSOCK;
5157                         break;
5158 #endif
5159 #if defined(S_IFCHR)
5160                 case UNIX_TYPE_CHARDEV:
5161                         unixmode |= S_IFCHR;
5162                         break;
5163 #endif
5164 #if defined(S_IFBLK)
5165                 case UNIX_TYPE_BLKDEV:
5166                         unixmode |= S_IFBLK;
5167                         break;
5168 #endif
5169                 default:
5170                         return NT_STATUS_INVALID_PARAMETER;
5171         }
5172
5173         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5174 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5175
5176         /* Ok - do the mknod. */
5177         if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5178                 return map_nt_error_from_unix(errno);
5179         }
5180
5181         /* If any of the other "set" calls fail we
5182          * don't want to end up with a half-constructed mknod.
5183          */
5184
5185         if (lp_inherit_perms(SNUM(conn))) {
5186                 inherit_access_acl(
5187                         conn, parent_dirname(fname),
5188                         fname, unixmode);
5189         }
5190
5191         if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5192                 status = map_nt_error_from_unix(errno);
5193                 SMB_VFS_UNLINK(conn,fname);
5194                 return status;
5195         }
5196         return NT_STATUS_OK;
5197 }
5198
5199 /****************************************************************************
5200  Deal with SMB_SET_FILE_UNIX_BASIC.
5201 ****************************************************************************/
5202
5203 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5204                                         struct smb_request *req,
5205                                         const char *pdata,
5206                                         int total_data,
5207                                         files_struct *fsp,
5208                                         const char *fname,
5209                                         SMB_STRUCT_STAT *psbuf)
5210 {
5211         struct timespec ts[2];
5212         uint32 raw_unixmode;
5213         mode_t unixmode;
5214         SMB_OFF_T size = 0;
5215         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5216         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5217         NTSTATUS status = NT_STATUS_OK;
5218         BOOL delete_on_fail = False;
5219         enum perm_type ptype;
5220
5221         if (total_data < 100) {
5222                 return NT_STATUS_INVALID_PARAMETER;
5223         }
5224
5225         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5226            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5227                 size=IVAL(pdata,0); /* first 8 Bytes are size */
5228 #ifdef LARGE_SMB_OFF_T
5229                 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5230 #else /* LARGE_SMB_OFF_T */
5231                 if (IVAL(pdata,4) != 0) {
5232                         /* more than 32 bits? */
5233                         return NT_STATUS_INVALID_PARAMETER;
5234                 }
5235 #endif /* LARGE_SMB_OFF_T */
5236         }
5237
5238         ts[0] = interpret_long_date(pdata+24); /* access_time */
5239         ts[1] = interpret_long_date(pdata+32); /* modification_time */
5240         set_owner = (uid_t)IVAL(pdata,40);
5241         set_grp = (gid_t)IVAL(pdata,48);
5242         raw_unixmode = IVAL(pdata,84);
5243
5244         if (VALID_STAT(*psbuf)) {
5245                 if (S_ISDIR(psbuf->st_mode)) {
5246                         ptype = PERM_EXISTING_DIR;
5247                 } else {
5248                         ptype = PERM_EXISTING_FILE;
5249                 }
5250         } else {
5251                 ptype = PERM_NEW_FILE;
5252         }
5253
5254         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5255         if (!NT_STATUS_IS_OK(status)) {
5256                 return status;
5257         }
5258
5259         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5260 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5261                 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5262
5263         if (!VALID_STAT(*psbuf)) {
5264                 /*
5265                  * The only valid use of this is to create character and block
5266                  * devices, and named pipes. This is deprecated (IMHO) and 
5267                  * a new info level should be used for mknod. JRA.
5268                  */
5269
5270                 status = smb_unix_mknod(conn,
5271                                         pdata,
5272                                         total_data,
5273                                         fname,
5274                                         psbuf);
5275                 if (!NT_STATUS_IS_OK(status)) {
5276                         return status;
5277                 }
5278
5279                 /* Ensure we don't try and change anything else. */
5280                 raw_unixmode = SMB_MODE_NO_CHANGE;
5281                 size = get_file_size(*psbuf);
5282                 ts[0] = get_atimespec(psbuf);
5283                 ts[1] = get_mtimespec(psbuf);
5284                 /* 
5285                  * We continue here as we might want to change the 
5286                  * owner uid/gid.
5287                  */
5288                 delete_on_fail = True;
5289         }
5290
5291 #if 1
5292         /* Horrible backwards compatibility hack as an old server bug
5293          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5294          * */
5295
5296         if (!size) {
5297                 size = get_file_size(*psbuf);
5298         }
5299 #endif
5300
5301         /*
5302          * Deal with the UNIX specific mode set.
5303          */
5304
5305         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5306                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
5307                         (unsigned int)unixmode, fname ));
5308                 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
5309                         return map_nt_error_from_unix(errno);
5310                 }
5311         }
5312
5313         /*
5314          * Deal with the UNIX specific uid set.
5315          */
5316
5317         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
5318                 int ret;
5319
5320                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
5321                         (unsigned int)set_owner, fname ));
5322
5323                 if (S_ISLNK(psbuf->st_mode)) {
5324                         ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
5325                 } else {
5326                         ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
5327                 }
5328
5329                 if (ret != 0) {
5330                         status = map_nt_error_from_unix(errno);
5331                         if (delete_on_fail) {
5332                                 SMB_VFS_UNLINK(conn,fname);
5333                         }
5334                         return status;
5335                 }
5336         }
5337
5338         /*
5339          * Deal with the UNIX specific gid set.
5340          */
5341
5342         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
5343                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
5344                         (unsigned int)set_owner, fname ));
5345                 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
5346                         status = map_nt_error_from_unix(errno);
5347                         if (delete_on_fail) {
5348                                 SMB_VFS_UNLINK(conn,fname);
5349                         }
5350                         return status;
5351                 }
5352         }
5353
5354         /* Deal with any size changes. */
5355
5356         status = smb_set_file_size(conn, req,
5357                                 fsp,
5358                                 fname,
5359                                 psbuf,
5360                                 size);
5361         if (!NT_STATUS_IS_OK(status)) {
5362                 return status;
5363         }
5364
5365         /* Deal with any time changes. */
5366
5367         return smb_set_file_time(conn,
5368                                 fsp,
5369                                 fname,
5370                                 psbuf,
5371                                 ts);
5372 }
5373
5374 /****************************************************************************
5375  Deal with SMB_SET_FILE_UNIX_INFO2.
5376 ****************************************************************************/
5377
5378 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
5379                                         struct smb_request *req,
5380                                         const char *pdata,
5381                                         int total_data,
5382                                         files_struct *fsp,
5383                                         const char *fname,
5384                                         SMB_STRUCT_STAT *psbuf)
5385 {
5386         NTSTATUS status;
5387         uint32 smb_fflags;
5388         uint32 smb_fmask;
5389
5390         if (total_data < 116) {
5391                 return NT_STATUS_INVALID_PARAMETER;
5392         }
5393
5394         /* Start by setting all the fields that are common between UNIX_BASIC
5395          * and UNIX_INFO2.
5396          */
5397         status = smb_set_file_unix_basic(conn, req, pdata, total_data,
5398                                 fsp, fname, psbuf);
5399         if (!NT_STATUS_IS_OK(status)) {
5400                 return status;
5401         }
5402
5403         smb_fflags = IVAL(pdata, 108);
5404         smb_fmask = IVAL(pdata, 112);
5405
5406         /* NB: We should only attempt to alter the file flags if the client
5407          * sends a non-zero mask.
5408          */
5409         if (smb_fmask != 0) {
5410                 int stat_fflags = 0;
5411
5412                 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
5413                             &stat_fflags)) {
5414                         /* Client asked to alter a flag we don't understand. */
5415                         return NT_STATUS_INVALID_PARAMETER;
5416                 }
5417
5418                 if (fsp && fsp->fh->fd != -1) {
5419                         /* XXX: we should be  using SMB_VFS_FCHFLAGS here. */
5420                         return NT_STATUS_NOT_SUPPORTED;
5421                 } else {
5422                         if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
5423                                 return map_nt_error_from_unix(errno);
5424                         }
5425                 }
5426         }
5427
5428         /* XXX: need to add support for changing the create_time here. You
5429          * can do this for paths on Darwin with setattrlist(2). The right way
5430          * to hook this up is probably by extending the VFS utimes interface.
5431          */
5432
5433         return NT_STATUS_OK;
5434 }
5435
5436 /****************************************************************************
5437  Create a directory with POSIX semantics.
5438 ****************************************************************************/
5439
5440 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
5441                                 struct smb_request *req,
5442                                 char **ppdata,
5443                                 int total_data,
5444                                 const char *fname,
5445                                 SMB_STRUCT_STAT *psbuf,
5446                                 int *pdata_return_size)
5447 {
5448         NTSTATUS status = NT_STATUS_OK;
5449         uint32 raw_unixmode = 0;
5450         uint32 mod_unixmode = 0;
5451         mode_t unixmode = (mode_t)0;
5452         files_struct *fsp = NULL;
5453         uint16 info_level_return = 0;
5454         int info;
5455         char *pdata = *ppdata;
5456
5457         if (total_data < 18) {
5458                 return NT_STATUS_INVALID_PARAMETER;
5459         }
5460
5461         raw_unixmode = IVAL(pdata,8);
5462         /* Next 4 bytes are not yet defined. */
5463
5464         status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
5465         if (!NT_STATUS_IS_OK(status)) {
5466                 return status;
5467         }
5468
5469         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5470
5471         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
5472                 fname, (unsigned int)unixmode ));
5473
5474         status = open_directory(conn, req,
5475                                 fname,
5476                                 psbuf,
5477                                 FILE_READ_ATTRIBUTES, /* Just a stat open */
5478                                 FILE_SHARE_NONE, /* Ignored for stat opens */
5479                                 FILE_CREATE,
5480                                 0,
5481                                 mod_unixmode,
5482                                 &info,
5483                                 &fsp);
5484
5485         if (NT_STATUS_IS_OK(status)) {
5486                 close_file(fsp, NORMAL_CLOSE);
5487         }
5488
5489         info_level_return = SVAL(pdata,16);
5490  
5491         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5492                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5493         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5494                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5495         } else {
5496                 *pdata_return_size = 12;
5497         }
5498
5499         /* Realloc the data size */
5500         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5501         if (*ppdata == NULL) {
5502                 *pdata_return_size = 0;
5503                 return NT_STATUS_NO_MEMORY;
5504         }
5505         pdata = *ppdata;
5506
5507         SSVAL(pdata,0,NO_OPLOCK_RETURN);
5508         SSVAL(pdata,2,0); /* No fnum. */
5509         SIVAL(pdata,4,info); /* Was directory created. */
5510
5511         switch (info_level_return) {
5512                 case SMB_QUERY_FILE_UNIX_BASIC:
5513                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5514                         SSVAL(pdata,10,0); /* Padding. */
5515                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5516                         break;
5517                 case SMB_QUERY_FILE_UNIX_INFO2:
5518                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5519                         SSVAL(pdata,10,0); /* Padding. */
5520                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5521                         break;
5522                 default:
5523                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5524                         SSVAL(pdata,10,0); /* Padding. */
5525                         break;
5526         }
5527
5528         return status;
5529 }
5530
5531 /****************************************************************************
5532  Open/Create a file with POSIX semantics.
5533 ****************************************************************************/
5534
5535 static NTSTATUS smb_posix_open(connection_struct *conn,
5536                                struct smb_request *req,
5537                                 char **ppdata,
5538                                 int total_data,
5539                                 const char *fname,
5540                                 SMB_STRUCT_STAT *psbuf,
5541                                 int *pdata_return_size)
5542 {
5543         BOOL extended_oplock_granted = False;
5544         char *pdata = *ppdata;
5545         uint32 flags = 0;
5546         uint32 wire_open_mode = 0;
5547         uint32 raw_unixmode = 0;
5548         uint32 mod_unixmode = 0;
5549         uint32 create_disp = 0;
5550         uint32 access_mask = 0;
5551         uint32 create_options = 0;
5552         NTSTATUS status = NT_STATUS_OK;
5553         mode_t unixmode = (mode_t)0;
5554         files_struct *fsp = NULL;
5555         int oplock_request = 0;
5556         int info = 0;
5557         uint16 info_level_return = 0;
5558
5559         if (total_data < 18) {
5560                 return NT_STATUS_INVALID_PARAMETER;
5561         }
5562
5563         flags = IVAL(pdata,0);
5564         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
5565         if (oplock_request) {
5566                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
5567         }
5568
5569         wire_open_mode = IVAL(pdata,4);
5570
5571         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
5572                 return smb_posix_mkdir(conn, req,
5573                                         ppdata,
5574                                         total_data,
5575                                         fname,
5576                                         psbuf,
5577                                         pdata_return_size);
5578         }
5579
5580         switch (wire_open_mode & SMB_ACCMODE) {
5581                 case SMB_O_RDONLY:
5582                         access_mask = FILE_READ_DATA;
5583                         break;
5584                 case SMB_O_WRONLY:
5585                         access_mask = FILE_WRITE_DATA;
5586                         break;
5587                 case SMB_O_RDWR:
5588                         access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
5589                         break;
5590                 default:
5591                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
5592                                 (unsigned int)wire_open_mode ));
5593                         return NT_STATUS_INVALID_PARAMETER;
5594         }
5595
5596         wire_open_mode &= ~SMB_ACCMODE;
5597
5598         if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
5599                 create_disp = FILE_CREATE;
5600         } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
5601                 create_disp = FILE_OVERWRITE_IF;
5602         } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
5603                 create_disp = FILE_OPEN_IF;
5604         } else {
5605                 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
5606                         (unsigned int)wire_open_mode ));
5607                 return NT_STATUS_INVALID_PARAMETER;
5608         }
5609
5610         raw_unixmode = IVAL(pdata,8);
5611         /* Next 4 bytes are not yet defined. */
5612
5613         status = unix_perms_from_wire(conn,
5614                                 psbuf,
5615                                 raw_unixmode,
5616                                 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
5617                                 &unixmode);
5618
5619         if (!NT_STATUS_IS_OK(status)) {
5620                 return status;
5621         }
5622
5623         mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
5624
5625         if (wire_open_mode & SMB_O_SYNC) {
5626                 create_options |= FILE_WRITE_THROUGH;
5627         }
5628         if (wire_open_mode & SMB_O_APPEND) {
5629                 access_mask |= FILE_APPEND_DATA;
5630         }
5631         if (wire_open_mode & SMB_O_DIRECT) {
5632                 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
5633         }
5634
5635         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
5636                 fname,
5637                 (unsigned int)wire_open_mode,
5638                 (unsigned int)unixmode ));
5639
5640         status = open_file_ntcreate(conn, req,
5641                                 fname,
5642                                 psbuf,
5643                                 access_mask,
5644                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5645                                 create_disp,
5646                                 0,              /* no create options yet. */
5647                                 mod_unixmode,
5648                                 oplock_request,
5649                                 &info,
5650                                 &fsp);
5651
5652         if (!NT_STATUS_IS_OK(status)) {
5653                 return status;
5654         }
5655
5656         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
5657                 extended_oplock_granted = True;
5658         }
5659
5660         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
5661                 extended_oplock_granted = True;
5662         }
5663
5664         info_level_return = SVAL(pdata,16);
5665  
5666         /* Allocate the correct return size. */
5667
5668         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
5669                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
5670         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
5671                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
5672         } else {
5673                 *pdata_return_size = 12;
5674         }
5675
5676         /* Realloc the data size */
5677         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
5678         if (*ppdata == NULL) {
5679                 close_file(fsp,ERROR_CLOSE);
5680                 *pdata_return_size = 0;
5681                 return NT_STATUS_NO_MEMORY;
5682         }
5683         pdata = *ppdata;
5684
5685         if (extended_oplock_granted) {
5686                 if (flags & REQUEST_BATCH_OPLOCK) {
5687                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
5688                 } else {
5689                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
5690                 }
5691         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
5692                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
5693         } else {
5694                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
5695         }
5696
5697         SSVAL(pdata,2,fsp->fnum);
5698         SIVAL(pdata,4,info); /* Was file created etc. */
5699
5700         switch (info_level_return) {
5701                 case SMB_QUERY_FILE_UNIX_BASIC:
5702                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
5703                         SSVAL(pdata,10,0); /* padding. */
5704                         store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
5705                         break;
5706                 case SMB_QUERY_FILE_UNIX_INFO2:
5707                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
5708                         SSVAL(pdata,10,0); /* padding. */
5709                         store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
5710                         break;
5711                 default:
5712                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
5713                         SSVAL(pdata,10,0); /* padding. */
5714                         break;
5715         }
5716         return NT_STATUS_OK;
5717 }
5718
5719 /****************************************************************************
5720  Delete a file with POSIX semantics.
5721 ****************************************************************************/
5722
5723 static NTSTATUS smb_posix_unlink(connection_struct *conn,
5724                                  struct smb_request *req,
5725                                 const char *pdata,
5726                                 int total_data,
5727                                 const char *fname,
5728                                 SMB_STRUCT_STAT *psbuf)
5729 {
5730         NTSTATUS status = NT_STATUS_OK;
5731         files_struct *fsp = NULL;
5732         uint16 flags = 0;
5733         char del = 1;
5734         int info = 0;
5735         int i;
5736         struct share_mode_lock *lck = NULL;
5737
5738         if (total_data < 2) {
5739                 return NT_STATUS_INVALID_PARAMETER;
5740         }
5741
5742         flags = SVAL(pdata,0);
5743
5744         if (!VALID_STAT(*psbuf)) {
5745                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5746         }
5747
5748         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
5749                         !VALID_STAT_OF_DIR(*psbuf)) {
5750                 return NT_STATUS_NOT_A_DIRECTORY;
5751         }
5752
5753         DEBUG(10,("smb_posix_unlink: %s %s\n",
5754                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
5755                 fname));
5756
5757         if (VALID_STAT_OF_DIR(*psbuf)) {
5758                 status = open_directory(conn, req,
5759                                         fname,
5760                                         psbuf,
5761                                         DELETE_ACCESS,
5762                                         FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5763                                         FILE_OPEN,
5764                                         0,
5765                                         FILE_FLAG_POSIX_SEMANTICS|0777,
5766                                         &info,
5767                                         &fsp);
5768         } else {
5769
5770                 status = open_file_ntcreate(conn, req,
5771                                 fname,
5772                                 psbuf,
5773                                 DELETE_ACCESS,
5774                                 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5775                                 FILE_OPEN,
5776                                 0,
5777                                 FILE_FLAG_POSIX_SEMANTICS|0777,
5778                                 0, /* No oplock, but break existing ones. */
5779                                 &info,
5780                                 &fsp);
5781         }
5782
5783         if (!NT_STATUS_IS_OK(status)) {
5784                 return status;
5785         }
5786
5787         /*
5788          * Don't lie to client. If we can't really delete due to
5789          * non-POSIX opens return SHARING_VIOLATION.
5790          */
5791
5792         lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
5793         if (lck == NULL) {
5794                 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
5795                         "lock for file %s\n", fsp->fsp_name));
5796                 close_file(fsp, NORMAL_CLOSE);
5797                 return NT_STATUS_INVALID_PARAMETER;
5798         }
5799
5800         /*
5801          * See if others still have the file open. If this is the case, then
5802          * don't delete. If all opens are POSIX delete we can set the delete
5803          * on close disposition.
5804          */
5805         for (i=0; i<lck->num_share_modes; i++) {
5806                 struct share_mode_entry *e = &lck->share_modes[i];
5807                 if (is_valid_share_mode_entry(e)) {
5808                         if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
5809                                 continue;
5810                         }
5811                         /* Fail with sharing violation. */
5812                         close_file(fsp, NORMAL_CLOSE);
5813                         TALLOC_FREE(lck);
5814                         return NT_STATUS_SHARING_VIOLATION;
5815                 }
5816         }
5817
5818         /*
5819          * Set the delete on close.
5820          */
5821         status = smb_set_file_disposition_info(conn,
5822                                                 &del,
5823                                                 1,
5824                                                 fsp,
5825                                                 fname,
5826                                                 psbuf);
5827
5828         if (!NT_STATUS_IS_OK(status)) {
5829                 close_file(fsp, NORMAL_CLOSE);
5830                 TALLOC_FREE(lck);
5831                 return status;
5832         }
5833         TALLOC_FREE(lck);
5834         return close_file(fsp, NORMAL_CLOSE);
5835 }
5836
5837 /****************************************************************************
5838  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
5839 ****************************************************************************/
5840
5841 static int call_trans2setfilepathinfo(connection_struct *conn,
5842                                       struct smb_request *req,
5843                                       char *inbuf, char *outbuf, int length,
5844                                       int bufsize,
5845                                         unsigned int tran_call,
5846                                         char **pparams, int total_params, char **ppdata, int total_data,
5847                                         unsigned int max_data_bytes)
5848 {
5849         char *params = *pparams;
5850         char *pdata = *ppdata;
5851         uint16 info_level;
5852         SMB_STRUCT_STAT sbuf;
5853         pstring fname;
5854         files_struct *fsp = NULL;
5855         NTSTATUS status = NT_STATUS_OK;
5856         int data_return_size = 0;
5857
5858         if (!params) {
5859                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5860         }
5861
5862         ZERO_STRUCT(sbuf);
5863
5864         if (tran_call == TRANSACT2_SETFILEINFO) {
5865                 if (total_params < 4) {
5866                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5867                 }
5868
5869                 fsp = file_fsp(SVAL(params,0));
5870                 info_level = SVAL(params,2);    
5871
5872                 if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
5873                         /*
5874                          * This is actually a SETFILEINFO on a directory
5875                          * handle (returned from an NT SMB). NT5.0 seems
5876                          * to do this call. JRA.
5877                          */
5878                         pstrcpy(fname, fsp->fsp_name);
5879                         if (INFO_LEVEL_IS_UNIX(info_level)) {
5880                                 /* Always do lstat for UNIX calls. */
5881                                 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
5882                                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
5883                                         return UNIXERROR(ERRDOS,ERRbadpath);
5884                                 }
5885                         } else {
5886                                 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
5887                                         DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
5888                                         return UNIXERROR(ERRDOS,ERRbadpath);
5889                                 }
5890                         }
5891                 } else if (fsp && fsp->print_file) {
5892                         /*
5893                          * Doing a DELETE_ON_CLOSE should cancel a print job.
5894                          */
5895                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
5896                                 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
5897
5898                                 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
5899         
5900                                 SSVAL(params,0,0);
5901                                 send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
5902                                 return(-1);
5903                         } else
5904                                 return (UNIXERROR(ERRDOS,ERRbadpath));
5905             } else {
5906                         /*
5907                          * Original code - this is an open file.
5908                          */
5909                         CHECK_FSP(fsp,conn);
5910
5911                         pstrcpy(fname, fsp->fsp_name);
5912
5913                         if (SMB_VFS_FSTAT(fsp, fsp->fh->fd, &sbuf) != 0) {
5914                                 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
5915                                 return(UNIXERROR(ERRDOS,ERRbadfid));
5916                         }
5917                 }
5918         } else {
5919                 /* set path info */
5920                 if (total_params < 7) {
5921                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
5922                 }
5923
5924                 info_level = SVAL(params,0);    
5925                 srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, &params[6],
5926                                 sizeof(fname), total_params - 6, STR_TERMINATE,
5927                                 &status);
5928                 if (!NT_STATUS_IS_OK(status)) {
5929                         return ERROR_NT(status);
5930                 }
5931
5932                 status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
5933                 if (!NT_STATUS_IS_OK(status)) {
5934                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5935                                 return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
5936                         }
5937                         return ERROR_NT(status);
5938                 }
5939
5940                 status = unix_convert(conn, fname, False, NULL, &sbuf);
5941                 if (!NT_STATUS_IS_OK(status)) {
5942                         return ERROR_NT(status);
5943                 }
5944
5945                 status = check_name(conn, fname);
5946                 if (!NT_STATUS_IS_OK(status)) {
5947                         return ERROR_NT(status);
5948                 }
5949
5950                 if (INFO_LEVEL_IS_UNIX(info_level)) {
5951                         /*
5952                          * For CIFS UNIX extensions the target name may not exist.
5953                          */
5954
5955                         /* Always do lstat for UNIX calls. */
5956                         SMB_VFS_LSTAT(conn,fname,&sbuf);
5957
5958                 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
5959                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
5960                         return UNIXERROR(ERRDOS,ERRbadpath);
5961                 }
5962         }
5963
5964         if (!CAN_WRITE(conn)) {
5965                 return ERROR_DOS(ERRSRV,ERRaccess);
5966         }
5967
5968         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5969                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5970         }
5971
5972         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
5973                 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
5974
5975         /* Realloc the parameter size */
5976         *pparams = (char *)SMB_REALLOC(*pparams,2);
5977         if (*pparams == NULL) {
5978                 return ERROR_NT(NT_STATUS_NO_MEMORY);
5979         }
5980         params = *pparams;
5981
5982         SSVAL(params,0,0);
5983
5984         if (fsp && !null_timespec(fsp->pending_modtime)) {
5985                 /* the pending modtime overrides the current modtime */
5986                 set_mtimespec(&sbuf, fsp->pending_modtime);
5987         }
5988
5989         switch (info_level) {
5990
5991                 case SMB_INFO_STANDARD:
5992                 {
5993                         status = smb_set_info_standard(conn,
5994                                         pdata,
5995                                         total_data,
5996                                         fsp,
5997                                         fname,
5998                                         &sbuf);
5999                         break;
6000                 }
6001
6002                 case SMB_INFO_SET_EA:
6003                 {
6004                         status = smb_info_set_ea(conn,
6005                                                 pdata,
6006                                                 total_data,
6007                                                 fsp,
6008                                                 fname);
6009                         break;
6010                 }
6011
6012                 case SMB_SET_FILE_BASIC_INFO:
6013                 case SMB_FILE_BASIC_INFORMATION:
6014                 {
6015                         status = smb_set_file_basic_info(conn,
6016                                                         pdata,
6017                                                         total_data,
6018                                                         fsp,
6019                                                         fname,
6020                                                         &sbuf);
6021                         break;
6022                 }
6023
6024                 case SMB_FILE_ALLOCATION_INFORMATION:
6025                 case SMB_SET_FILE_ALLOCATION_INFO:
6026                 {
6027                         status = smb_set_file_allocation_info(conn, req,
6028                                                                 pdata,
6029                                                                 total_data,
6030                                                                 fsp,
6031                                                                 fname,
6032                                                                 &sbuf);
6033                         break;
6034                 }
6035
6036                 case SMB_FILE_END_OF_FILE_INFORMATION:
6037                 case SMB_SET_FILE_END_OF_FILE_INFO:
6038                 {
6039                         status = smb_set_file_end_of_file_info(conn, req,
6040                                                                 pdata,
6041                                                                 total_data,
6042                                                                 fsp,
6043                                                                 fname,
6044                                                                 &sbuf);
6045                         break;
6046                 }
6047
6048                 case SMB_FILE_DISPOSITION_INFORMATION:
6049                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6050                 {
6051 #if 0
6052                         /* JRA - We used to just ignore this on a path ? 
6053                          * Shouldn't this be invalid level on a pathname
6054                          * based call ?
6055                          */
6056                         if (tran_call != TRANSACT2_SETFILEINFO) {
6057                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6058                         }
6059 #endif
6060                         status = smb_set_file_disposition_info(conn,
6061                                                 pdata,
6062                                                 total_data,
6063                                                 fsp,
6064                                                 fname,
6065                                                 &sbuf);
6066                         break;
6067                 }
6068
6069                 case SMB_FILE_POSITION_INFORMATION:
6070                 {
6071                         status = smb_file_position_information(conn,
6072                                                 pdata,
6073                                                 total_data,
6074                                                 fsp);
6075                         break;
6076                 }
6077
6078                 /* From tridge Samba4 : 
6079                  * MODE_INFORMATION in setfileinfo (I have no
6080                  * idea what "mode information" on a file is - it takes a value of 0,
6081                  * 2, 4 or 6. What could it be?).
6082                  */
6083
6084                 case SMB_FILE_MODE_INFORMATION:
6085                 {
6086                         status = smb_file_mode_information(conn,
6087                                                 pdata,
6088                                                 total_data);
6089                         break;
6090                 }
6091
6092                 /*
6093                  * CIFS UNIX extensions.
6094                  */
6095
6096                 case SMB_SET_FILE_UNIX_BASIC:
6097                 {
6098                         status = smb_set_file_unix_basic(conn, req,
6099                                                         pdata,
6100                                                         total_data,
6101                                                         fsp,
6102                                                         fname,
6103                                                         &sbuf);
6104                         break;
6105                 }
6106
6107                 case SMB_SET_FILE_UNIX_INFO2:
6108                 {
6109                         status = smb_set_file_unix_info2(conn, req,
6110                                                         pdata,
6111                                                         total_data,
6112                                                         fsp,
6113                                                         fname,
6114                                                         &sbuf);
6115                         break;
6116                 }
6117
6118                 case SMB_SET_FILE_UNIX_LINK:
6119                 {
6120                         if (tran_call != TRANSACT2_SETPATHINFO) {
6121                                 /* We must have a pathname for this. */
6122                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6123                         }
6124                         status = smb_set_file_unix_link(conn,
6125                                                 inbuf,
6126                                                 pdata,
6127                                                 total_data,
6128                                                 fname);
6129                         break;
6130                 }
6131
6132                 case SMB_SET_FILE_UNIX_HLINK:
6133                 {
6134                         if (tran_call != TRANSACT2_SETPATHINFO) {
6135                                 /* We must have a pathname for this. */
6136                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6137                         }
6138                         status = smb_set_file_unix_hlink(conn,
6139                                                 inbuf,
6140                                                 outbuf,
6141                                                 pdata,
6142                                                 total_data,
6143                                                 fname);
6144                         break;
6145                 }
6146
6147                 case SMB_FILE_RENAME_INFORMATION:
6148                 {
6149                         status = smb_file_rename_information(conn, req,
6150                                                         inbuf,
6151                                                         outbuf,
6152                                                         pdata,
6153                                                         total_data,
6154                                                         fsp,
6155                                                         fname);
6156                         break;
6157                 }
6158
6159 #if defined(HAVE_POSIX_ACLS)
6160                 case SMB_SET_POSIX_ACL:
6161                 {
6162                         status = smb_set_posix_acl(conn,
6163                                                 pdata,
6164                                                 total_data,
6165                                                 fsp,
6166                                                 fname,
6167                                                 &sbuf);
6168                         break;
6169                 }
6170 #endif
6171
6172                 case SMB_SET_POSIX_LOCK:
6173                 {
6174                         if (tran_call != TRANSACT2_SETFILEINFO) {
6175                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6176                         }
6177                         status = smb_set_posix_lock(conn,
6178                                                 inbuf,
6179                                                 length,
6180                                                 pdata,
6181                                                 total_data,
6182                                                 fsp);
6183                         break;
6184                 }
6185
6186                 case SMB_POSIX_PATH_OPEN:
6187                 {
6188                         if (tran_call != TRANSACT2_SETPATHINFO) {
6189                                 /* We must have a pathname for this. */
6190                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6191                         }
6192
6193                         status = smb_posix_open(conn, req,
6194                                                 ppdata,
6195                                                 total_data,
6196                                                 fname,
6197                                                 &sbuf,
6198                                                 &data_return_size);
6199                         break;
6200                 }
6201
6202                 case SMB_POSIX_PATH_UNLINK:
6203                 {
6204                         if (tran_call != TRANSACT2_SETPATHINFO) {
6205                                 /* We must have a pathname for this. */
6206                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6207                         }
6208
6209                         status = smb_posix_unlink(conn, req,
6210                                                 pdata,
6211                                                 total_data,
6212                                                 fname,
6213                                                 &sbuf);
6214                         break;
6215                 }
6216
6217                 default:
6218                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6219         }
6220
6221         
6222         if (!NT_STATUS_IS_OK(status)) {
6223                 if (open_was_deferred(SVAL(inbuf,smb_mid))) {
6224                         /* We have re-scheduled this call. */
6225                         return -1;
6226                 }
6227                 if (blocking_lock_was_deferred(SVAL(inbuf,smb_mid))) {
6228                         /* We have re-scheduled this call. */
6229                         return -1;
6230                 }
6231                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6232                         return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
6233                 }
6234                 return ERROR_NT(status);
6235         }
6236
6237         SSVAL(params,0,0);
6238         send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
6239   
6240         return -1;
6241 }
6242
6243 /****************************************************************************
6244  Reply to a TRANS2_MKDIR (make directory with extended attributes).
6245 ****************************************************************************/
6246
6247 static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6248                                         char **pparams, int total_params, char **ppdata, int total_data,
6249                                         unsigned int max_data_bytes)
6250 {
6251         char *params = *pparams;
6252         char *pdata = *ppdata;
6253         pstring directory;
6254         SMB_STRUCT_STAT sbuf;
6255         NTSTATUS status = NT_STATUS_OK;
6256         struct ea_list *ea_list = NULL;
6257
6258         if (!CAN_WRITE(conn))
6259                 return ERROR_DOS(ERRSRV,ERRaccess);
6260
6261         if (total_params < 5) {
6262                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6263         }
6264
6265         srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory, &params[4],
6266                         sizeof(directory), total_params - 4, STR_TERMINATE,
6267                         &status);
6268         if (!NT_STATUS_IS_OK(status)) {
6269                 return ERROR_NT(status);
6270         }
6271
6272         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
6273
6274         status = unix_convert(conn, directory, False, NULL, &sbuf);
6275         if (!NT_STATUS_IS_OK(status)) {
6276                 return ERROR_NT(status);
6277         }
6278
6279         status = check_name(conn, directory);
6280         if (!NT_STATUS_IS_OK(status)) {
6281                 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
6282                 return ERROR_NT(status);
6283         }
6284
6285         /* Any data in this call is an EA list. */
6286         if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
6287                 return ERROR_NT(NT_STATUS_EAS_NOT_SUPPORTED);
6288         }
6289
6290         /*
6291          * OS/2 workplace shell seems to send SET_EA requests of "null"
6292          * length (4 bytes containing IVAL 4).
6293          * They seem to have no effect. Bug #3212. JRA.
6294          */
6295
6296         if (total_data != 4) {
6297                 if (total_data < 10) {
6298                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6299                 }
6300
6301                 if (IVAL(pdata,0) > total_data) {
6302                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
6303                                 IVAL(pdata,0), (unsigned int)total_data));
6304                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6305                 }
6306
6307                 ea_list = read_ea_list(tmp_talloc_ctx(), pdata + 4,
6308                                        total_data - 4);
6309                 if (!ea_list) {
6310                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6311                 }
6312         } else if (IVAL(pdata,0) != 4) {
6313                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6314         }
6315
6316         status = create_directory(conn, directory);
6317
6318         if (!NT_STATUS_IS_OK(status)) {
6319                 return ERROR_NT(status);
6320         }
6321   
6322         /* Try and set any given EA. */
6323         if (ea_list) {
6324                 status = set_ea(conn, NULL, directory, ea_list);
6325                 if (!NT_STATUS_IS_OK(status)) {
6326                         return ERROR_NT(status);
6327                 }
6328         }
6329
6330         /* Realloc the parameter and data sizes */
6331         *pparams = (char *)SMB_REALLOC(*pparams,2);
6332         if(*pparams == NULL) {
6333                 return ERROR_NT(NT_STATUS_NO_MEMORY);
6334         }
6335         params = *pparams;
6336
6337         SSVAL(params,0,0);
6338
6339         send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
6340   
6341         return(-1);
6342 }
6343
6344 /****************************************************************************
6345  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
6346  We don't actually do this - we just send a null response.
6347 ****************************************************************************/
6348
6349 static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6350                                         char **pparams, int total_params, char **ppdata, int total_data,
6351                                         unsigned int max_data_bytes)
6352 {
6353         static uint16 fnf_handle = 257;
6354         char *params = *pparams;
6355         uint16 info_level;
6356
6357         if (total_params < 6) {
6358                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6359         }
6360
6361         info_level = SVAL(params,4);
6362         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
6363
6364         switch (info_level) {
6365                 case 1:
6366                 case 2:
6367                         break;
6368                 default:
6369                         return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6370         }
6371
6372         /* Realloc the parameter and data sizes */
6373         *pparams = (char *)SMB_REALLOC(*pparams,6);
6374         if (*pparams == NULL) {
6375                 return ERROR_NT(NT_STATUS_NO_MEMORY);
6376         }
6377         params = *pparams;
6378
6379         SSVAL(params,0,fnf_handle);
6380         SSVAL(params,2,0); /* No changes */
6381         SSVAL(params,4,0); /* No EA errors */
6382
6383         fnf_handle++;
6384
6385         if(fnf_handle == 0)
6386                 fnf_handle = 257;
6387
6388         send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
6389   
6390         return(-1);
6391 }
6392
6393 /****************************************************************************
6394  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
6395  changes). Currently this does nothing.
6396 ****************************************************************************/
6397
6398 static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
6399                                         char **pparams, int total_params, char **ppdata, int total_data,
6400                                         unsigned int max_data_bytes)
6401 {
6402         char *params = *pparams;
6403
6404         DEBUG(3,("call_trans2findnotifynext\n"));
6405
6406         /* Realloc the parameter and data sizes */
6407         *pparams = (char *)SMB_REALLOC(*pparams,4);
6408         if (*pparams == NULL) {
6409                 return ERROR_NT(NT_STATUS_NO_MEMORY);
6410         }
6411         params = *pparams;
6412
6413         SSVAL(params,0,0); /* No changes */
6414         SSVAL(params,2,0); /* No EA errors */
6415
6416         send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
6417   
6418         return(-1);
6419 }
6420
6421 /****************************************************************************
6422  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
6423 ****************************************************************************/
6424
6425 static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6426                                         char **pparams, int total_params, char **ppdata, int total_data,
6427                                         unsigned int max_data_bytes)
6428 {
6429         char *params = *pparams;
6430         pstring pathname;
6431         int reply_size = 0;
6432         int max_referral_level;
6433         NTSTATUS status = NT_STATUS_OK;
6434
6435         DEBUG(10,("call_trans2getdfsreferral\n"));
6436
6437         if (total_params < 3) {
6438                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6439         }
6440
6441         max_referral_level = SVAL(params,0);
6442
6443         if(!lp_host_msdfs())
6444                 return ERROR_DOS(ERRDOS,ERRbadfunc);
6445
6446         srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pathname, &params[2],
6447                     sizeof(pathname), total_params - 2, STR_TERMINATE);
6448         if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
6449                 return ERROR_NT(status);
6450     
6451         SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
6452         send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
6453
6454         return(-1);
6455 }
6456
6457 #define LMCAT_SPL       0x53
6458 #define LMFUNC_GETJOBID 0x60
6459
6460 /****************************************************************************
6461  Reply to a TRANS2_IOCTL - used for OS/2 printing.
6462 ****************************************************************************/
6463
6464 static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf, int length, int bufsize,
6465                                         char **pparams, int total_params, char **ppdata, int total_data,
6466                                         unsigned int max_data_bytes)
6467 {
6468         char *pdata = *ppdata;
6469         files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv15));
6470
6471         /* check for an invalid fid before proceeding */
6472         
6473         if (!fsp)                                
6474                 return(ERROR_DOS(ERRDOS,ERRbadfid));  
6475
6476         if ((SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6477                         (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6478                 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
6479                 if (*ppdata == NULL) {
6480                         return ERROR_NT(NT_STATUS_NO_MEMORY);
6481                 }
6482                 pdata = *ppdata;
6483
6484                 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
6485                         CAN ACCEPT THIS IN UNICODE. JRA. */
6486
6487                 SSVAL(pdata,0,fsp->rap_print_jobid);                     /* Job number */
6488                 srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
6489                 srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
6490                 send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
6491                 return(-1);
6492         } else {
6493                 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
6494                 return ERROR_DOS(ERRSRV,ERRerror);
6495         }
6496 }
6497
6498 /****************************************************************************
6499  Reply to a SMBfindclose (stop trans2 directory search).
6500 ****************************************************************************/
6501
6502 int reply_findclose(connection_struct *conn,
6503                     char *inbuf,char *outbuf,int length,int bufsize)
6504 {
6505         int outsize = 0;
6506         int dptr_num=SVALS(inbuf,smb_vwv0);
6507         START_PROFILE(SMBfindclose);
6508
6509         DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
6510
6511         dptr_close(&dptr_num);
6512
6513         outsize = set_message(inbuf, outbuf,0,0,False);
6514
6515         DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
6516
6517         END_PROFILE(SMBfindclose);
6518         return(outsize);
6519 }
6520
6521 /****************************************************************************
6522  Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
6523 ****************************************************************************/
6524
6525 int reply_findnclose(connection_struct *conn, 
6526                      char *inbuf,char *outbuf,int length,int bufsize)
6527 {
6528         int outsize = 0;
6529         int dptr_num= -1;
6530         START_PROFILE(SMBfindnclose);
6531         
6532         dptr_num = SVAL(inbuf,smb_vwv0);
6533
6534         DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
6535
6536         /* We never give out valid handles for a 
6537            findnotifyfirst - so any dptr_num is ok here. 
6538            Just ignore it. */
6539
6540         outsize = set_message(inbuf, outbuf,0,0,False);
6541
6542         DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
6543
6544         END_PROFILE(SMBfindnclose);
6545         return(outsize);
6546 }
6547
6548 static int handle_trans2(connection_struct *conn, struct smb_request *req,
6549                          struct trans_state *state,
6550                          char *inbuf, char *outbuf, int size, int bufsize)
6551 {
6552         int outsize;
6553
6554         if (Protocol >= PROTOCOL_NT1) {
6555                 SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
6556         }
6557
6558         /* Now we must call the relevant TRANS2 function */
6559         switch(state->call)  {
6560         case TRANSACT2_OPEN:
6561         {
6562                 START_PROFILE(Trans2_open);
6563                 outsize = call_trans2open(
6564                         conn, req, inbuf, outbuf, bufsize,
6565                         &state->param, state->total_param,
6566                         &state->data, state->total_data,
6567                         state->max_data_return);
6568                 END_PROFILE(Trans2_open);
6569                 break;
6570         }
6571
6572         case TRANSACT2_FINDFIRST:
6573         {
6574                 START_PROFILE(Trans2_findfirst);
6575                 outsize = call_trans2findfirst(
6576                         conn, inbuf, outbuf, bufsize,
6577                         &state->param, state->total_param,
6578                         &state->data, state->total_data,
6579                         state->max_data_return);
6580                 END_PROFILE(Trans2_findfirst);
6581                 break;
6582         }
6583
6584         case TRANSACT2_FINDNEXT:
6585         {
6586                 START_PROFILE(Trans2_findnext);
6587                 outsize = call_trans2findnext(
6588                         conn, inbuf, outbuf, size, bufsize, 
6589                         &state->param, state->total_param,
6590                         &state->data, state->total_data,
6591                         state->max_data_return);
6592                 END_PROFILE(Trans2_findnext);
6593                 break;
6594         }
6595
6596         case TRANSACT2_QFSINFO:
6597         {
6598                 START_PROFILE(Trans2_qfsinfo);
6599                 outsize = call_trans2qfsinfo(
6600                         conn, inbuf, outbuf, size, bufsize,
6601                         &state->param, state->total_param,
6602                         &state->data, state->total_data,
6603                         state->max_data_return);
6604                 END_PROFILE(Trans2_qfsinfo);
6605             break;
6606         }
6607
6608         case TRANSACT2_SETFSINFO:
6609         {
6610                 START_PROFILE(Trans2_setfsinfo);
6611                 outsize = call_trans2setfsinfo(
6612                         conn, inbuf, outbuf, size, bufsize, 
6613                         &state->param, state->total_param,
6614                         &state->data, state->total_data,
6615                         state->max_data_return);
6616                 END_PROFILE(Trans2_setfsinfo);
6617                 break;
6618         }
6619
6620         case TRANSACT2_QPATHINFO:
6621         case TRANSACT2_QFILEINFO:
6622         {
6623                 START_PROFILE(Trans2_qpathinfo);
6624                 outsize = call_trans2qfilepathinfo(
6625                         conn, inbuf, outbuf, size, bufsize, state->call,
6626                         &state->param, state->total_param,
6627                         &state->data, state->total_data,
6628                         state->max_data_return);
6629                 END_PROFILE(Trans2_qpathinfo);
6630                 break;
6631         }
6632
6633         case TRANSACT2_SETPATHINFO:
6634         case TRANSACT2_SETFILEINFO:
6635         {
6636                 START_PROFILE(Trans2_setpathinfo);
6637                 outsize = call_trans2setfilepathinfo(
6638                         conn, req, inbuf, outbuf, size, bufsize, state->call,
6639                         &state->param, state->total_param,
6640                         &state->data, state->total_data,
6641                         state->max_data_return);
6642                 END_PROFILE(Trans2_setpathinfo);
6643                 break;
6644         }
6645
6646         case TRANSACT2_FINDNOTIFYFIRST:
6647         {
6648                 START_PROFILE(Trans2_findnotifyfirst);
6649                 outsize = call_trans2findnotifyfirst(
6650                         conn, inbuf, outbuf, size, bufsize, 
6651                         &state->param, state->total_param,
6652                         &state->data, state->total_data,
6653                         state->max_data_return);
6654                 END_PROFILE(Trans2_findnotifyfirst);
6655                 break;
6656         }
6657
6658         case TRANSACT2_FINDNOTIFYNEXT:
6659         {
6660                 START_PROFILE(Trans2_findnotifynext);
6661                 outsize = call_trans2findnotifynext(
6662                         conn, inbuf, outbuf, size, bufsize, 
6663                         &state->param, state->total_param,
6664                         &state->data, state->total_data,
6665                         state->max_data_return);
6666                 END_PROFILE(Trans2_findnotifynext);
6667                 break;
6668         }
6669
6670         case TRANSACT2_MKDIR:
6671         {
6672                 START_PROFILE(Trans2_mkdir);
6673                 outsize = call_trans2mkdir(
6674                         conn, inbuf, outbuf, size, bufsize,
6675                         &state->param, state->total_param,
6676                         &state->data, state->total_data,
6677                         state->max_data_return);
6678                 END_PROFILE(Trans2_mkdir);
6679                 break;
6680         }
6681
6682         case TRANSACT2_GET_DFS_REFERRAL:
6683         {
6684                 START_PROFILE(Trans2_get_dfs_referral);
6685                 outsize = call_trans2getdfsreferral(
6686                         conn, inbuf, outbuf, size, bufsize,
6687                         &state->param, state->total_param,
6688                         &state->data, state->total_data,
6689                         state->max_data_return);
6690                 END_PROFILE(Trans2_get_dfs_referral);
6691                 break;
6692         }
6693
6694         case TRANSACT2_IOCTL:
6695         {
6696                 START_PROFILE(Trans2_ioctl);
6697                 outsize = call_trans2ioctl(
6698                         conn, inbuf, outbuf, size, bufsize,
6699                         &state->param, state->total_param,
6700                         &state->data, state->total_data,
6701                         state->max_data_return);
6702                 END_PROFILE(Trans2_ioctl);
6703                 break;
6704         }
6705
6706         default:
6707                 /* Error in request */
6708                 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
6709                 outsize = ERROR_DOS(ERRSRV,ERRerror);
6710         }
6711
6712         return outsize;
6713 }
6714
6715 /****************************************************************************
6716  Reply to a SMBtrans2.
6717  ****************************************************************************/
6718
6719 int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
6720                  int size, int bufsize)
6721 {
6722         int outsize = 0;
6723         unsigned int dsoff = SVAL(inbuf, smb_dsoff);
6724         unsigned int dscnt = SVAL(inbuf, smb_dscnt);
6725         unsigned int psoff = SVAL(inbuf, smb_psoff);
6726         unsigned int pscnt = SVAL(inbuf, smb_pscnt);
6727         unsigned int tran_call = SVAL(inbuf, smb_setup0);
6728         struct trans_state *state;
6729         NTSTATUS result;
6730
6731         START_PROFILE(SMBtrans2);
6732
6733         result = allow_new_trans(conn->pending_trans, SVAL(inbuf, smb_mid));
6734         if (!NT_STATUS_IS_OK(result)) {
6735                 DEBUG(2, ("Got invalid trans2 request: %s\n",
6736                           nt_errstr(result)));
6737                 END_PROFILE(SMBtrans2);
6738                 return ERROR_NT(result);
6739         }
6740
6741         if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
6742             && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
6743             && (tran_call != TRANSACT2_QFILEINFO)) {
6744                 END_PROFILE(SMBtrans2);
6745                 return ERROR_DOS(ERRSRV,ERRaccess);
6746         }
6747
6748         if ((state = TALLOC_P(conn->mem_ctx, struct trans_state)) == NULL) {
6749                 DEBUG(0, ("talloc failed\n"));
6750                 END_PROFILE(SMBtrans2);
6751                 return ERROR_NT(NT_STATUS_NO_MEMORY);
6752         }
6753
6754         state->cmd = SMBtrans2;
6755
6756         state->mid = SVAL(inbuf, smb_mid);
6757         state->vuid = SVAL(inbuf, smb_uid);
6758         state->setup_count = SVAL(inbuf, smb_suwcnt);
6759         state->setup = NULL;
6760         state->total_param = SVAL(inbuf, smb_tpscnt);
6761         state->param = NULL;
6762         state->total_data =  SVAL(inbuf, smb_tdscnt);
6763         state->data = NULL;
6764         state->max_param_return = SVAL(inbuf, smb_mprcnt);
6765         state->max_data_return  = SVAL(inbuf, smb_mdrcnt);
6766         state->max_setup_return = SVAL(inbuf, smb_msrcnt);
6767         state->close_on_completion = BITSETW(inbuf+smb_vwv5,0);
6768         state->one_way = BITSETW(inbuf+smb_vwv5,1);
6769
6770         state->call = tran_call;
6771
6772         /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
6773            is so as a sanity check */
6774         if (state->setup_count != 1) {
6775                 /*
6776                  * Need to have rc=0 for ioctl to get job id for OS/2.
6777                  *  Network printing will fail if function is not successful.
6778                  *  Similar function in reply.c will be used if protocol
6779                  *  is LANMAN1.0 instead of LM1.2X002.
6780                  *  Until DosPrintSetJobInfo with PRJINFO3 is supported,
6781                  *  outbuf doesn't have to be set(only job id is used).
6782                  */
6783                 if ( (state->setup_count == 4) && (tran_call == TRANSACT2_IOCTL) &&
6784                                 (SVAL(inbuf,(smb_setup+4)) == LMCAT_SPL) &&
6785                                 (SVAL(inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
6786                         DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
6787                 } else {
6788                         DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
6789                         DEBUG(2,("Transaction is %d\n",tran_call));
6790                         TALLOC_FREE(state);
6791                         END_PROFILE(SMBtrans2);
6792                         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6793                 }
6794         }
6795
6796         if ((dscnt > state->total_data) || (pscnt > state->total_param))
6797                 goto bad_param;
6798
6799         if (state->total_data) {
6800                 /* Can't use talloc here, the core routines do realloc on the
6801                  * params and data. */
6802                 state->data = (char *)SMB_MALLOC(state->total_data);
6803                 if (state->data == NULL) {
6804                         DEBUG(0,("reply_trans2: data malloc fail for %u "
6805                                  "bytes !\n", (unsigned int)state->total_data));
6806                         TALLOC_FREE(state);
6807                         END_PROFILE(SMBtrans2);
6808                         return(ERROR_DOS(ERRDOS,ERRnomem));
6809                 }
6810                 if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
6811                         goto bad_param;
6812                 if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
6813                     (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
6814                         goto bad_param;
6815
6816                 memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
6817         }
6818
6819         if (state->total_param) {
6820                 /* Can't use talloc here, the core routines do realloc on the
6821                  * params and data. */
6822                 state->param = (char *)SMB_MALLOC(state->total_param);
6823                 if (state->param == NULL) {
6824                         DEBUG(0,("reply_trans: param malloc fail for %u "
6825                                  "bytes !\n", (unsigned int)state->total_param));
6826                         SAFE_FREE(state->data);
6827                         TALLOC_FREE(state);
6828                         END_PROFILE(SMBtrans2);
6829                         return(ERROR_DOS(ERRDOS,ERRnomem));
6830                 } 
6831                 if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
6832                         goto bad_param;
6833                 if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
6834                     (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
6835                         goto bad_param;
6836
6837                 memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
6838         }
6839
6840         state->received_data  = dscnt;
6841         state->received_param = pscnt;
6842
6843         if ((state->received_param == state->total_param) &&
6844             (state->received_data == state->total_data)) {
6845
6846                 struct smb_request req;
6847                 init_smb_request(&req, (uint8 *)inbuf);
6848
6849                 outsize = handle_trans2(conn, &req, state, inbuf, outbuf,
6850                                         size, bufsize);
6851                 SAFE_FREE(state->data);
6852                 SAFE_FREE(state->param);
6853                 TALLOC_FREE(state);
6854                 END_PROFILE(SMBtrans2);
6855                 return outsize;
6856         }
6857
6858         DLIST_ADD(conn->pending_trans, state);
6859
6860         /* We need to send an interim response then receive the rest
6861            of the parameter/data bytes */
6862         outsize = set_message(inbuf, outbuf,0,0,False);
6863         show_msg(outbuf);
6864         END_PROFILE(SMBtrans2);
6865         return outsize;
6866
6867   bad_param:
6868
6869         DEBUG(0,("reply_trans2: invalid trans parameters\n"));
6870         SAFE_FREE(state->data);
6871         SAFE_FREE(state->param);
6872         TALLOC_FREE(state);
6873         END_PROFILE(SMBtrans2);
6874         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6875 }
6876
6877
6878 /****************************************************************************
6879  Reply to a SMBtranss2
6880  ****************************************************************************/
6881
6882 int reply_transs2(connection_struct *conn,
6883                   char *inbuf,char *outbuf,int size,int bufsize)
6884 {
6885         int outsize = 0;
6886         unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
6887         struct trans_state *state;
6888         struct smb_request req;
6889
6890         START_PROFILE(SMBtranss2);
6891
6892         show_msg(inbuf);
6893
6894         for (state = conn->pending_trans; state != NULL;
6895              state = state->next) {
6896                 if (state->mid == SVAL(inbuf,smb_mid)) {
6897                         break;
6898                 }
6899         }
6900
6901         if ((state == NULL) || (state->cmd != SMBtrans2)) {
6902                 END_PROFILE(SMBtranss2);
6903                 return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
6904         }
6905
6906         /* Revise state->total_param and state->total_data in case they have
6907            changed downwards */
6908
6909         if (SVAL(inbuf, smb_tpscnt) < state->total_param)
6910                 state->total_param = SVAL(inbuf, smb_tpscnt);
6911         if (SVAL(inbuf, smb_tdscnt) < state->total_data)
6912                 state->total_data = SVAL(inbuf, smb_tdscnt);
6913
6914         pcnt = SVAL(inbuf, smb_spscnt);
6915         poff = SVAL(inbuf, smb_spsoff);
6916         pdisp = SVAL(inbuf, smb_spsdisp);
6917
6918         dcnt = SVAL(inbuf, smb_sdscnt);
6919         doff = SVAL(inbuf, smb_sdsoff);
6920         ddisp = SVAL(inbuf, smb_sdsdisp);
6921
6922         state->received_param += pcnt;
6923         state->received_data += dcnt;
6924                 
6925         if ((state->received_data > state->total_data) ||
6926             (state->received_param > state->total_param))
6927                 goto bad_param;
6928
6929         if (pcnt) {
6930                 if (pdisp+pcnt > state->total_param)
6931                         goto bad_param;
6932                 if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
6933                         goto bad_param;
6934                 if (pdisp > state->total_param)
6935                         goto bad_param;
6936                 if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
6937                     (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
6938                         goto bad_param;
6939                 if (state->param + pdisp < state->param)
6940                         goto bad_param;
6941
6942                 memcpy(state->param+pdisp,smb_base(inbuf)+poff,
6943                        pcnt);
6944         }
6945
6946         if (dcnt) {
6947                 if (ddisp+dcnt > state->total_data)
6948                         goto bad_param;
6949                 if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
6950                         goto bad_param;
6951                 if (ddisp > state->total_data)
6952                         goto bad_param;
6953                 if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
6954                     (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
6955                         goto bad_param;
6956                 if (state->data + ddisp < state->data)
6957                         goto bad_param;
6958
6959                 memcpy(state->data+ddisp, smb_base(inbuf)+doff,
6960                        dcnt);      
6961         }
6962
6963         if ((state->received_param < state->total_param) ||
6964             (state->received_data < state->total_data)) {
6965                 END_PROFILE(SMBtranss2);
6966                 return -1;
6967         }
6968
6969         /* construct_reply_common has done us the favor to pre-fill the
6970          * command field with SMBtranss2 which is wrong :-)
6971          */
6972         SCVAL(outbuf,smb_com,SMBtrans2);
6973
6974         init_smb_request(&req, (uint8 *)inbuf);
6975
6976         outsize = handle_trans2(conn, &req, state, inbuf, outbuf, size,
6977                                 bufsize);
6978
6979         DLIST_REMOVE(conn->pending_trans, state);
6980         SAFE_FREE(state->data);
6981         SAFE_FREE(state->param);
6982         TALLOC_FREE(state);
6983
6984         if (outsize == 0) {
6985                 END_PROFILE(SMBtranss2);
6986                 return(ERROR_DOS(ERRSRV,ERRnosupport));
6987         }
6988         
6989         END_PROFILE(SMBtranss2);
6990         return(outsize);
6991
6992   bad_param:
6993
6994         DEBUG(0,("reply_transs2: invalid trans parameters\n"));
6995         DLIST_REMOVE(conn->pending_trans, state);
6996         SAFE_FREE(state->data);
6997         SAFE_FREE(state->param);
6998         TALLOC_FREE(state);
6999         END_PROFILE(SMBtranss2);
7000         return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
7001 }