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