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