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