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