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