Fix bug 8021 - Incorrect string termination in volume/volume_name for TRANS2-QUERY_FS...
[Samba.git] / source3 / smbd / trans2.c
blob693cf02803036a2e3ba9ebf0c7be81050b0da554
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
10 Extensively modified by Andrew Tridgell, 1995
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.
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.
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/>.
26 #include "includes.h"
27 #include "version.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
30 #include "../librpc/gen_ndr/xattr.h"
31 #include "../librpc/gen_ndr/ndr_security.h"
32 #include "libcli/security/security.h"
34 #define DIR_ENTRY_SAFETY_MARGIN 4096
36 static char *store_file_unix_basic(connection_struct *conn,
37 char *pdata,
38 files_struct *fsp,
39 const SMB_STRUCT_STAT *psbuf);
41 static char *store_file_unix_basic_info2(connection_struct *conn,
42 char *pdata,
43 files_struct *fsp,
44 const SMB_STRUCT_STAT *psbuf);
46 /********************************************************************
47 Roundup a value to the nearest allocation roundup size boundary.
48 Only do this for Windows clients.
49 ********************************************************************/
51 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
53 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
55 /* Only roundup for Windows clients. */
56 enum remote_arch_types ra_type = get_remote_arch();
57 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
58 val = SMB_ROUNDUP(val,rval);
60 return val;
63 /********************************************************************
64 Create a 64 bit FileIndex. If the file is on the same device as
65 the root of the share, just return the 64-bit inode. If it isn't,
66 mangle as we used to do.
67 ********************************************************************/
69 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
71 uint64_t file_index;
72 if (conn->base_share_dev == psbuf->st_ex_dev) {
73 return (uint64_t)psbuf->st_ex_ino;
75 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
76 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
77 return file_index;
80 /****************************************************************************
81 Utility functions for dealing with extended attributes.
82 ****************************************************************************/
84 /****************************************************************************
85 Refuse to allow clients to overwrite our private xattrs.
86 ****************************************************************************/
88 static bool samba_private_attr_name(const char *unix_ea_name)
90 static const char * const prohibited_ea_names[] = {
91 SAMBA_POSIX_INHERITANCE_EA_NAME,
92 SAMBA_XATTR_DOS_ATTRIB,
93 SAMBA_XATTR_MARKER,
94 XATTR_NTACL_NAME,
95 NULL
98 int i;
100 for (i = 0; prohibited_ea_names[i]; i++) {
101 if (strequal( prohibited_ea_names[i], unix_ea_name))
102 return true;
104 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
105 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
106 return true;
108 return false;
111 /****************************************************************************
112 Get one EA value. Fill in a struct ea_struct.
113 ****************************************************************************/
115 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
116 files_struct *fsp, const char *fname,
117 const char *ea_name, struct ea_struct *pea)
119 /* Get the value of this xattr. Max size is 64k. */
120 size_t attr_size = 256;
121 char *val = NULL;
122 ssize_t sizeret;
124 again:
126 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
127 if (!val) {
128 return NT_STATUS_NO_MEMORY;
131 if (fsp && fsp->fh->fd != -1) {
132 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
133 } else {
134 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
137 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
138 attr_size = 65536;
139 goto again;
142 if (sizeret == -1) {
143 return map_nt_error_from_unix(errno);
146 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
147 dump_data(10, (uint8 *)val, sizeret);
149 pea->flags = 0;
150 if (strnequal(ea_name, "user.", 5)) {
151 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
152 } else {
153 pea->name = talloc_strdup(mem_ctx, ea_name);
155 if (pea->name == NULL) {
156 TALLOC_FREE(val);
157 return NT_STATUS_NO_MEMORY;
159 pea->value.data = (unsigned char *)val;
160 pea->value.length = (size_t)sizeret;
161 return NT_STATUS_OK;
164 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
165 files_struct *fsp, const char *fname,
166 char ***pnames, size_t *pnum_names)
168 /* Get a list of all xattrs. Max namesize is 64k. */
169 size_t ea_namelist_size = 1024;
170 char *ea_namelist = NULL;
172 char *p;
173 char **names, **tmp;
174 size_t num_names;
175 ssize_t sizeret = -1;
177 if (!lp_ea_support(SNUM(conn))) {
178 if (pnames) {
179 *pnames = NULL;
181 *pnum_names = 0;
182 return NT_STATUS_OK;
186 * TALLOC the result early to get the talloc hierarchy right.
189 names = TALLOC_ARRAY(mem_ctx, char *, 1);
190 if (names == NULL) {
191 DEBUG(0, ("talloc failed\n"));
192 return NT_STATUS_NO_MEMORY;
195 while (ea_namelist_size <= 65536) {
197 ea_namelist = TALLOC_REALLOC_ARRAY(
198 names, ea_namelist, char, ea_namelist_size);
199 if (ea_namelist == NULL) {
200 DEBUG(0, ("talloc failed\n"));
201 TALLOC_FREE(names);
202 return NT_STATUS_NO_MEMORY;
205 if (fsp && fsp->fh->fd != -1) {
206 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
207 ea_namelist_size);
208 } else {
209 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
210 ea_namelist_size);
213 if ((sizeret == -1) && (errno == ERANGE)) {
214 ea_namelist_size *= 2;
216 else {
217 break;
221 if (sizeret == -1) {
222 TALLOC_FREE(names);
223 return map_nt_error_from_unix(errno);
226 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
227 (unsigned int)sizeret));
229 if (sizeret == 0) {
230 TALLOC_FREE(names);
231 if (pnames) {
232 *pnames = NULL;
234 *pnum_names = 0;
235 return NT_STATUS_OK;
239 * Ensure the result is 0-terminated
242 if (ea_namelist[sizeret-1] != '\0') {
243 TALLOC_FREE(names);
244 return NT_STATUS_INTERNAL_ERROR;
248 * count the names
250 num_names = 0;
252 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
253 num_names += 1;
256 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
257 if (tmp == NULL) {
258 DEBUG(0, ("talloc failed\n"));
259 TALLOC_FREE(names);
260 return NT_STATUS_NO_MEMORY;
263 names = tmp;
264 num_names = 0;
266 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
267 names[num_names++] = p;
270 if (pnames) {
271 *pnames = names;
272 } else {
273 TALLOC_FREE(names);
275 *pnum_names = num_names;
276 return NT_STATUS_OK;
279 /****************************************************************************
280 Return a linked list of the total EA's. Plus the total size
281 ****************************************************************************/
283 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
284 const char *fname, size_t *pea_total_len)
286 /* Get a list of all xattrs. Max namesize is 64k. */
287 size_t i, num_names;
288 char **names;
289 struct ea_list *ea_list_head = NULL;
290 NTSTATUS status;
292 *pea_total_len = 0;
294 if (!lp_ea_support(SNUM(conn))) {
295 return NULL;
298 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
299 &names, &num_names);
301 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
302 return NULL;
305 for (i=0; i<num_names; i++) {
306 struct ea_list *listp;
307 fstring dos_ea_name;
309 if (strnequal(names[i], "system.", 7)
310 || samba_private_attr_name(names[i]))
311 continue;
313 listp = TALLOC_P(mem_ctx, struct ea_list);
314 if (listp == NULL) {
315 return NULL;
318 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
319 fname, names[i],
320 &listp->ea))) {
321 return NULL;
324 push_ascii_fstring(dos_ea_name, listp->ea.name);
326 *pea_total_len +=
327 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
329 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
330 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
331 (unsigned int)listp->ea.value.length));
333 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
337 /* Add on 4 for total length. */
338 if (*pea_total_len) {
339 *pea_total_len += 4;
342 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
343 (unsigned int)*pea_total_len));
345 return ea_list_head;
348 /****************************************************************************
349 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
350 that was filled.
351 ****************************************************************************/
353 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
354 connection_struct *conn, struct ea_list *ea_list)
356 unsigned int ret_data_size = 4;
357 char *p = pdata;
359 SMB_ASSERT(total_data_size >= 4);
361 if (!lp_ea_support(SNUM(conn))) {
362 SIVAL(pdata,4,0);
363 return 4;
366 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
367 size_t dos_namelen;
368 fstring dos_ea_name;
369 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
370 dos_namelen = strlen(dos_ea_name);
371 if (dos_namelen > 255 || dos_namelen == 0) {
372 break;
374 if (ea_list->ea.value.length > 65535) {
375 break;
377 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
378 break;
381 /* We know we have room. */
382 SCVAL(p,0,ea_list->ea.flags);
383 SCVAL(p,1,dos_namelen);
384 SSVAL(p,2,ea_list->ea.value.length);
385 fstrcpy(p+4, dos_ea_name);
386 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
388 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
389 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
392 ret_data_size = PTR_DIFF(p, pdata);
393 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
394 SIVAL(pdata,0,ret_data_size);
395 return ret_data_size;
398 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
399 char *pdata,
400 unsigned int total_data_size,
401 unsigned int *ret_data_size,
402 connection_struct *conn,
403 struct ea_list *ea_list)
405 uint8_t *p = (uint8_t *)pdata;
406 uint8_t *last_start = NULL;
408 *ret_data_size = 0;
410 if (!lp_ea_support(SNUM(conn))) {
411 return NT_STATUS_NO_EAS_ON_FILE;
414 for (; ea_list; ea_list = ea_list->next) {
415 size_t dos_namelen;
416 fstring dos_ea_name;
417 size_t this_size;
419 if (last_start) {
420 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
422 last_start = p;
424 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
425 dos_namelen = strlen(dos_ea_name);
426 if (dos_namelen > 255 || dos_namelen == 0) {
427 return NT_STATUS_INTERNAL_ERROR;
429 if (ea_list->ea.value.length > 65535) {
430 return NT_STATUS_INTERNAL_ERROR;
433 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
435 if (ea_list->next) {
436 size_t pad = 4 - (this_size % 4);
437 this_size += pad;
440 if (this_size > total_data_size) {
441 return NT_STATUS_INFO_LENGTH_MISMATCH;
444 /* We know we have room. */
445 SIVAL(p, 0x00, 0); /* next offset */
446 SCVAL(p, 0x04, ea_list->ea.flags);
447 SCVAL(p, 0x05, dos_namelen);
448 SSVAL(p, 0x06, ea_list->ea.value.length);
449 fstrcpy((char *)(p+0x08), dos_ea_name);
450 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
452 total_data_size -= this_size;
453 p += this_size;
456 *ret_data_size = PTR_DIFF(p, pdata);
457 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
458 return NT_STATUS_OK;
461 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
463 size_t total_ea_len = 0;
464 TALLOC_CTX *mem_ctx = NULL;
466 if (!lp_ea_support(SNUM(conn))) {
467 return 0;
469 mem_ctx = talloc_tos();
470 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
471 return total_ea_len;
474 /****************************************************************************
475 Ensure the EA name is case insensitive by matching any existing EA name.
476 ****************************************************************************/
478 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
480 size_t total_ea_len;
481 TALLOC_CTX *mem_ctx = talloc_tos();
482 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
484 for (; ea_list; ea_list = ea_list->next) {
485 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
486 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
487 &unix_ea_name[5], ea_list->ea.name));
488 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
489 break;
494 /****************************************************************************
495 Set or delete an extended attribute.
496 ****************************************************************************/
498 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
499 const struct smb_filename *smb_fname, struct ea_list *ea_list)
501 char *fname = NULL;
503 if (!lp_ea_support(SNUM(conn))) {
504 return NT_STATUS_EAS_NOT_SUPPORTED;
507 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
508 return NT_STATUS_ACCESS_DENIED;
511 /* For now setting EAs on streams isn't supported. */
512 fname = smb_fname->base_name;
514 for (;ea_list; ea_list = ea_list->next) {
515 int ret;
516 fstring unix_ea_name;
518 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
519 fstrcat(unix_ea_name, ea_list->ea.name);
521 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
523 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
525 if (samba_private_attr_name(unix_ea_name)) {
526 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
527 return NT_STATUS_ACCESS_DENIED;
530 if (ea_list->ea.value.length == 0) {
531 /* Remove the attribute. */
532 if (fsp && (fsp->fh->fd != -1)) {
533 DEBUG(10,("set_ea: deleting ea name %s on "
534 "file %s by file descriptor.\n",
535 unix_ea_name, fsp_str_dbg(fsp)));
536 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
537 } else {
538 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
539 unix_ea_name, fname));
540 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
542 #ifdef ENOATTR
543 /* Removing a non existent attribute always succeeds. */
544 if (ret == -1 && errno == ENOATTR) {
545 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
546 unix_ea_name));
547 ret = 0;
549 #endif
550 } else {
551 if (fsp && (fsp->fh->fd != -1)) {
552 DEBUG(10,("set_ea: setting ea name %s on file "
553 "%s by file descriptor.\n",
554 unix_ea_name, fsp_str_dbg(fsp)));
555 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
556 ea_list->ea.value.data, ea_list->ea.value.length, 0);
557 } else {
558 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
559 unix_ea_name, fname));
560 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
561 ea_list->ea.value.data, ea_list->ea.value.length, 0);
565 if (ret == -1) {
566 #ifdef ENOTSUP
567 if (errno == ENOTSUP) {
568 return NT_STATUS_EAS_NOT_SUPPORTED;
570 #endif
571 return map_nt_error_from_unix(errno);
575 return NT_STATUS_OK;
577 /****************************************************************************
578 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
579 ****************************************************************************/
581 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
583 struct ea_list *ea_list_head = NULL;
584 size_t converted_size, offset = 0;
586 while (offset + 2 < data_size) {
587 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
588 unsigned int namelen = CVAL(pdata,offset);
590 offset++; /* Go past the namelen byte. */
592 /* integer wrap paranioa. */
593 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
594 (offset > data_size) || (namelen > data_size) ||
595 (offset + namelen >= data_size)) {
596 break;
598 /* Ensure the name is null terminated. */
599 if (pdata[offset + namelen] != '\0') {
600 return NULL;
602 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
603 &converted_size)) {
604 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
605 "failed: %s", strerror(errno)));
607 if (!eal->ea.name) {
608 return NULL;
611 offset += (namelen + 1); /* Go past the name + terminating zero. */
612 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
613 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
616 return ea_list_head;
619 /****************************************************************************
620 Read one EA list entry from the buffer.
621 ****************************************************************************/
623 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
625 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
626 uint16 val_len;
627 unsigned int namelen;
628 size_t converted_size;
630 if (!eal) {
631 return NULL;
634 if (data_size < 6) {
635 return NULL;
638 eal->ea.flags = CVAL(pdata,0);
639 namelen = CVAL(pdata,1);
640 val_len = SVAL(pdata,2);
642 if (4 + namelen + 1 + val_len > data_size) {
643 return NULL;
646 /* Ensure the name is null terminated. */
647 if (pdata[namelen + 4] != '\0') {
648 return NULL;
650 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
651 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
652 strerror(errno)));
654 if (!eal->ea.name) {
655 return NULL;
658 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
659 if (!eal->ea.value.data) {
660 return NULL;
663 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
665 /* Ensure we're null terminated just in case we print the value. */
666 eal->ea.value.data[val_len] = '\0';
667 /* But don't count the null. */
668 eal->ea.value.length--;
670 if (pbytes_used) {
671 *pbytes_used = 4 + namelen + 1 + val_len;
674 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
675 dump_data(10, eal->ea.value.data, eal->ea.value.length);
677 return eal;
680 /****************************************************************************
681 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
682 ****************************************************************************/
684 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
686 struct ea_list *ea_list_head = NULL;
687 size_t offset = 0;
688 size_t bytes_used = 0;
690 while (offset < data_size) {
691 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
693 if (!eal) {
694 return NULL;
697 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
698 offset += bytes_used;
701 return ea_list_head;
704 /****************************************************************************
705 Count the total EA size needed.
706 ****************************************************************************/
708 static size_t ea_list_size(struct ea_list *ealist)
710 fstring dos_ea_name;
711 struct ea_list *listp;
712 size_t ret = 0;
714 for (listp = ealist; listp; listp = listp->next) {
715 push_ascii_fstring(dos_ea_name, listp->ea.name);
716 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
718 /* Add on 4 for total length. */
719 if (ret) {
720 ret += 4;
723 return ret;
726 /****************************************************************************
727 Return a union of EA's from a file list and a list of names.
728 The TALLOC context for the two lists *MUST* be identical as we steal
729 memory from one list to add to another. JRA.
730 ****************************************************************************/
732 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
734 struct ea_list *nlistp, *flistp;
736 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
737 for (flistp = file_list; flistp; flistp = flistp->next) {
738 if (strequal(nlistp->ea.name, flistp->ea.name)) {
739 break;
743 if (flistp) {
744 /* Copy the data from this entry. */
745 nlistp->ea.flags = flistp->ea.flags;
746 nlistp->ea.value = flistp->ea.value;
747 } else {
748 /* Null entry. */
749 nlistp->ea.flags = 0;
750 ZERO_STRUCT(nlistp->ea.value);
754 *total_ea_len = ea_list_size(name_list);
755 return name_list;
758 /****************************************************************************
759 Send the required number of replies back.
760 We assume all fields other than the data fields are
761 set correctly for the type of call.
762 HACK ! Always assumes smb_setup field is zero.
763 ****************************************************************************/
765 void send_trans2_replies(connection_struct *conn,
766 struct smb_request *req,
767 const char *params,
768 int paramsize,
769 const char *pdata,
770 int datasize,
771 int max_data_bytes)
773 /* As we are using a protocol > LANMAN1 then the max_send
774 variable must have been set in the sessetupX call.
775 This takes precedence over the max_xmit field in the
776 global struct. These different max_xmit variables should
777 be merged as this is now too confusing */
779 int data_to_send = datasize;
780 int params_to_send = paramsize;
781 int useable_space;
782 const char *pp = params;
783 const char *pd = pdata;
784 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
785 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
786 int data_alignment_offset = 0;
787 bool overflow = False;
788 struct smbd_server_connection *sconn = req->sconn;
789 int max_send = sconn->smb1.sessions.max_send;
791 /* Modify the data_to_send and datasize and set the error if
792 we're trying to send more than max_data_bytes. We still send
793 the part of the packet(s) that fit. Strange, but needed
794 for OS/2. */
796 if (max_data_bytes > 0 && datasize > max_data_bytes) {
797 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
798 max_data_bytes, datasize ));
799 datasize = data_to_send = max_data_bytes;
800 overflow = True;
803 /* If there genuinely are no parameters or data to send just send the empty packet */
805 if(params_to_send == 0 && data_to_send == 0) {
806 reply_outbuf(req, 10, 0);
807 show_msg((char *)req->outbuf);
808 if (!srv_send_smb(sconn,
809 (char *)req->outbuf,
810 true, req->seqnum+1,
811 IS_CONN_ENCRYPTED(conn),
812 &req->pcd)) {
813 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
815 TALLOC_FREE(req->outbuf);
816 return;
819 /* When sending params and data ensure that both are nicely aligned */
820 /* Only do this alignment when there is also data to send - else
821 can cause NT redirector problems. */
823 if (((params_to_send % 4) != 0) && (data_to_send != 0))
824 data_alignment_offset = 4 - (params_to_send % 4);
826 /* Space is bufsize minus Netbios over TCP header minus SMB header */
827 /* The alignment_offset is to align the param bytes on an even byte
828 boundary. NT 4.0 Beta needs this to work correctly. */
830 useable_space = max_send - (smb_size
831 + 2 * 10 /* wct */
832 + alignment_offset
833 + data_alignment_offset);
835 if (useable_space < 0) {
836 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
837 "= %d!!!", useable_space));
838 exit_server_cleanly("send_trans2_replies: Not enough space");
841 while (params_to_send || data_to_send) {
842 /* Calculate whether we will totally or partially fill this packet */
844 total_sent_thistime = params_to_send + data_to_send;
846 /* We can never send more than useable_space */
848 * Note that 'useable_space' does not include the alignment offsets,
849 * but we must include the alignment offsets in the calculation of
850 * the length of the data we send over the wire, as the alignment offsets
851 * are sent here. Fix from Marc_Jacobsen@hp.com.
854 total_sent_thistime = MIN(total_sent_thistime, useable_space);
856 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
857 + data_alignment_offset);
860 * We might have SMBtrans2s in req which was transferred to
861 * the outbuf, fix that.
863 SCVAL(req->outbuf, smb_com, SMBtrans2);
865 /* Set total params and data to be sent */
866 SSVAL(req->outbuf,smb_tprcnt,paramsize);
867 SSVAL(req->outbuf,smb_tdrcnt,datasize);
869 /* Calculate how many parameters and data we can fit into
870 * this packet. Parameters get precedence
873 params_sent_thistime = MIN(params_to_send,useable_space);
874 data_sent_thistime = useable_space - params_sent_thistime;
875 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
877 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
879 /* smb_proff is the offset from the start of the SMB header to the
880 parameter bytes, however the first 4 bytes of outbuf are
881 the Netbios over TCP header. Thus use smb_base() to subtract
882 them from the calculation */
884 SSVAL(req->outbuf,smb_proff,
885 ((smb_buf(req->outbuf)+alignment_offset)
886 - smb_base(req->outbuf)));
888 if(params_sent_thistime == 0)
889 SSVAL(req->outbuf,smb_prdisp,0);
890 else
891 /* Absolute displacement of param bytes sent in this packet */
892 SSVAL(req->outbuf,smb_prdisp,pp - params);
894 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
895 if(data_sent_thistime == 0) {
896 SSVAL(req->outbuf,smb_droff,0);
897 SSVAL(req->outbuf,smb_drdisp, 0);
898 } else {
899 /* The offset of the data bytes is the offset of the
900 parameter bytes plus the number of parameters being sent this time */
901 SSVAL(req->outbuf, smb_droff,
902 ((smb_buf(req->outbuf)+alignment_offset)
903 - smb_base(req->outbuf))
904 + params_sent_thistime + data_alignment_offset);
905 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
908 /* Initialize the padding for alignment */
910 if (alignment_offset != 0) {
911 memset(smb_buf(req->outbuf), 0, alignment_offset);
914 /* Copy the param bytes into the packet */
916 if(params_sent_thistime) {
917 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
918 params_sent_thistime);
921 /* Copy in the data bytes */
922 if(data_sent_thistime) {
923 if (data_alignment_offset != 0) {
924 memset((smb_buf(req->outbuf)+alignment_offset+
925 params_sent_thistime), 0,
926 data_alignment_offset);
928 memcpy(smb_buf(req->outbuf)+alignment_offset
929 +params_sent_thistime+data_alignment_offset,
930 pd,data_sent_thistime);
933 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
934 params_sent_thistime, data_sent_thistime, useable_space));
935 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
936 params_to_send, data_to_send, paramsize, datasize));
938 if (overflow) {
939 error_packet_set((char *)req->outbuf,
940 ERRDOS,ERRbufferoverflow,
941 STATUS_BUFFER_OVERFLOW,
942 __LINE__,__FILE__);
945 /* Send the packet */
946 show_msg((char *)req->outbuf);
947 if (!srv_send_smb(sconn,
948 (char *)req->outbuf,
949 true, req->seqnum+1,
950 IS_CONN_ENCRYPTED(conn),
951 &req->pcd))
952 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
954 TALLOC_FREE(req->outbuf);
956 pp += params_sent_thistime;
957 pd += data_sent_thistime;
959 params_to_send -= params_sent_thistime;
960 data_to_send -= data_sent_thistime;
962 /* Sanity check */
963 if(params_to_send < 0 || data_to_send < 0) {
964 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
965 params_to_send, data_to_send));
966 return;
970 return;
973 /****************************************************************************
974 Reply to a TRANSACT2_OPEN.
975 ****************************************************************************/
977 static void call_trans2open(connection_struct *conn,
978 struct smb_request *req,
979 char **pparams, int total_params,
980 char **ppdata, int total_data,
981 unsigned int max_data_bytes)
983 struct smb_filename *smb_fname = NULL;
984 char *params = *pparams;
985 char *pdata = *ppdata;
986 int deny_mode;
987 int32 open_attr;
988 bool oplock_request;
989 #if 0
990 bool return_additional_info;
991 int16 open_sattr;
992 time_t open_time;
993 #endif
994 int open_ofun;
995 uint32 open_size;
996 char *pname;
997 char *fname = NULL;
998 SMB_OFF_T size=0;
999 int fattr=0,mtime=0;
1000 SMB_INO_T inode = 0;
1001 int smb_action = 0;
1002 files_struct *fsp;
1003 struct ea_list *ea_list = NULL;
1004 uint16 flags = 0;
1005 NTSTATUS status;
1006 uint32 access_mask;
1007 uint32 share_mode;
1008 uint32 create_disposition;
1009 uint32 create_options = 0;
1010 uint32_t private_flags = 0;
1011 TALLOC_CTX *ctx = talloc_tos();
1014 * Ensure we have enough parameters to perform the operation.
1017 if (total_params < 29) {
1018 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1019 goto out;
1022 flags = SVAL(params, 0);
1023 deny_mode = SVAL(params, 2);
1024 open_attr = SVAL(params,6);
1025 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1026 if (oplock_request) {
1027 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1030 #if 0
1031 return_additional_info = BITSETW(params,0);
1032 open_sattr = SVAL(params, 4);
1033 open_time = make_unix_date3(params+8);
1034 #endif
1035 open_ofun = SVAL(params,12);
1036 open_size = IVAL(params,14);
1037 pname = &params[28];
1039 if (IS_IPC(conn)) {
1040 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1041 goto out;
1044 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1045 total_params - 28, STR_TERMINATE,
1046 &status);
1047 if (!NT_STATUS_IS_OK(status)) {
1048 reply_nterror(req, status);
1049 goto out;
1052 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1053 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1054 (unsigned int)open_ofun, open_size));
1056 status = filename_convert(ctx,
1057 conn,
1058 req->flags2 & FLAGS2_DFS_PATHNAMES,
1059 fname,
1061 NULL,
1062 &smb_fname);
1063 if (!NT_STATUS_IS_OK(status)) {
1064 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1065 reply_botherror(req,
1066 NT_STATUS_PATH_NOT_COVERED,
1067 ERRSRV, ERRbadpath);
1068 goto out;
1070 reply_nterror(req, status);
1071 goto out;
1074 if (open_ofun == 0) {
1075 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1076 goto out;
1079 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1080 &access_mask, &share_mode,
1081 &create_disposition,
1082 &create_options,
1083 &private_flags)) {
1084 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1085 goto out;
1088 /* Any data in this call is an EA list. */
1089 if (total_data && (total_data != 4)) {
1090 if (total_data < 10) {
1091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1092 goto out;
1095 if (IVAL(pdata,0) > total_data) {
1096 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1097 IVAL(pdata,0), (unsigned int)total_data));
1098 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1099 goto out;
1102 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1103 total_data - 4);
1104 if (!ea_list) {
1105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1106 goto out;
1109 if (!lp_ea_support(SNUM(conn))) {
1110 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1111 goto out;
1115 status = SMB_VFS_CREATE_FILE(
1116 conn, /* conn */
1117 req, /* req */
1118 0, /* root_dir_fid */
1119 smb_fname, /* fname */
1120 access_mask, /* access_mask */
1121 share_mode, /* share_access */
1122 create_disposition, /* create_disposition*/
1123 create_options, /* create_options */
1124 open_attr, /* file_attributes */
1125 oplock_request, /* oplock_request */
1126 open_size, /* allocation_size */
1127 private_flags,
1128 NULL, /* sd */
1129 ea_list, /* ea_list */
1130 &fsp, /* result */
1131 &smb_action); /* psbuf */
1133 if (!NT_STATUS_IS_OK(status)) {
1134 if (open_was_deferred(req->mid)) {
1135 /* We have re-scheduled this call. */
1136 goto out;
1138 reply_openerror(req, status);
1139 goto out;
1142 size = get_file_size_stat(&smb_fname->st);
1143 fattr = dos_mode(conn, smb_fname);
1144 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1145 inode = smb_fname->st.st_ex_ino;
1146 if (fattr & aDIR) {
1147 close_file(req, fsp, ERROR_CLOSE);
1148 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1149 goto out;
1152 /* Realloc the size of parameters and data we will return */
1153 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1154 if(*pparams == NULL ) {
1155 reply_nterror(req, NT_STATUS_NO_MEMORY);
1156 goto out;
1158 params = *pparams;
1160 SSVAL(params,0,fsp->fnum);
1161 SSVAL(params,2,fattr);
1162 srv_put_dos_date2(params,4, mtime);
1163 SIVAL(params,8, (uint32)size);
1164 SSVAL(params,12,deny_mode);
1165 SSVAL(params,14,0); /* open_type - file or directory. */
1166 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1168 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1169 smb_action |= EXTENDED_OPLOCK_GRANTED;
1172 SSVAL(params,18,smb_action);
1175 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1177 SIVAL(params,20,inode);
1178 SSVAL(params,24,0); /* Padding. */
1179 if (flags & 8) {
1180 uint32 ea_size = estimate_ea_size(conn, fsp,
1181 fsp->fsp_name->base_name);
1182 SIVAL(params, 26, ea_size);
1183 } else {
1184 SIVAL(params, 26, 0);
1187 /* Send the required number of replies */
1188 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1189 out:
1190 TALLOC_FREE(smb_fname);
1193 /*********************************************************
1194 Routine to check if a given string matches exactly.
1195 as a special case a mask of "." does NOT match. That
1196 is required for correct wildcard semantics
1197 Case can be significant or not.
1198 **********************************************************/
1200 static bool exact_match(bool has_wild,
1201 bool case_sensitive,
1202 const char *str,
1203 const char *mask)
1205 if (mask[0] == '.' && mask[1] == 0) {
1206 return false;
1209 if (has_wild) {
1210 return false;
1213 if (case_sensitive) {
1214 return strcmp(str,mask)==0;
1215 } else {
1216 return StrCaseCmp(str,mask) == 0;
1220 /****************************************************************************
1221 Return the filetype for UNIX extensions.
1222 ****************************************************************************/
1224 static uint32 unix_filetype(mode_t mode)
1226 if(S_ISREG(mode))
1227 return UNIX_TYPE_FILE;
1228 else if(S_ISDIR(mode))
1229 return UNIX_TYPE_DIR;
1230 #ifdef S_ISLNK
1231 else if(S_ISLNK(mode))
1232 return UNIX_TYPE_SYMLINK;
1233 #endif
1234 #ifdef S_ISCHR
1235 else if(S_ISCHR(mode))
1236 return UNIX_TYPE_CHARDEV;
1237 #endif
1238 #ifdef S_ISBLK
1239 else if(S_ISBLK(mode))
1240 return UNIX_TYPE_BLKDEV;
1241 #endif
1242 #ifdef S_ISFIFO
1243 else if(S_ISFIFO(mode))
1244 return UNIX_TYPE_FIFO;
1245 #endif
1246 #ifdef S_ISSOCK
1247 else if(S_ISSOCK(mode))
1248 return UNIX_TYPE_SOCKET;
1249 #endif
1251 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1252 return UNIX_TYPE_UNKNOWN;
1255 /****************************************************************************
1256 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1257 ****************************************************************************/
1259 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1261 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1262 const SMB_STRUCT_STAT *psbuf,
1263 uint32 perms,
1264 enum perm_type ptype,
1265 mode_t *ret_perms)
1267 mode_t ret = 0;
1269 if (perms == SMB_MODE_NO_CHANGE) {
1270 if (!VALID_STAT(*psbuf)) {
1271 return NT_STATUS_INVALID_PARAMETER;
1272 } else {
1273 *ret_perms = psbuf->st_ex_mode;
1274 return NT_STATUS_OK;
1278 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1279 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1280 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1281 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1282 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1283 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1284 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1285 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1286 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1287 #ifdef S_ISVTX
1288 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1289 #endif
1290 #ifdef S_ISGID
1291 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1292 #endif
1293 #ifdef S_ISUID
1294 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1295 #endif
1297 switch (ptype) {
1298 case PERM_NEW_FILE:
1299 /* Apply mode mask */
1300 ret &= lp_create_mask(SNUM(conn));
1301 /* Add in force bits */
1302 ret |= lp_force_create_mode(SNUM(conn));
1303 break;
1304 case PERM_NEW_DIR:
1305 ret &= lp_dir_mask(SNUM(conn));
1306 /* Add in force bits */
1307 ret |= lp_force_dir_mode(SNUM(conn));
1308 break;
1309 case PERM_EXISTING_FILE:
1310 /* Apply mode mask */
1311 ret &= lp_security_mask(SNUM(conn));
1312 /* Add in force bits */
1313 ret |= lp_force_security_mode(SNUM(conn));
1314 break;
1315 case PERM_EXISTING_DIR:
1316 /* Apply mode mask */
1317 ret &= lp_dir_security_mask(SNUM(conn));
1318 /* Add in force bits */
1319 ret |= lp_force_dir_security_mode(SNUM(conn));
1320 break;
1323 *ret_perms = ret;
1324 return NT_STATUS_OK;
1327 /****************************************************************************
1328 Needed to show the msdfs symlinks as directories. Modifies psbuf
1329 to be a directory if it's a msdfs link.
1330 ****************************************************************************/
1332 static bool check_msdfs_link(connection_struct *conn,
1333 const char *pathname,
1334 SMB_STRUCT_STAT *psbuf)
1336 int saved_errno = errno;
1337 if(lp_host_msdfs() &&
1338 lp_msdfs_root(SNUM(conn)) &&
1339 is_msdfs_link(conn, pathname, psbuf)) {
1341 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1342 "as a directory\n",
1343 pathname));
1344 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1345 errno = saved_errno;
1346 return true;
1348 errno = saved_errno;
1349 return false;
1353 /****************************************************************************
1354 Get a level dependent lanman2 dir entry.
1355 ****************************************************************************/
1357 struct smbd_dirptr_lanman2_state {
1358 connection_struct *conn;
1359 uint32_t info_level;
1360 bool check_mangled_names;
1361 bool has_wild;
1362 bool got_exact_match;
1365 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1366 void *private_data,
1367 const char *dname,
1368 const char *mask,
1369 char **_fname)
1371 struct smbd_dirptr_lanman2_state *state =
1372 (struct smbd_dirptr_lanman2_state *)private_data;
1373 bool ok;
1374 char mangled_name[13]; /* mangled 8.3 name. */
1375 bool got_match;
1376 const char *fname;
1378 /* Mangle fname if it's an illegal name. */
1379 if (mangle_must_mangle(dname, state->conn->params)) {
1380 ok = name_to_8_3(dname, mangled_name,
1381 true, state->conn->params);
1382 if (!ok) {
1383 return false;
1385 fname = mangled_name;
1386 } else {
1387 fname = dname;
1390 got_match = exact_match(state->has_wild,
1391 state->conn->case_sensitive,
1392 fname, mask);
1393 state->got_exact_match = got_match;
1394 if (!got_match) {
1395 got_match = mask_match(fname, mask,
1396 state->conn->case_sensitive);
1399 if(!got_match && state->check_mangled_names &&
1400 !mangle_is_8_3(fname, false, state->conn->params)) {
1402 * It turns out that NT matches wildcards against
1403 * both long *and* short names. This may explain some
1404 * of the wildcard wierdness from old DOS clients
1405 * that some people have been seeing.... JRA.
1407 /* Force the mangling into 8.3. */
1408 ok = name_to_8_3(fname, mangled_name,
1409 false, state->conn->params);
1410 if (!ok) {
1411 return false;
1414 got_match = exact_match(state->has_wild,
1415 state->conn->case_sensitive,
1416 mangled_name, mask);
1417 state->got_exact_match = got_match;
1418 if (!got_match) {
1419 got_match = mask_match(mangled_name, mask,
1420 state->conn->case_sensitive);
1424 if (!got_match) {
1425 return false;
1428 *_fname = talloc_strdup(ctx, fname);
1429 if (*_fname == NULL) {
1430 return false;
1433 return true;
1436 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1437 void *private_data,
1438 struct smb_filename *smb_fname,
1439 uint32_t *_mode)
1441 struct smbd_dirptr_lanman2_state *state =
1442 (struct smbd_dirptr_lanman2_state *)private_data;
1443 bool ms_dfs_link = false;
1444 uint32_t mode = 0;
1446 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1447 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1448 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1449 "Couldn't lstat [%s] (%s)\n",
1450 smb_fname_str_dbg(smb_fname),
1451 strerror(errno)));
1452 return false;
1454 } else if (!VALID_STAT(smb_fname->st) &&
1455 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1456 /* Needed to show the msdfs symlinks as
1457 * directories */
1459 ms_dfs_link = check_msdfs_link(state->conn,
1460 smb_fname->base_name,
1461 &smb_fname->st);
1462 if (!ms_dfs_link) {
1463 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1464 "Couldn't stat [%s] (%s)\n",
1465 smb_fname_str_dbg(smb_fname),
1466 strerror(errno)));
1467 return false;
1471 if (ms_dfs_link) {
1472 mode = dos_mode_msdfs(state->conn, smb_fname);
1473 } else {
1474 mode = dos_mode(state->conn, smb_fname);
1477 *_mode = mode;
1478 return true;
1481 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1482 connection_struct *conn,
1483 uint16_t flags2,
1484 uint32_t info_level,
1485 struct ea_list *name_list,
1486 bool check_mangled_names,
1487 bool requires_resume_key,
1488 uint32_t mode,
1489 const char *fname,
1490 const struct smb_filename *smb_fname,
1491 int space_remaining,
1492 uint8_t align,
1493 bool do_pad,
1494 char *base_data,
1495 char **ppdata,
1496 char *end_data,
1497 bool *out_of_space,
1498 uint64_t *last_entry_off)
1500 char *p, *q, *pdata = *ppdata;
1501 uint32_t reskey=0;
1502 uint64_t file_size = 0;
1503 uint64_t allocation_size = 0;
1504 uint64_t file_index = 0;
1505 uint32_t len;
1506 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1507 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1508 time_t c_date = (time_t)0;
1509 char *nameptr;
1510 char *last_entry_ptr;
1511 bool was_8_3;
1512 int off;
1513 int pad = 0;
1515 *out_of_space = false;
1517 ZERO_STRUCT(mdate_ts);
1518 ZERO_STRUCT(adate_ts);
1519 ZERO_STRUCT(create_date_ts);
1520 ZERO_STRUCT(cdate_ts);
1522 if (!(mode & aDIR)) {
1523 file_size = get_file_size_stat(&smb_fname->st);
1525 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1527 file_index = get_FileIndex(conn, &smb_fname->st);
1529 mdate_ts = smb_fname->st.st_ex_mtime;
1530 adate_ts = smb_fname->st.st_ex_atime;
1531 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1532 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1534 if (lp_dos_filetime_resolution(SNUM(conn))) {
1535 dos_filetime_timespec(&create_date_ts);
1536 dos_filetime_timespec(&mdate_ts);
1537 dos_filetime_timespec(&adate_ts);
1538 dos_filetime_timespec(&cdate_ts);
1541 create_date = convert_timespec_to_time_t(create_date_ts);
1542 mdate = convert_timespec_to_time_t(mdate_ts);
1543 adate = convert_timespec_to_time_t(adate_ts);
1544 c_date = convert_timespec_to_time_t(cdate_ts);
1546 /* align the record */
1547 SMB_ASSERT(align >= 1);
1549 off = (int)PTR_DIFF(pdata, base_data);
1550 pad = (off + (align-1)) & ~(align-1);
1551 pad -= off;
1553 if (pad && pad > space_remaining) {
1554 *out_of_space = true;
1555 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1556 "for padding (wanted %u, had %d)\n",
1557 (unsigned int)pad,
1558 space_remaining ));
1559 return false; /* Not finished - just out of space */
1562 off += pad;
1563 /* initialize padding to 0 */
1564 if (pad) {
1565 memset(pdata, 0, pad);
1567 space_remaining -= pad;
1569 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1570 space_remaining ));
1572 pdata += pad;
1573 p = pdata;
1574 last_entry_ptr = p;
1576 pad = 0;
1577 off = 0;
1579 switch (info_level) {
1580 case SMB_FIND_INFO_STANDARD:
1581 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1582 if(requires_resume_key) {
1583 SIVAL(p,0,reskey);
1584 p += 4;
1586 srv_put_dos_date2(p,0,create_date);
1587 srv_put_dos_date2(p,4,adate);
1588 srv_put_dos_date2(p,8,mdate);
1589 SIVAL(p,12,(uint32)file_size);
1590 SIVAL(p,16,(uint32)allocation_size);
1591 SSVAL(p,20,mode);
1592 p += 23;
1593 nameptr = p;
1594 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1595 p += ucs2_align(base_data, p, 0);
1597 len = srvstr_push(base_data, flags2, p,
1598 fname, PTR_DIFF(end_data, p),
1599 STR_TERMINATE);
1600 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1601 if (len > 2) {
1602 SCVAL(nameptr, -1, len - 2);
1603 } else {
1604 SCVAL(nameptr, -1, 0);
1606 } else {
1607 if (len > 1) {
1608 SCVAL(nameptr, -1, len - 1);
1609 } else {
1610 SCVAL(nameptr, -1, 0);
1613 p += len;
1614 break;
1616 case SMB_FIND_EA_SIZE:
1617 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1618 if (requires_resume_key) {
1619 SIVAL(p,0,reskey);
1620 p += 4;
1622 srv_put_dos_date2(p,0,create_date);
1623 srv_put_dos_date2(p,4,adate);
1624 srv_put_dos_date2(p,8,mdate);
1625 SIVAL(p,12,(uint32)file_size);
1626 SIVAL(p,16,(uint32)allocation_size);
1627 SSVAL(p,20,mode);
1629 unsigned int ea_size = estimate_ea_size(conn, NULL,
1630 smb_fname->base_name);
1631 SIVAL(p,22,ea_size); /* Extended attributes */
1633 p += 27;
1634 nameptr = p - 1;
1635 len = srvstr_push(base_data, flags2,
1636 p, fname, PTR_DIFF(end_data, p),
1637 STR_TERMINATE | STR_NOALIGN);
1638 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1639 if (len > 2) {
1640 len -= 2;
1641 } else {
1642 len = 0;
1644 } else {
1645 if (len > 1) {
1646 len -= 1;
1647 } else {
1648 len = 0;
1651 SCVAL(nameptr,0,len);
1652 p += len;
1653 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1654 break;
1656 case SMB_FIND_EA_LIST:
1658 struct ea_list *file_list = NULL;
1659 size_t ea_len = 0;
1661 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1662 if (!name_list) {
1663 return false;
1665 if (requires_resume_key) {
1666 SIVAL(p,0,reskey);
1667 p += 4;
1669 srv_put_dos_date2(p,0,create_date);
1670 srv_put_dos_date2(p,4,adate);
1671 srv_put_dos_date2(p,8,mdate);
1672 SIVAL(p,12,(uint32)file_size);
1673 SIVAL(p,16,(uint32)allocation_size);
1674 SSVAL(p,20,mode);
1675 p += 22; /* p now points to the EA area. */
1677 file_list = get_ea_list_from_file(ctx, conn, NULL,
1678 smb_fname->base_name,
1679 &ea_len);
1680 name_list = ea_list_union(name_list, file_list, &ea_len);
1682 /* We need to determine if this entry will fit in the space available. */
1683 /* Max string size is 255 bytes. */
1684 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1685 *out_of_space = true;
1686 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1687 "(wanted %u, had %d)\n",
1688 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1689 space_remaining ));
1690 return False; /* Not finished - just out of space */
1693 /* Push the ea_data followed by the name. */
1694 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1695 nameptr = p;
1696 len = srvstr_push(base_data, flags2,
1697 p + 1, fname, PTR_DIFF(end_data, p+1),
1698 STR_TERMINATE | STR_NOALIGN);
1699 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1700 if (len > 2) {
1701 len -= 2;
1702 } else {
1703 len = 0;
1705 } else {
1706 if (len > 1) {
1707 len -= 1;
1708 } else {
1709 len = 0;
1712 SCVAL(nameptr,0,len);
1713 p += len + 1;
1714 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1715 break;
1718 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1719 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1720 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1721 p += 4;
1722 SIVAL(p,0,reskey); p += 4;
1723 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1724 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1725 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1726 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1727 SOFF_T(p,0,file_size); p += 8;
1728 SOFF_T(p,0,allocation_size); p += 8;
1729 SIVAL(p,0,mode); p += 4;
1730 q = p; p += 4; /* q is placeholder for name length. */
1732 unsigned int ea_size = estimate_ea_size(conn, NULL,
1733 smb_fname->base_name);
1734 SIVAL(p,0,ea_size); /* Extended attributes */
1735 p += 4;
1737 /* Clear the short name buffer. This is
1738 * IMPORTANT as not doing so will trigger
1739 * a Win2k client bug. JRA.
1741 if (!was_8_3 && check_mangled_names) {
1742 char mangled_name[13]; /* mangled 8.3 name. */
1743 if (!name_to_8_3(fname,mangled_name,True,
1744 conn->params)) {
1745 /* Error - mangle failed ! */
1746 memset(mangled_name,'\0',12);
1748 mangled_name[12] = 0;
1749 len = srvstr_push(base_data, flags2,
1750 p+2, mangled_name, 24,
1751 STR_UPPER|STR_UNICODE);
1752 if (len < 24) {
1753 memset(p + 2 + len,'\0',24 - len);
1755 SSVAL(p, 0, len);
1756 } else {
1757 memset(p,'\0',26);
1759 p += 2 + 24;
1760 len = srvstr_push(base_data, flags2, p,
1761 fname, PTR_DIFF(end_data, p),
1762 STR_TERMINATE_ASCII);
1763 SIVAL(q,0,len);
1764 p += len;
1766 len = PTR_DIFF(p, pdata);
1767 pad = (len + (align-1)) & ~(align-1);
1769 * offset to the next entry, the caller
1770 * will overwrite it for the last entry
1771 * that's why we always include the padding
1773 SIVAL(pdata,0,pad);
1775 * set padding to zero
1777 if (do_pad) {
1778 memset(p, 0, pad - len);
1779 p = pdata + pad;
1780 } else {
1781 p = pdata + len;
1783 break;
1785 case SMB_FIND_FILE_DIRECTORY_INFO:
1786 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1787 p += 4;
1788 SIVAL(p,0,reskey); p += 4;
1789 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1790 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1791 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1792 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1793 SOFF_T(p,0,file_size); p += 8;
1794 SOFF_T(p,0,allocation_size); p += 8;
1795 SIVAL(p,0,mode); p += 4;
1796 len = srvstr_push(base_data, flags2,
1797 p + 4, fname, PTR_DIFF(end_data, p+4),
1798 STR_TERMINATE_ASCII);
1799 SIVAL(p,0,len);
1800 p += 4 + len;
1802 len = PTR_DIFF(p, pdata);
1803 pad = (len + (align-1)) & ~(align-1);
1805 * offset to the next entry, the caller
1806 * will overwrite it for the last entry
1807 * that's why we always include the padding
1809 SIVAL(pdata,0,pad);
1811 * set padding to zero
1813 if (do_pad) {
1814 memset(p, 0, pad - len);
1815 p = pdata + pad;
1816 } else {
1817 p = pdata + len;
1819 break;
1821 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1822 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1823 p += 4;
1824 SIVAL(p,0,reskey); p += 4;
1825 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1826 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1827 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1828 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1829 SOFF_T(p,0,file_size); p += 8;
1830 SOFF_T(p,0,allocation_size); p += 8;
1831 SIVAL(p,0,mode); p += 4;
1832 q = p; p += 4; /* q is placeholder for name length. */
1834 unsigned int ea_size = estimate_ea_size(conn, NULL,
1835 smb_fname->base_name);
1836 SIVAL(p,0,ea_size); /* Extended attributes */
1837 p +=4;
1839 len = srvstr_push(base_data, flags2, p,
1840 fname, PTR_DIFF(end_data, p),
1841 STR_TERMINATE_ASCII);
1842 SIVAL(q, 0, len);
1843 p += len;
1845 len = PTR_DIFF(p, pdata);
1846 pad = (len + (align-1)) & ~(align-1);
1848 * offset to the next entry, the caller
1849 * will overwrite it for the last entry
1850 * that's why we always include the padding
1852 SIVAL(pdata,0,pad);
1854 * set padding to zero
1856 if (do_pad) {
1857 memset(p, 0, pad - len);
1858 p = pdata + pad;
1859 } else {
1860 p = pdata + len;
1862 break;
1864 case SMB_FIND_FILE_NAMES_INFO:
1865 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1866 p += 4;
1867 SIVAL(p,0,reskey); p += 4;
1868 p += 4;
1869 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1870 acl on a dir (tridge) */
1871 len = srvstr_push(base_data, flags2, p,
1872 fname, PTR_DIFF(end_data, p),
1873 STR_TERMINATE_ASCII);
1874 SIVAL(p, -4, len);
1875 p += len;
1877 len = PTR_DIFF(p, pdata);
1878 pad = (len + (align-1)) & ~(align-1);
1880 * offset to the next entry, the caller
1881 * will overwrite it for the last entry
1882 * that's why we always include the padding
1884 SIVAL(pdata,0,pad);
1886 * set padding to zero
1888 if (do_pad) {
1889 memset(p, 0, pad - len);
1890 p = pdata + pad;
1891 } else {
1892 p = pdata + len;
1894 break;
1896 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1897 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1898 p += 4;
1899 SIVAL(p,0,reskey); p += 4;
1900 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1901 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1902 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1903 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1904 SOFF_T(p,0,file_size); p += 8;
1905 SOFF_T(p,0,allocation_size); p += 8;
1906 SIVAL(p,0,mode); p += 4;
1907 q = p; p += 4; /* q is placeholder for name length. */
1909 unsigned int ea_size = estimate_ea_size(conn, NULL,
1910 smb_fname->base_name);
1911 SIVAL(p,0,ea_size); /* Extended attributes */
1912 p +=4;
1914 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1915 SBVAL(p,0,file_index); p += 8;
1916 len = srvstr_push(base_data, flags2, p,
1917 fname, PTR_DIFF(end_data, p),
1918 STR_TERMINATE_ASCII);
1919 SIVAL(q, 0, len);
1920 p += len;
1922 len = PTR_DIFF(p, pdata);
1923 pad = (len + (align-1)) & ~(align-1);
1925 * offset to the next entry, the caller
1926 * will overwrite it for the last entry
1927 * that's why we always include the padding
1929 SIVAL(pdata,0,pad);
1931 * set padding to zero
1933 if (do_pad) {
1934 memset(p, 0, pad - len);
1935 p = pdata + pad;
1936 } else {
1937 p = pdata + len;
1939 break;
1941 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1942 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1943 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1944 p += 4;
1945 SIVAL(p,0,reskey); p += 4;
1946 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1947 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1948 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1949 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1950 SOFF_T(p,0,file_size); p += 8;
1951 SOFF_T(p,0,allocation_size); p += 8;
1952 SIVAL(p,0,mode); p += 4;
1953 q = p; p += 4; /* q is placeholder for name length */
1955 unsigned int ea_size = estimate_ea_size(conn, NULL,
1956 smb_fname->base_name);
1957 SIVAL(p,0,ea_size); /* Extended attributes */
1958 p +=4;
1960 /* Clear the short name buffer. This is
1961 * IMPORTANT as not doing so will trigger
1962 * a Win2k client bug. JRA.
1964 if (!was_8_3 && check_mangled_names) {
1965 char mangled_name[13]; /* mangled 8.3 name. */
1966 if (!name_to_8_3(fname,mangled_name,True,
1967 conn->params)) {
1968 /* Error - mangle failed ! */
1969 memset(mangled_name,'\0',12);
1971 mangled_name[12] = 0;
1972 len = srvstr_push(base_data, flags2,
1973 p+2, mangled_name, 24,
1974 STR_UPPER|STR_UNICODE);
1975 SSVAL(p, 0, len);
1976 if (len < 24) {
1977 memset(p + 2 + len,'\0',24 - len);
1979 SSVAL(p, 0, len);
1980 } else {
1981 memset(p,'\0',26);
1983 p += 26;
1984 SSVAL(p,0,0); p += 2; /* Reserved ? */
1985 SBVAL(p,0,file_index); p += 8;
1986 len = srvstr_push(base_data, flags2, p,
1987 fname, PTR_DIFF(end_data, p),
1988 STR_TERMINATE_ASCII);
1989 SIVAL(q,0,len);
1990 p += len;
1992 len = PTR_DIFF(p, pdata);
1993 pad = (len + (align-1)) & ~(align-1);
1995 * offset to the next entry, the caller
1996 * will overwrite it for the last entry
1997 * that's why we always include the padding
1999 SIVAL(pdata,0,pad);
2001 * set padding to zero
2003 if (do_pad) {
2004 memset(p, 0, pad - len);
2005 p = pdata + pad;
2006 } else {
2007 p = pdata + len;
2009 break;
2011 /* CIFS UNIX Extension. */
2013 case SMB_FIND_FILE_UNIX:
2014 case SMB_FIND_FILE_UNIX_INFO2:
2015 p+= 4;
2016 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2018 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2020 if (info_level == SMB_FIND_FILE_UNIX) {
2021 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2022 p = store_file_unix_basic(conn, p,
2023 NULL, &smb_fname->st);
2024 len = srvstr_push(base_data, flags2, p,
2025 fname, PTR_DIFF(end_data, p),
2026 STR_TERMINATE);
2027 } else {
2028 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2029 p = store_file_unix_basic_info2(conn, p,
2030 NULL, &smb_fname->st);
2031 nameptr = p;
2032 p += 4;
2033 len = srvstr_push(base_data, flags2, p, fname,
2034 PTR_DIFF(end_data, p), 0);
2035 SIVAL(nameptr, 0, len);
2038 p += len;
2040 len = PTR_DIFF(p, pdata);
2041 pad = (len + (align-1)) & ~(align-1);
2043 * offset to the next entry, the caller
2044 * will overwrite it for the last entry
2045 * that's why we always include the padding
2047 SIVAL(pdata,0,pad);
2049 * set padding to zero
2051 if (do_pad) {
2052 memset(p, 0, pad - len);
2053 p = pdata + pad;
2054 } else {
2055 p = pdata + len;
2057 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2059 break;
2061 default:
2062 return false;
2065 if (PTR_DIFF(p,pdata) > space_remaining) {
2066 *out_of_space = true;
2067 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2068 "(wanted %u, had %d)\n",
2069 (unsigned int)PTR_DIFF(p,pdata),
2070 space_remaining ));
2071 return false; /* Not finished - just out of space */
2074 /* Setup the last entry pointer, as an offset from base_data */
2075 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2076 /* Advance the data pointer to the next slot */
2077 *ppdata = p;
2079 return true;
2082 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2083 connection_struct *conn,
2084 struct dptr_struct *dirptr,
2085 uint16 flags2,
2086 const char *path_mask,
2087 uint32 dirtype,
2088 int info_level,
2089 int requires_resume_key,
2090 bool dont_descend,
2091 bool ask_sharemode,
2092 uint8_t align,
2093 bool do_pad,
2094 char **ppdata,
2095 char *base_data,
2096 char *end_data,
2097 int space_remaining,
2098 bool *out_of_space,
2099 bool *got_exact_match,
2100 int *_last_entry_off,
2101 struct ea_list *name_list)
2103 const char *p;
2104 const char *mask = NULL;
2105 long prev_dirpos = 0;
2106 uint32_t mode = 0;
2107 char *fname = NULL;
2108 struct smb_filename *smb_fname = NULL;
2109 struct smbd_dirptr_lanman2_state state;
2110 bool ok;
2111 uint64_t last_entry_off = 0;
2113 ZERO_STRUCT(state);
2114 state.conn = conn;
2115 state.info_level = info_level;
2116 state.check_mangled_names = lp_manglednames(conn->params);
2117 state.has_wild = dptr_has_wild(dirptr);
2118 state.got_exact_match = false;
2120 *out_of_space = false;
2121 *got_exact_match = false;
2123 p = strrchr_m(path_mask,'/');
2124 if(p != NULL) {
2125 if(p[1] == '\0') {
2126 mask = "*.*";
2127 } else {
2128 mask = p+1;
2130 } else {
2131 mask = path_mask;
2134 ok = smbd_dirptr_get_entry(ctx,
2135 dirptr,
2136 mask,
2137 dirtype,
2138 dont_descend,
2139 ask_sharemode,
2140 smbd_dirptr_lanman2_match_fn,
2141 smbd_dirptr_lanman2_mode_fn,
2142 &state,
2143 &fname,
2144 &smb_fname,
2145 &mode,
2146 &prev_dirpos);
2147 if (!ok) {
2148 return false;
2151 *got_exact_match = state.got_exact_match;
2153 ok = smbd_marshall_dir_entry(ctx,
2154 conn,
2155 flags2,
2156 info_level,
2157 name_list,
2158 state.check_mangled_names,
2159 requires_resume_key,
2160 mode,
2161 fname,
2162 smb_fname,
2163 space_remaining,
2164 align,
2165 do_pad,
2166 base_data,
2167 ppdata,
2168 end_data,
2169 out_of_space,
2170 &last_entry_off);
2171 TALLOC_FREE(fname);
2172 TALLOC_FREE(smb_fname);
2173 if (*out_of_space) {
2174 dptr_SeekDir(dirptr, prev_dirpos);
2175 return false;
2177 if (!ok) {
2178 return false;
2181 *_last_entry_off = last_entry_off;
2182 return true;
2185 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2186 connection_struct *conn,
2187 struct dptr_struct *dirptr,
2188 uint16 flags2,
2189 const char *path_mask,
2190 uint32 dirtype,
2191 int info_level,
2192 bool requires_resume_key,
2193 bool dont_descend,
2194 bool ask_sharemode,
2195 char **ppdata,
2196 char *base_data,
2197 char *end_data,
2198 int space_remaining,
2199 bool *out_of_space,
2200 bool *got_exact_match,
2201 int *last_entry_off,
2202 struct ea_list *name_list)
2204 uint8_t align = 4;
2205 const bool do_pad = true;
2207 if (info_level >= 1 && info_level <= 3) {
2208 /* No alignment on earlier info levels. */
2209 align = 1;
2212 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2213 path_mask, dirtype, info_level,
2214 requires_resume_key, dont_descend, ask_sharemode,
2215 align, do_pad,
2216 ppdata, base_data, end_data,
2217 space_remaining,
2218 out_of_space, got_exact_match,
2219 last_entry_off, name_list);
2222 /****************************************************************************
2223 Reply to a TRANS2_FINDFIRST.
2224 ****************************************************************************/
2226 static void call_trans2findfirst(connection_struct *conn,
2227 struct smb_request *req,
2228 char **pparams, int total_params,
2229 char **ppdata, int total_data,
2230 unsigned int max_data_bytes)
2232 /* We must be careful here that we don't return more than the
2233 allowed number of data bytes. If this means returning fewer than
2234 maxentries then so be it. We assume that the redirector has
2235 enough room for the fixed number of parameter bytes it has
2236 requested. */
2237 struct smb_filename *smb_dname = NULL;
2238 char *params = *pparams;
2239 char *pdata = *ppdata;
2240 char *data_end;
2241 uint32 dirtype;
2242 int maxentries;
2243 uint16 findfirst_flags;
2244 bool close_after_first;
2245 bool close_if_end;
2246 bool requires_resume_key;
2247 int info_level;
2248 char *directory = NULL;
2249 char *mask = NULL;
2250 char *p;
2251 int last_entry_off=0;
2252 int dptr_num = -1;
2253 int numentries = 0;
2254 int i;
2255 bool finished = False;
2256 bool dont_descend = False;
2257 bool out_of_space = False;
2258 int space_remaining;
2259 bool mask_contains_wcard = False;
2260 struct ea_list *ea_list = NULL;
2261 NTSTATUS ntstatus = NT_STATUS_OK;
2262 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2263 TALLOC_CTX *ctx = talloc_tos();
2264 struct dptr_struct *dirptr = NULL;
2265 struct smbd_server_connection *sconn = req->sconn;
2267 if (total_params < 13) {
2268 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2269 goto out;
2272 dirtype = SVAL(params,0);
2273 maxentries = SVAL(params,2);
2274 findfirst_flags = SVAL(params,4);
2275 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2276 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2277 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2278 info_level = SVAL(params,6);
2280 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2281 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2282 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2283 info_level, max_data_bytes));
2285 if (!maxentries) {
2286 /* W2K3 seems to treat zero as 1. */
2287 maxentries = 1;
2290 switch (info_level) {
2291 case SMB_FIND_INFO_STANDARD:
2292 case SMB_FIND_EA_SIZE:
2293 case SMB_FIND_EA_LIST:
2294 case SMB_FIND_FILE_DIRECTORY_INFO:
2295 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2296 case SMB_FIND_FILE_NAMES_INFO:
2297 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2298 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2299 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2300 break;
2301 case SMB_FIND_FILE_UNIX:
2302 case SMB_FIND_FILE_UNIX_INFO2:
2303 /* Always use filesystem for UNIX mtime query. */
2304 ask_sharemode = false;
2305 if (!lp_unix_extensions()) {
2306 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2307 goto out;
2309 break;
2310 default:
2311 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2312 goto out;
2315 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2316 params+12, total_params - 12,
2317 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2318 if (!NT_STATUS_IS_OK(ntstatus)) {
2319 reply_nterror(req, ntstatus);
2320 goto out;
2323 ntstatus = filename_convert(ctx, conn,
2324 req->flags2 & FLAGS2_DFS_PATHNAMES,
2325 directory,
2326 (UCF_SAVE_LCOMP |
2327 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2328 &mask_contains_wcard,
2329 &smb_dname);
2330 if (!NT_STATUS_IS_OK(ntstatus)) {
2331 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2332 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2333 ERRSRV, ERRbadpath);
2334 goto out;
2336 reply_nterror(req, ntstatus);
2337 goto out;
2340 mask = smb_dname->original_lcomp;
2342 directory = smb_dname->base_name;
2344 p = strrchr_m(directory,'/');
2345 if(p == NULL) {
2346 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2347 if((directory[0] == '.') && (directory[1] == '\0')) {
2348 mask = talloc_strdup(ctx,"*");
2349 if (!mask) {
2350 reply_nterror(req, NT_STATUS_NO_MEMORY);
2351 goto out;
2353 mask_contains_wcard = True;
2355 } else {
2356 *p = 0;
2359 if (p == NULL || p == directory) {
2360 /* Ensure we don't have a directory name of "". */
2361 directory = talloc_strdup(talloc_tos(), ".");
2362 if (!directory) {
2363 reply_nterror(req, NT_STATUS_NO_MEMORY);
2364 goto out;
2368 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2370 if (info_level == SMB_FIND_EA_LIST) {
2371 uint32 ea_size;
2373 if (total_data < 4) {
2374 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2375 goto out;
2378 ea_size = IVAL(pdata,0);
2379 if (ea_size != total_data) {
2380 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2381 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2382 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2383 goto out;
2386 if (!lp_ea_support(SNUM(conn))) {
2387 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2388 goto out;
2391 /* Pull out the list of names. */
2392 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2393 if (!ea_list) {
2394 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2395 goto out;
2399 *ppdata = (char *)SMB_REALLOC(
2400 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2401 if(*ppdata == NULL ) {
2402 reply_nterror(req, NT_STATUS_NO_MEMORY);
2403 goto out;
2405 pdata = *ppdata;
2406 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2408 /* Realloc the params space */
2409 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2410 if (*pparams == NULL) {
2411 reply_nterror(req, NT_STATUS_NO_MEMORY);
2412 goto out;
2414 params = *pparams;
2416 /* Save the wildcard match and attribs we are using on this directory -
2417 needed as lanman2 assumes these are being saved between calls */
2419 ntstatus = dptr_create(conn,
2420 NULL, /* fsp */
2421 directory,
2422 False,
2423 True,
2424 req->smbpid,
2425 mask,
2426 mask_contains_wcard,
2427 dirtype,
2428 &dirptr);
2430 if (!NT_STATUS_IS_OK(ntstatus)) {
2431 reply_nterror(req, ntstatus);
2432 goto out;
2435 dptr_num = dptr_dnum(dirptr);
2436 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2438 /* Initialize per TRANS2_FIND_FIRST operation data */
2439 dptr_init_search_op(dirptr);
2441 /* We don't need to check for VOL here as this is returned by
2442 a different TRANS2 call. */
2444 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2445 directory,lp_dontdescend(SNUM(conn))));
2446 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2447 dont_descend = True;
2449 p = pdata;
2450 space_remaining = max_data_bytes;
2451 out_of_space = False;
2453 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2454 bool got_exact_match = False;
2456 /* this is a heuristic to avoid seeking the dirptr except when
2457 absolutely necessary. It allows for a filename of about 40 chars */
2458 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2459 out_of_space = True;
2460 finished = False;
2461 } else {
2462 finished = !get_lanman2_dir_entry(ctx,
2463 conn,
2464 dirptr,
2465 req->flags2,
2466 mask,dirtype,info_level,
2467 requires_resume_key,dont_descend,
2468 ask_sharemode,
2469 &p,pdata,data_end,
2470 space_remaining, &out_of_space,
2471 &got_exact_match,
2472 &last_entry_off, ea_list);
2475 if (finished && out_of_space)
2476 finished = False;
2478 if (!finished && !out_of_space)
2479 numentries++;
2482 * As an optimisation if we know we aren't looking
2483 * for a wildcard name (ie. the name matches the wildcard exactly)
2484 * then we can finish on any (first) match.
2485 * This speeds up large directory searches. JRA.
2488 if(got_exact_match)
2489 finished = True;
2491 /* Ensure space_remaining never goes -ve. */
2492 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2493 space_remaining = 0;
2494 out_of_space = true;
2495 } else {
2496 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2500 /* Check if we can close the dirptr */
2501 if(close_after_first || (finished && close_if_end)) {
2502 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2503 dptr_close(sconn, &dptr_num);
2507 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2508 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2509 * the protocol level is less than NT1. Tested with smbclient. JRA.
2510 * This should fix the OS/2 client bug #2335.
2513 if(numentries == 0) {
2514 dptr_close(sconn, &dptr_num);
2515 if (get_Protocol() < PROTOCOL_NT1) {
2516 reply_force_doserror(req, ERRDOS, ERRnofiles);
2517 goto out;
2518 } else {
2519 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2520 ERRDOS, ERRbadfile);
2521 goto out;
2525 /* At this point pdata points to numentries directory entries. */
2527 /* Set up the return parameter block */
2528 SSVAL(params,0,dptr_num);
2529 SSVAL(params,2,numentries);
2530 SSVAL(params,4,finished);
2531 SSVAL(params,6,0); /* Never an EA error */
2532 SSVAL(params,8,last_entry_off);
2534 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2535 max_data_bytes);
2537 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2538 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2539 if (!directory) {
2540 reply_nterror(req, NT_STATUS_NO_MEMORY);
2544 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2545 smb_fn_name(req->cmd),
2546 mask, directory, dirtype, numentries ) );
2549 * Force a name mangle here to ensure that the
2550 * mask as an 8.3 name is top of the mangled cache.
2551 * The reasons for this are subtle. Don't remove
2552 * this code unless you know what you are doing
2553 * (see PR#13758). JRA.
2556 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2557 char mangled_name[13];
2558 name_to_8_3(mask, mangled_name, True, conn->params);
2560 out:
2561 TALLOC_FREE(smb_dname);
2562 return;
2565 /****************************************************************************
2566 Reply to a TRANS2_FINDNEXT.
2567 ****************************************************************************/
2569 static void call_trans2findnext(connection_struct *conn,
2570 struct smb_request *req,
2571 char **pparams, int total_params,
2572 char **ppdata, int total_data,
2573 unsigned int max_data_bytes)
2575 /* We must be careful here that we don't return more than the
2576 allowed number of data bytes. If this means returning fewer than
2577 maxentries then so be it. We assume that the redirector has
2578 enough room for the fixed number of parameter bytes it has
2579 requested. */
2580 char *params = *pparams;
2581 char *pdata = *ppdata;
2582 char *data_end;
2583 int dptr_num;
2584 int maxentries;
2585 uint16 info_level;
2586 uint32 resume_key;
2587 uint16 findnext_flags;
2588 bool close_after_request;
2589 bool close_if_end;
2590 bool requires_resume_key;
2591 bool continue_bit;
2592 bool mask_contains_wcard = False;
2593 char *resume_name = NULL;
2594 const char *mask = NULL;
2595 const char *directory = NULL;
2596 char *p = NULL;
2597 uint16 dirtype;
2598 int numentries = 0;
2599 int i, last_entry_off=0;
2600 bool finished = False;
2601 bool dont_descend = False;
2602 bool out_of_space = False;
2603 int space_remaining;
2604 struct ea_list *ea_list = NULL;
2605 NTSTATUS ntstatus = NT_STATUS_OK;
2606 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2607 TALLOC_CTX *ctx = talloc_tos();
2608 struct dptr_struct *dirptr;
2609 struct smbd_server_connection *sconn = req->sconn;
2611 if (total_params < 13) {
2612 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2613 return;
2616 dptr_num = SVAL(params,0);
2617 maxentries = SVAL(params,2);
2618 info_level = SVAL(params,4);
2619 resume_key = IVAL(params,6);
2620 findnext_flags = SVAL(params,10);
2621 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2622 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2623 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2624 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2626 if (!continue_bit) {
2627 /* We only need resume_name if continue_bit is zero. */
2628 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2629 params+12,
2630 total_params - 12, STR_TERMINATE, &ntstatus,
2631 &mask_contains_wcard);
2632 if (!NT_STATUS_IS_OK(ntstatus)) {
2633 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2634 complain (it thinks we're asking for the directory above the shared
2635 path or an invalid name). Catch this as the resume name is only compared, never used in
2636 a file access. JRA. */
2637 srvstr_pull_talloc(ctx, params, req->flags2,
2638 &resume_name, params+12,
2639 total_params - 12,
2640 STR_TERMINATE);
2642 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2643 reply_nterror(req, ntstatus);
2644 return;
2649 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2650 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2651 resume_key = %d resume name = %s continue=%d level = %d\n",
2652 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2653 requires_resume_key, resume_key,
2654 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2656 if (!maxentries) {
2657 /* W2K3 seems to treat zero as 1. */
2658 maxentries = 1;
2661 switch (info_level) {
2662 case SMB_FIND_INFO_STANDARD:
2663 case SMB_FIND_EA_SIZE:
2664 case SMB_FIND_EA_LIST:
2665 case SMB_FIND_FILE_DIRECTORY_INFO:
2666 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2667 case SMB_FIND_FILE_NAMES_INFO:
2668 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2669 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2670 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2671 break;
2672 case SMB_FIND_FILE_UNIX:
2673 case SMB_FIND_FILE_UNIX_INFO2:
2674 /* Always use filesystem for UNIX mtime query. */
2675 ask_sharemode = false;
2676 if (!lp_unix_extensions()) {
2677 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2678 return;
2680 break;
2681 default:
2682 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2683 return;
2686 if (info_level == SMB_FIND_EA_LIST) {
2687 uint32 ea_size;
2689 if (total_data < 4) {
2690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2691 return;
2694 ea_size = IVAL(pdata,0);
2695 if (ea_size != total_data) {
2696 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2697 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2698 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2699 return;
2702 if (!lp_ea_support(SNUM(conn))) {
2703 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2704 return;
2707 /* Pull out the list of names. */
2708 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2709 if (!ea_list) {
2710 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2711 return;
2715 *ppdata = (char *)SMB_REALLOC(
2716 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2717 if(*ppdata == NULL) {
2718 reply_nterror(req, NT_STATUS_NO_MEMORY);
2719 return;
2722 pdata = *ppdata;
2723 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2725 /* Realloc the params space */
2726 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2727 if(*pparams == NULL ) {
2728 reply_nterror(req, NT_STATUS_NO_MEMORY);
2729 return;
2732 params = *pparams;
2734 /* Check that the dptr is valid */
2735 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2736 reply_nterror(req, STATUS_NO_MORE_FILES);
2737 return;
2740 directory = dptr_path(sconn, dptr_num);
2742 /* Get the wildcard mask from the dptr */
2743 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2744 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2745 reply_nterror(req, STATUS_NO_MORE_FILES);
2746 return;
2749 mask = p;
2751 /* Get the attr mask from the dptr */
2752 dirtype = dptr_attr(sconn, dptr_num);
2754 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2755 dptr_num, mask, dirtype,
2756 (long)dirptr,
2757 dptr_TellDir(dirptr)));
2759 /* Initialize per TRANS2_FIND_NEXT operation data */
2760 dptr_init_search_op(dirptr);
2762 /* We don't need to check for VOL here as this is returned by
2763 a different TRANS2 call. */
2765 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2766 directory,lp_dontdescend(SNUM(conn))));
2767 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2768 dont_descend = True;
2770 p = pdata;
2771 space_remaining = max_data_bytes;
2772 out_of_space = False;
2775 * Seek to the correct position. We no longer use the resume key but
2776 * depend on the last file name instead.
2779 if(!continue_bit && resume_name && *resume_name) {
2780 SMB_STRUCT_STAT st;
2782 long current_pos = 0;
2784 * Remember, name_to_8_3 is called by
2785 * get_lanman2_dir_entry(), so the resume name
2786 * could be mangled. Ensure we check the unmangled name.
2789 if (mangle_is_mangled(resume_name, conn->params)) {
2790 char *new_resume_name = NULL;
2791 mangle_lookup_name_from_8_3(ctx,
2792 resume_name,
2793 &new_resume_name,
2794 conn->params);
2795 if (new_resume_name) {
2796 resume_name = new_resume_name;
2801 * Fix for NT redirector problem triggered by resume key indexes
2802 * changing between directory scans. We now return a resume key of 0
2803 * and instead look for the filename to continue from (also given
2804 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2805 * findfirst/findnext (as is usual) then the directory pointer
2806 * should already be at the correct place.
2809 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2810 } /* end if resume_name && !continue_bit */
2812 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2813 bool got_exact_match = False;
2815 /* this is a heuristic to avoid seeking the dirptr except when
2816 absolutely necessary. It allows for a filename of about 40 chars */
2817 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2818 out_of_space = True;
2819 finished = False;
2820 } else {
2821 finished = !get_lanman2_dir_entry(ctx,
2822 conn,
2823 dirptr,
2824 req->flags2,
2825 mask,dirtype,info_level,
2826 requires_resume_key,dont_descend,
2827 ask_sharemode,
2828 &p,pdata,data_end,
2829 space_remaining, &out_of_space,
2830 &got_exact_match,
2831 &last_entry_off, ea_list);
2834 if (finished && out_of_space)
2835 finished = False;
2837 if (!finished && !out_of_space)
2838 numentries++;
2841 * As an optimisation if we know we aren't looking
2842 * for a wildcard name (ie. the name matches the wildcard exactly)
2843 * then we can finish on any (first) match.
2844 * This speeds up large directory searches. JRA.
2847 if(got_exact_match)
2848 finished = True;
2850 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2853 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2854 smb_fn_name(req->cmd),
2855 mask, directory, dirtype, numentries ) );
2857 /* Check if we can close the dirptr */
2858 if(close_after_request || (finished && close_if_end)) {
2859 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2860 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2863 /* Set up the return parameter block */
2864 SSVAL(params,0,numentries);
2865 SSVAL(params,2,finished);
2866 SSVAL(params,4,0); /* Never an EA error */
2867 SSVAL(params,6,last_entry_off);
2869 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2870 max_data_bytes);
2872 return;
2875 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2877 E_md4hash(lp_servicename(SNUM(conn)),objid);
2878 return objid;
2881 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2883 SMB_ASSERT(extended_info != NULL);
2885 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2886 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2887 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2888 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2889 #ifdef SAMBA_VERSION_REVISION
2890 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2891 #endif
2892 extended_info->samba_subversion = 0;
2893 #ifdef SAMBA_VERSION_RC_RELEASE
2894 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2895 #else
2896 #ifdef SAMBA_VERSION_PRE_RELEASE
2897 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2898 #endif
2899 #endif
2900 #ifdef SAMBA_VERSION_VENDOR_PATCH
2901 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2902 #endif
2903 extended_info->samba_gitcommitdate = 0;
2904 #ifdef SAMBA_VERSION_COMMIT_TIME
2905 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2906 #endif
2908 memset(extended_info->samba_version_string, 0,
2909 sizeof(extended_info->samba_version_string));
2911 snprintf (extended_info->samba_version_string,
2912 sizeof(extended_info->samba_version_string),
2913 "%s", samba_version_string());
2916 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2917 TALLOC_CTX *mem_ctx,
2918 uint16_t info_level,
2919 uint16_t flags2,
2920 unsigned int max_data_bytes,
2921 char **ppdata,
2922 int *ret_data_len)
2924 char *pdata, *end_data;
2925 int data_len = 0, len;
2926 const char *vname = volume_label(SNUM(conn));
2927 int snum = SNUM(conn);
2928 char *fstype = lp_fstype(SNUM(conn));
2929 uint32 additional_flags = 0;
2930 struct smb_filename smb_fname_dot;
2931 SMB_STRUCT_STAT st;
2933 if (IS_IPC(conn)) {
2934 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2935 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2936 "info level (0x%x) on IPC$.\n",
2937 (unsigned int)info_level));
2938 return NT_STATUS_ACCESS_DENIED;
2942 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2944 ZERO_STRUCT(smb_fname_dot);
2945 smb_fname_dot.base_name = discard_const_p(char, ".");
2947 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2948 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2949 return map_nt_error_from_unix(errno);
2952 st = smb_fname_dot.st;
2954 *ppdata = (char *)SMB_REALLOC(
2955 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2956 if (*ppdata == NULL) {
2957 return NT_STATUS_NO_MEMORY;
2960 pdata = *ppdata;
2961 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2962 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2964 switch (info_level) {
2965 case SMB_INFO_ALLOCATION:
2967 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2968 data_len = 18;
2969 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2970 return map_nt_error_from_unix(errno);
2973 block_size = lp_block_size(snum);
2974 if (bsize < block_size) {
2975 uint64_t factor = block_size/bsize;
2976 bsize = block_size;
2977 dsize /= factor;
2978 dfree /= factor;
2980 if (bsize > block_size) {
2981 uint64_t factor = bsize/block_size;
2982 bsize = block_size;
2983 dsize *= factor;
2984 dfree *= factor;
2986 bytes_per_sector = 512;
2987 sectors_per_unit = bsize/bytes_per_sector;
2989 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2990 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2991 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2993 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2994 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2995 SIVAL(pdata,l1_cUnit,dsize);
2996 SIVAL(pdata,l1_cUnitAvail,dfree);
2997 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2998 break;
3001 case SMB_INFO_VOLUME:
3002 /* Return volume name */
3004 * Add volume serial number - hash of a combination of
3005 * the called hostname and the service name.
3007 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3009 * Win2k3 and previous mess this up by sending a name length
3010 * one byte short. I believe only older clients (OS/2 Win9x) use
3011 * this call so try fixing this by adding a terminating null to
3012 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3014 len = srvstr_push(
3015 pdata, flags2,
3016 pdata+l2_vol_szVolLabel, vname,
3017 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3018 STR_NOALIGN);
3019 SCVAL(pdata,l2_vol_cch,len);
3020 data_len = l2_vol_szVolLabel + len;
3021 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3022 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3023 len, vname));
3024 break;
3026 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3027 case SMB_FS_ATTRIBUTE_INFORMATION:
3029 additional_flags = 0;
3030 #if defined(HAVE_SYS_QUOTAS)
3031 additional_flags |= FILE_VOLUME_QUOTAS;
3032 #endif
3034 if(lp_nt_acl_support(SNUM(conn))) {
3035 additional_flags |= FILE_PERSISTENT_ACLS;
3038 /* Capabilities are filled in at connection time through STATVFS call */
3039 additional_flags |= conn->fs_capabilities;
3040 additional_flags |= lp_parm_int(conn->params->service,
3041 "share", "fake_fscaps",
3044 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3045 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3046 additional_flags); /* FS ATTRIBUTES */
3048 SIVAL(pdata,4,255); /* Max filename component length */
3049 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3050 and will think we can't do long filenames */
3051 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3052 PTR_DIFF(end_data, pdata+12),
3053 STR_UNICODE);
3054 SIVAL(pdata,8,len);
3055 data_len = 12 + len;
3056 break;
3058 case SMB_QUERY_FS_LABEL_INFO:
3059 case SMB_FS_LABEL_INFORMATION:
3060 len = srvstr_push(pdata, flags2, pdata+4, vname,
3061 PTR_DIFF(end_data, pdata+4), 0);
3062 data_len = 4 + len;
3063 SIVAL(pdata,0,len);
3064 break;
3066 case SMB_QUERY_FS_VOLUME_INFO:
3067 case SMB_FS_VOLUME_INFORMATION:
3070 * Add volume serial number - hash of a combination of
3071 * the called hostname and the service name.
3073 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3074 (str_checksum(get_local_machine_name())<<16));
3076 /* Max label len is 32 characters. */
3077 len = srvstr_push(pdata, flags2, pdata+18, vname,
3078 PTR_DIFF(end_data, pdata+18),
3079 STR_UNICODE);
3080 SIVAL(pdata,12,len);
3081 data_len = 18+len;
3083 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3084 (int)strlen(vname),vname, lp_servicename(snum)));
3085 break;
3087 case SMB_QUERY_FS_SIZE_INFO:
3088 case SMB_FS_SIZE_INFORMATION:
3090 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3091 data_len = 24;
3092 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3093 return map_nt_error_from_unix(errno);
3095 block_size = lp_block_size(snum);
3096 if (bsize < block_size) {
3097 uint64_t factor = block_size/bsize;
3098 bsize = block_size;
3099 dsize /= factor;
3100 dfree /= factor;
3102 if (bsize > block_size) {
3103 uint64_t factor = bsize/block_size;
3104 bsize = block_size;
3105 dsize *= factor;
3106 dfree *= factor;
3108 bytes_per_sector = 512;
3109 sectors_per_unit = bsize/bytes_per_sector;
3110 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3111 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3112 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3113 SBIG_UINT(pdata,0,dsize);
3114 SBIG_UINT(pdata,8,dfree);
3115 SIVAL(pdata,16,sectors_per_unit);
3116 SIVAL(pdata,20,bytes_per_sector);
3117 break;
3120 case SMB_FS_FULL_SIZE_INFORMATION:
3122 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3123 data_len = 32;
3124 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3125 return map_nt_error_from_unix(errno);
3127 block_size = lp_block_size(snum);
3128 if (bsize < block_size) {
3129 uint64_t factor = block_size/bsize;
3130 bsize = block_size;
3131 dsize /= factor;
3132 dfree /= factor;
3134 if (bsize > block_size) {
3135 uint64_t factor = bsize/block_size;
3136 bsize = block_size;
3137 dsize *= factor;
3138 dfree *= factor;
3140 bytes_per_sector = 512;
3141 sectors_per_unit = bsize/bytes_per_sector;
3142 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3143 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3144 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3145 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3146 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3147 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3148 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3149 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3150 break;
3153 case SMB_QUERY_FS_DEVICE_INFO:
3154 case SMB_FS_DEVICE_INFORMATION:
3156 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3158 if (!CAN_WRITE(conn)) {
3159 characteristics |= FILE_READ_ONLY_DEVICE;
3161 data_len = 8;
3162 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3163 SIVAL(pdata,4,characteristics);
3164 break;
3167 #ifdef HAVE_SYS_QUOTAS
3168 case SMB_FS_QUOTA_INFORMATION:
3170 * what we have to send --metze:
3172 * Unknown1: 24 NULL bytes
3173 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3174 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3175 * Quota Flags: 2 byte :
3176 * Unknown3: 6 NULL bytes
3178 * 48 bytes total
3180 * details for Quota Flags:
3182 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3183 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3184 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3185 * 0x0001 Enable Quotas: enable quota for this fs
3189 /* we need to fake up a fsp here,
3190 * because its not send in this call
3192 files_struct fsp;
3193 SMB_NTQUOTA_STRUCT quotas;
3195 ZERO_STRUCT(fsp);
3196 ZERO_STRUCT(quotas);
3198 fsp.conn = conn;
3199 fsp.fnum = -1;
3201 /* access check */
3202 if (conn->session_info->utok.uid != sec_initial_uid()) {
3203 DEBUG(0,("set_user_quota: access_denied "
3204 "service [%s] user [%s]\n",
3205 lp_servicename(SNUM(conn)),
3206 conn->session_info->unix_name));
3207 return NT_STATUS_ACCESS_DENIED;
3210 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3211 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3212 return map_nt_error_from_unix(errno);
3215 data_len = 48;
3217 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3218 lp_servicename(SNUM(conn))));
3220 /* Unknown1 24 NULL bytes*/
3221 SBIG_UINT(pdata,0,(uint64_t)0);
3222 SBIG_UINT(pdata,8,(uint64_t)0);
3223 SBIG_UINT(pdata,16,(uint64_t)0);
3225 /* Default Soft Quota 8 bytes */
3226 SBIG_UINT(pdata,24,quotas.softlim);
3228 /* Default Hard Quota 8 bytes */
3229 SBIG_UINT(pdata,32,quotas.hardlim);
3231 /* Quota flag 2 bytes */
3232 SSVAL(pdata,40,quotas.qflags);
3234 /* Unknown3 6 NULL bytes */
3235 SSVAL(pdata,42,0);
3236 SIVAL(pdata,44,0);
3238 break;
3240 #endif /* HAVE_SYS_QUOTAS */
3241 case SMB_FS_OBJECTID_INFORMATION:
3243 unsigned char objid[16];
3244 struct smb_extended_info extended_info;
3245 memcpy(pdata,create_volume_objectid(conn, objid),16);
3246 samba_extended_info_version (&extended_info);
3247 SIVAL(pdata,16,extended_info.samba_magic);
3248 SIVAL(pdata,20,extended_info.samba_version);
3249 SIVAL(pdata,24,extended_info.samba_subversion);
3250 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3251 memcpy(pdata+36,extended_info.samba_version_string,28);
3252 data_len = 64;
3253 break;
3257 * Query the version and capabilities of the CIFS UNIX extensions
3258 * in use.
3261 case SMB_QUERY_CIFS_UNIX_INFO:
3263 bool large_write = lp_min_receive_file_size() &&
3264 !srv_is_signing_active(conn->sconn);
3265 bool large_read = !srv_is_signing_active(conn->sconn);
3266 int encrypt_caps = 0;
3268 if (!lp_unix_extensions()) {
3269 return NT_STATUS_INVALID_LEVEL;
3272 switch (conn->encrypt_level) {
3273 case 0:
3274 encrypt_caps = 0;
3275 break;
3276 case 1:
3277 case Auto:
3278 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3279 break;
3280 case Required:
3281 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3282 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3283 large_write = false;
3284 large_read = false;
3285 break;
3288 data_len = 12;
3289 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3290 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3292 /* We have POSIX ACLs, pathname, encryption,
3293 * large read/write, and locking capability. */
3295 SBIG_UINT(pdata,4,((uint64_t)(
3296 CIFS_UNIX_POSIX_ACLS_CAP|
3297 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3298 CIFS_UNIX_FCNTL_LOCKS_CAP|
3299 CIFS_UNIX_EXTATTR_CAP|
3300 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3301 encrypt_caps|
3302 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3303 (large_write ?
3304 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3305 break;
3308 case SMB_QUERY_POSIX_FS_INFO:
3310 int rc;
3311 vfs_statvfs_struct svfs;
3313 if (!lp_unix_extensions()) {
3314 return NT_STATUS_INVALID_LEVEL;
3317 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3319 if (!rc) {
3320 data_len = 56;
3321 SIVAL(pdata,0,svfs.OptimalTransferSize);
3322 SIVAL(pdata,4,svfs.BlockSize);
3323 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3324 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3325 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3326 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3327 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3328 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3329 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3330 #ifdef EOPNOTSUPP
3331 } else if (rc == EOPNOTSUPP) {
3332 return NT_STATUS_INVALID_LEVEL;
3333 #endif /* EOPNOTSUPP */
3334 } else {
3335 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3336 return NT_STATUS_DOS(ERRSRV, ERRerror);
3338 break;
3341 case SMB_QUERY_POSIX_WHOAMI:
3343 uint32_t flags = 0;
3344 uint32_t sid_bytes;
3345 int i;
3347 if (!lp_unix_extensions()) {
3348 return NT_STATUS_INVALID_LEVEL;
3351 if (max_data_bytes < 40) {
3352 return NT_STATUS_BUFFER_TOO_SMALL;
3355 /* We ARE guest if global_sid_Builtin_Guests is
3356 * in our list of SIDs.
3358 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3359 conn->session_info->security_token)) {
3360 flags |= SMB_WHOAMI_GUEST;
3363 /* We are NOT guest if global_sid_Authenticated_Users
3364 * is in our list of SIDs.
3366 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3367 conn->session_info->security_token)) {
3368 flags &= ~SMB_WHOAMI_GUEST;
3371 /* NOTE: 8 bytes for UID/GID, irrespective of native
3372 * platform size. This matches
3373 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3375 data_len = 4 /* flags */
3376 + 4 /* flag mask */
3377 + 8 /* uid */
3378 + 8 /* gid */
3379 + 4 /* ngroups */
3380 + 4 /* num_sids */
3381 + 4 /* SID bytes */
3382 + 4 /* pad/reserved */
3383 + (conn->session_info->utok.ngroups * 8)
3384 /* groups list */
3385 + (conn->session_info->security_token->num_sids *
3386 SID_MAX_SIZE)
3387 /* SID list */;
3389 SIVAL(pdata, 0, flags);
3390 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3391 SBIG_UINT(pdata, 8,
3392 (uint64_t)conn->session_info->utok.uid);
3393 SBIG_UINT(pdata, 16,
3394 (uint64_t)conn->session_info->utok.gid);
3397 if (data_len >= max_data_bytes) {
3398 /* Potential overflow, skip the GIDs and SIDs. */
3400 SIVAL(pdata, 24, 0); /* num_groups */
3401 SIVAL(pdata, 28, 0); /* num_sids */
3402 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3403 SIVAL(pdata, 36, 0); /* reserved */
3405 data_len = 40;
3406 break;
3409 SIVAL(pdata, 24, conn->session_info->utok.ngroups);
3410 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3412 /* We walk the SID list twice, but this call is fairly
3413 * infrequent, and I don't expect that it's performance
3414 * sensitive -- jpeach
3416 for (i = 0, sid_bytes = 0;
3417 i < conn->session_info->security_token->num_sids; ++i) {
3418 sid_bytes += ndr_size_dom_sid(
3419 &conn->session_info->security_token->sids[i],
3423 /* SID list byte count */
3424 SIVAL(pdata, 32, sid_bytes);
3426 /* 4 bytes pad/reserved - must be zero */
3427 SIVAL(pdata, 36, 0);
3428 data_len = 40;
3430 /* GID list */
3431 for (i = 0; i < conn->session_info->utok.ngroups; ++i) {
3432 SBIG_UINT(pdata, data_len,
3433 (uint64_t)conn->session_info->utok.groups[i]);
3434 data_len += 8;
3437 /* SID list */
3438 for (i = 0;
3439 i < conn->session_info->security_token->num_sids; ++i) {
3440 int sid_len = ndr_size_dom_sid(
3441 &conn->session_info->security_token->sids[i],
3444 sid_linearize(pdata + data_len, sid_len,
3445 &conn->session_info->security_token->sids[i]);
3446 data_len += sid_len;
3449 break;
3452 case SMB_MAC_QUERY_FS_INFO:
3454 * Thursby MAC extension... ONLY on NTFS filesystems
3455 * once we do streams then we don't need this
3457 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3458 data_len = 88;
3459 SIVAL(pdata,84,0x100); /* Don't support mac... */
3460 break;
3462 /* drop through */
3463 default:
3464 return NT_STATUS_INVALID_LEVEL;
3467 *ret_data_len = data_len;
3468 return NT_STATUS_OK;
3471 /****************************************************************************
3472 Reply to a TRANS2_QFSINFO (query filesystem info).
3473 ****************************************************************************/
3475 static void call_trans2qfsinfo(connection_struct *conn,
3476 struct smb_request *req,
3477 char **pparams, int total_params,
3478 char **ppdata, int total_data,
3479 unsigned int max_data_bytes)
3481 char *params = *pparams;
3482 uint16_t info_level;
3483 int data_len = 0;
3484 NTSTATUS status;
3486 if (total_params < 2) {
3487 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3488 return;
3491 info_level = SVAL(params,0);
3493 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3494 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3495 DEBUG(0,("call_trans2qfsinfo: encryption required "
3496 "and info level 0x%x sent.\n",
3497 (unsigned int)info_level));
3498 exit_server_cleanly("encryption required "
3499 "on connection");
3500 return;
3504 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3506 status = smbd_do_qfsinfo(conn, req,
3507 info_level,
3508 req->flags2,
3509 max_data_bytes,
3510 ppdata, &data_len);
3511 if (!NT_STATUS_IS_OK(status)) {
3512 reply_nterror(req, status);
3513 return;
3516 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3517 max_data_bytes);
3519 DEBUG( 4, ( "%s info_level = %d\n",
3520 smb_fn_name(req->cmd), info_level) );
3522 return;
3525 /****************************************************************************
3526 Reply to a TRANS2_SETFSINFO (set filesystem info).
3527 ****************************************************************************/
3529 static void call_trans2setfsinfo(connection_struct *conn,
3530 struct smb_request *req,
3531 char **pparams, int total_params,
3532 char **ppdata, int total_data,
3533 unsigned int max_data_bytes)
3535 char *pdata = *ppdata;
3536 char *params = *pparams;
3537 uint16 info_level;
3539 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3541 /* */
3542 if (total_params < 4) {
3543 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3544 total_params));
3545 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3546 return;
3549 info_level = SVAL(params,2);
3551 if (IS_IPC(conn)) {
3552 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3553 info_level != SMB_SET_CIFS_UNIX_INFO) {
3554 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3555 "info level (0x%x) on IPC$.\n",
3556 (unsigned int)info_level));
3557 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3558 return;
3562 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3563 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3564 DEBUG(0,("call_trans2setfsinfo: encryption required "
3565 "and info level 0x%x sent.\n",
3566 (unsigned int)info_level));
3567 exit_server_cleanly("encryption required "
3568 "on connection");
3569 return;
3573 switch(info_level) {
3574 case SMB_SET_CIFS_UNIX_INFO:
3576 uint16 client_unix_major;
3577 uint16 client_unix_minor;
3578 uint32 client_unix_cap_low;
3579 uint32 client_unix_cap_high;
3581 if (!lp_unix_extensions()) {
3582 reply_nterror(req,
3583 NT_STATUS_INVALID_LEVEL);
3584 return;
3587 /* There should be 12 bytes of capabilities set. */
3588 if (total_data < 8) {
3589 reply_nterror(
3590 req,
3591 NT_STATUS_INVALID_PARAMETER);
3592 return;
3594 client_unix_major = SVAL(pdata,0);
3595 client_unix_minor = SVAL(pdata,2);
3596 client_unix_cap_low = IVAL(pdata,4);
3597 client_unix_cap_high = IVAL(pdata,8);
3598 /* Just print these values for now. */
3599 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3600 cap_low = 0x%x, cap_high = 0x%x\n",
3601 (unsigned int)client_unix_major,
3602 (unsigned int)client_unix_minor,
3603 (unsigned int)client_unix_cap_low,
3604 (unsigned int)client_unix_cap_high ));
3606 /* Here is where we must switch to posix pathname processing... */
3607 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3608 lp_set_posix_pathnames();
3609 mangle_change_to_posix();
3612 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3613 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3614 /* Client that knows how to do posix locks,
3615 * but not posix open/mkdir operations. Set a
3616 * default type for read/write checks. */
3618 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3621 break;
3624 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3626 NTSTATUS status;
3627 size_t param_len = 0;
3628 size_t data_len = total_data;
3630 if (!lp_unix_extensions()) {
3631 reply_nterror(
3632 req,
3633 NT_STATUS_INVALID_LEVEL);
3634 return;
3637 if (lp_smb_encrypt(SNUM(conn)) == false) {
3638 reply_nterror(
3639 req,
3640 NT_STATUS_NOT_SUPPORTED);
3641 return;
3644 if (req->sconn->smb1.echo_handler.trusted_fde) {
3645 DEBUG( 2,("call_trans2setfsinfo: "
3646 "request transport encryption disabled"
3647 "with 'fork echo handler = yes'\n"));
3648 reply_nterror(
3649 req,
3650 NT_STATUS_NOT_SUPPORTED);
3651 return;
3654 DEBUG( 4,("call_trans2setfsinfo: "
3655 "request transport encryption.\n"));
3657 status = srv_request_encryption_setup(conn,
3658 (unsigned char **)ppdata,
3659 &data_len,
3660 (unsigned char **)pparams,
3661 &param_len);
3663 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3664 !NT_STATUS_IS_OK(status)) {
3665 reply_nterror(req, status);
3666 return;
3669 send_trans2_replies(conn, req,
3670 *pparams,
3671 param_len,
3672 *ppdata,
3673 data_len,
3674 max_data_bytes);
3676 if (NT_STATUS_IS_OK(status)) {
3677 /* Server-side transport
3678 * encryption is now *on*. */
3679 status = srv_encryption_start(conn);
3680 if (!NT_STATUS_IS_OK(status)) {
3681 exit_server_cleanly(
3682 "Failure in setting "
3683 "up encrypted transport");
3686 return;
3689 case SMB_FS_QUOTA_INFORMATION:
3691 files_struct *fsp = NULL;
3692 SMB_NTQUOTA_STRUCT quotas;
3694 ZERO_STRUCT(quotas);
3696 /* access check */
3697 if ((conn->session_info->utok.uid != sec_initial_uid())
3698 ||!CAN_WRITE(conn)) {
3699 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3700 lp_servicename(SNUM(conn)),
3701 conn->session_info->unix_name));
3702 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3703 return;
3706 /* note: normaly there're 48 bytes,
3707 * but we didn't use the last 6 bytes for now
3708 * --metze
3710 fsp = file_fsp(req, SVAL(params,0));
3712 if (!check_fsp_ntquota_handle(conn, req,
3713 fsp)) {
3714 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3715 reply_nterror(
3716 req, NT_STATUS_INVALID_HANDLE);
3717 return;
3720 if (total_data < 42) {
3721 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3722 total_data));
3723 reply_nterror(
3724 req,
3725 NT_STATUS_INVALID_PARAMETER);
3726 return;
3729 /* unknown_1 24 NULL bytes in pdata*/
3731 /* the soft quotas 8 bytes (uint64_t)*/
3732 quotas.softlim = (uint64_t)IVAL(pdata,24);
3733 #ifdef LARGE_SMB_OFF_T
3734 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3735 #else /* LARGE_SMB_OFF_T */
3736 if ((IVAL(pdata,28) != 0)&&
3737 ((quotas.softlim != 0xFFFFFFFF)||
3738 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3739 /* more than 32 bits? */
3740 reply_nterror(
3741 req,
3742 NT_STATUS_INVALID_PARAMETER);
3743 return;
3745 #endif /* LARGE_SMB_OFF_T */
3747 /* the hard quotas 8 bytes (uint64_t)*/
3748 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3749 #ifdef LARGE_SMB_OFF_T
3750 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3751 #else /* LARGE_SMB_OFF_T */
3752 if ((IVAL(pdata,36) != 0)&&
3753 ((quotas.hardlim != 0xFFFFFFFF)||
3754 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3755 /* more than 32 bits? */
3756 reply_nterror(
3757 req,
3758 NT_STATUS_INVALID_PARAMETER);
3759 return;
3761 #endif /* LARGE_SMB_OFF_T */
3763 /* quota_flags 2 bytes **/
3764 quotas.qflags = SVAL(pdata,40);
3766 /* unknown_2 6 NULL bytes follow*/
3768 /* now set the quotas */
3769 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3770 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3771 reply_nterror(req, map_nt_error_from_unix(errno));
3772 return;
3775 break;
3777 default:
3778 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3779 info_level));
3780 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3781 return;
3782 break;
3786 * sending this reply works fine,
3787 * but I'm not sure it's the same
3788 * like windows do...
3789 * --metze
3791 reply_outbuf(req, 10, 0);
3794 #if defined(HAVE_POSIX_ACLS)
3795 /****************************************************************************
3796 Utility function to count the number of entries in a POSIX acl.
3797 ****************************************************************************/
3799 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3801 unsigned int ace_count = 0;
3802 int entry_id = SMB_ACL_FIRST_ENTRY;
3803 SMB_ACL_ENTRY_T entry;
3805 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3806 /* get_next... */
3807 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3808 entry_id = SMB_ACL_NEXT_ENTRY;
3810 ace_count++;
3812 return ace_count;
3815 /****************************************************************************
3816 Utility function to marshall a POSIX acl into wire format.
3817 ****************************************************************************/
3819 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3821 int entry_id = SMB_ACL_FIRST_ENTRY;
3822 SMB_ACL_ENTRY_T entry;
3824 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3825 SMB_ACL_TAG_T tagtype;
3826 SMB_ACL_PERMSET_T permset;
3827 unsigned char perms = 0;
3828 unsigned int own_grp;
3830 /* get_next... */
3831 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3832 entry_id = SMB_ACL_NEXT_ENTRY;
3835 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3836 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3837 return False;
3840 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3841 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3842 return False;
3845 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3846 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3847 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3849 SCVAL(pdata,1,perms);
3851 switch (tagtype) {
3852 case SMB_ACL_USER_OBJ:
3853 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3854 own_grp = (unsigned int)pst->st_ex_uid;
3855 SIVAL(pdata,2,own_grp);
3856 SIVAL(pdata,6,0);
3857 break;
3858 case SMB_ACL_USER:
3860 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3861 if (!puid) {
3862 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3863 return False;
3865 own_grp = (unsigned int)*puid;
3866 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3867 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3868 SIVAL(pdata,2,own_grp);
3869 SIVAL(pdata,6,0);
3870 break;
3872 case SMB_ACL_GROUP_OBJ:
3873 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3874 own_grp = (unsigned int)pst->st_ex_gid;
3875 SIVAL(pdata,2,own_grp);
3876 SIVAL(pdata,6,0);
3877 break;
3878 case SMB_ACL_GROUP:
3880 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3881 if (!pgid) {
3882 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3883 return False;
3885 own_grp = (unsigned int)*pgid;
3886 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3887 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3888 SIVAL(pdata,2,own_grp);
3889 SIVAL(pdata,6,0);
3890 break;
3892 case SMB_ACL_MASK:
3893 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3894 SIVAL(pdata,2,0xFFFFFFFF);
3895 SIVAL(pdata,6,0xFFFFFFFF);
3896 break;
3897 case SMB_ACL_OTHER:
3898 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3899 SIVAL(pdata,2,0xFFFFFFFF);
3900 SIVAL(pdata,6,0xFFFFFFFF);
3901 break;
3902 default:
3903 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3904 return False;
3906 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3909 return True;
3911 #endif
3913 /****************************************************************************
3914 Store the FILE_UNIX_BASIC info.
3915 ****************************************************************************/
3917 static char *store_file_unix_basic(connection_struct *conn,
3918 char *pdata,
3919 files_struct *fsp,
3920 const SMB_STRUCT_STAT *psbuf)
3922 uint64_t file_index = get_FileIndex(conn, psbuf);
3924 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3925 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3927 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3928 pdata += 8;
3930 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3931 pdata += 8;
3933 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3934 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3935 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3936 pdata += 24;
3938 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3939 SIVAL(pdata,4,0);
3940 pdata += 8;
3942 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3943 SIVAL(pdata,4,0);
3944 pdata += 8;
3946 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3947 pdata += 4;
3949 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3950 SIVAL(pdata,4,0);
3951 pdata += 8;
3953 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3954 SIVAL(pdata,4,0);
3955 pdata += 8;
3957 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3958 pdata += 8;
3960 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3961 SIVAL(pdata,4,0);
3962 pdata += 8;
3964 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3965 SIVAL(pdata,4,0);
3966 pdata += 8;
3968 return pdata;
3971 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3972 * the chflags(2) (or equivalent) flags.
3974 * XXX: this really should be behind the VFS interface. To do this, we would
3975 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3976 * Each VFS module could then implement its own mapping as appropriate for the
3977 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3979 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3980 info2_flags_map[] =
3982 #ifdef UF_NODUMP
3983 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3984 #endif
3986 #ifdef UF_IMMUTABLE
3987 { UF_IMMUTABLE, EXT_IMMUTABLE },
3988 #endif
3990 #ifdef UF_APPEND
3991 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3992 #endif
3994 #ifdef UF_HIDDEN
3995 { UF_HIDDEN, EXT_HIDDEN },
3996 #endif
3998 /* Do not remove. We need to guarantee that this array has at least one
3999 * entry to build on HP-UX.
4001 { 0, 0 }
4005 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4006 uint32 *smb_fflags, uint32 *smb_fmask)
4008 int i;
4010 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4011 *smb_fmask |= info2_flags_map[i].smb_fflag;
4012 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4013 *smb_fflags |= info2_flags_map[i].smb_fflag;
4018 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4019 const uint32 smb_fflags,
4020 const uint32 smb_fmask,
4021 int *stat_fflags)
4023 uint32 max_fmask = 0;
4024 int i;
4026 *stat_fflags = psbuf->st_ex_flags;
4028 /* For each flags requested in smb_fmask, check the state of the
4029 * corresponding flag in smb_fflags and set or clear the matching
4030 * stat flag.
4033 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4034 max_fmask |= info2_flags_map[i].smb_fflag;
4035 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4036 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4037 *stat_fflags |= info2_flags_map[i].stat_fflag;
4038 } else {
4039 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4044 /* If smb_fmask is asking to set any bits that are not supported by
4045 * our flag mappings, we should fail.
4047 if ((smb_fmask & max_fmask) != smb_fmask) {
4048 return False;
4051 return True;
4055 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4056 * of file flags and birth (create) time.
4058 static char *store_file_unix_basic_info2(connection_struct *conn,
4059 char *pdata,
4060 files_struct *fsp,
4061 const SMB_STRUCT_STAT *psbuf)
4063 uint32 file_flags = 0;
4064 uint32 flags_mask = 0;
4066 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4068 /* Create (birth) time 64 bit */
4069 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4070 pdata += 8;
4072 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4073 SIVAL(pdata, 0, file_flags); /* flags */
4074 SIVAL(pdata, 4, flags_mask); /* mask */
4075 pdata += 8;
4077 return pdata;
4080 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4081 const struct stream_struct *streams,
4082 char *data,
4083 unsigned int max_data_bytes,
4084 unsigned int *data_size)
4086 unsigned int i;
4087 unsigned int ofs = 0;
4089 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4090 unsigned int next_offset;
4091 size_t namelen;
4092 smb_ucs2_t *namebuf;
4094 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4095 streams[i].name, &namelen) ||
4096 namelen <= 2)
4098 return NT_STATUS_INVALID_PARAMETER;
4102 * name_buf is now null-terminated, we need to marshall as not
4103 * terminated
4106 namelen -= 2;
4108 SIVAL(data, ofs+4, namelen);
4109 SOFF_T(data, ofs+8, streams[i].size);
4110 SOFF_T(data, ofs+16, streams[i].alloc_size);
4111 memcpy(data+ofs+24, namebuf, namelen);
4112 TALLOC_FREE(namebuf);
4114 next_offset = ofs + 24 + namelen;
4116 if (i == num_streams-1) {
4117 SIVAL(data, ofs, 0);
4119 else {
4120 unsigned int align = ndr_align_size(next_offset, 8);
4122 memset(data+next_offset, 0, align);
4123 next_offset += align;
4125 SIVAL(data, ofs, next_offset - ofs);
4126 ofs = next_offset;
4129 ofs = next_offset;
4132 *data_size = ofs;
4134 return NT_STATUS_OK;
4137 /****************************************************************************
4138 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4139 ****************************************************************************/
4141 static void call_trans2qpipeinfo(connection_struct *conn,
4142 struct smb_request *req,
4143 unsigned int tran_call,
4144 char **pparams, int total_params,
4145 char **ppdata, int total_data,
4146 unsigned int max_data_bytes)
4148 char *params = *pparams;
4149 char *pdata = *ppdata;
4150 unsigned int data_size = 0;
4151 unsigned int param_size = 2;
4152 uint16 info_level;
4153 files_struct *fsp;
4155 if (!params) {
4156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4157 return;
4160 if (total_params < 4) {
4161 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4162 return;
4165 fsp = file_fsp(req, SVAL(params,0));
4166 if (!fsp_is_np(fsp)) {
4167 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4168 return;
4171 info_level = SVAL(params,2);
4173 *pparams = (char *)SMB_REALLOC(*pparams,2);
4174 if (*pparams == NULL) {
4175 reply_nterror(req, NT_STATUS_NO_MEMORY);
4176 return;
4178 params = *pparams;
4179 SSVAL(params,0,0);
4180 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4181 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4182 if (*ppdata == NULL ) {
4183 reply_nterror(req, NT_STATUS_NO_MEMORY);
4184 return;
4186 pdata = *ppdata;
4188 switch (info_level) {
4189 case SMB_FILE_STANDARD_INFORMATION:
4190 memset(pdata,0,24);
4191 SOFF_T(pdata,0,4096LL);
4192 SIVAL(pdata,16,1);
4193 SIVAL(pdata,20,1);
4194 data_size = 24;
4195 break;
4197 default:
4198 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4199 return;
4202 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4203 max_data_bytes);
4205 return;
4208 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4209 TALLOC_CTX *mem_ctx,
4210 uint16_t info_level,
4211 files_struct *fsp,
4212 struct smb_filename *smb_fname,
4213 bool delete_pending,
4214 struct timespec write_time_ts,
4215 struct ea_list *ea_list,
4216 int lock_data_count,
4217 char *lock_data,
4218 uint16_t flags2,
4219 unsigned int max_data_bytes,
4220 char **ppdata,
4221 unsigned int *pdata_size)
4223 char *pdata = *ppdata;
4224 char *dstart, *dend;
4225 unsigned int data_size;
4226 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4227 time_t create_time, mtime, atime, c_time;
4228 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4229 char *p;
4230 char *base_name;
4231 char *dos_fname;
4232 int mode;
4233 int nlink;
4234 NTSTATUS status;
4235 uint64_t file_size = 0;
4236 uint64_t pos = 0;
4237 uint64_t allocation_size = 0;
4238 uint64_t file_index = 0;
4239 uint32_t access_mask = 0;
4241 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4242 return NT_STATUS_INVALID_LEVEL;
4245 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4246 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4247 info_level, max_data_bytes));
4249 mode = dos_mode(conn, smb_fname);
4250 nlink = psbuf->st_ex_nlink;
4252 if (nlink && (mode&aDIR)) {
4253 nlink = 1;
4256 if ((nlink > 0) && delete_pending) {
4257 nlink -= 1;
4260 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4261 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4262 if (*ppdata == NULL) {
4263 return NT_STATUS_NO_MEMORY;
4265 pdata = *ppdata;
4266 dstart = pdata;
4267 dend = dstart + data_size - 1;
4269 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4270 update_stat_ex_mtime(psbuf, write_time_ts);
4273 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4274 mtime_ts = psbuf->st_ex_mtime;
4275 atime_ts = psbuf->st_ex_atime;
4276 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4278 if (lp_dos_filetime_resolution(SNUM(conn))) {
4279 dos_filetime_timespec(&create_time_ts);
4280 dos_filetime_timespec(&mtime_ts);
4281 dos_filetime_timespec(&atime_ts);
4282 dos_filetime_timespec(&ctime_ts);
4285 create_time = convert_timespec_to_time_t(create_time_ts);
4286 mtime = convert_timespec_to_time_t(mtime_ts);
4287 atime = convert_timespec_to_time_t(atime_ts);
4288 c_time = convert_timespec_to_time_t(ctime_ts);
4290 p = strrchr_m(smb_fname->base_name,'/');
4291 if (!p)
4292 base_name = smb_fname->base_name;
4293 else
4294 base_name = p+1;
4296 /* NT expects the name to be in an exact form of the *full*
4297 filename. See the trans2 torture test */
4298 if (ISDOT(base_name)) {
4299 dos_fname = talloc_strdup(mem_ctx, "\\");
4300 if (!dos_fname) {
4301 return NT_STATUS_NO_MEMORY;
4303 } else {
4304 dos_fname = talloc_asprintf(mem_ctx,
4305 "\\%s",
4306 smb_fname->base_name);
4307 if (!dos_fname) {
4308 return NT_STATUS_NO_MEMORY;
4310 if (is_ntfs_stream_smb_fname(smb_fname)) {
4311 dos_fname = talloc_asprintf(dos_fname, "%s",
4312 smb_fname->stream_name);
4313 if (!dos_fname) {
4314 return NT_STATUS_NO_MEMORY;
4318 string_replace(dos_fname, '/', '\\');
4321 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4323 if (!fsp) {
4324 /* Do we have this path open ? */
4325 files_struct *fsp1;
4326 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4327 fsp1 = file_find_di_first(conn->sconn, fileid);
4328 if (fsp1 && fsp1->initial_allocation_size) {
4329 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4333 if (!(mode & aDIR)) {
4334 file_size = get_file_size_stat(psbuf);
4337 if (fsp) {
4338 pos = fsp->fh->position_information;
4341 if (fsp) {
4342 access_mask = fsp->access_mask;
4343 } else {
4344 /* GENERIC_EXECUTE mapping from Windows */
4345 access_mask = 0x12019F;
4348 /* This should be an index number - looks like
4349 dev/ino to me :-)
4351 I think this causes us to fail the IFSKIT
4352 BasicFileInformationTest. -tpot */
4353 file_index = get_FileIndex(conn, psbuf);
4355 switch (info_level) {
4356 case SMB_INFO_STANDARD:
4357 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4358 data_size = 22;
4359 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4360 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4361 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4362 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4363 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4364 SSVAL(pdata,l1_attrFile,mode);
4365 break;
4367 case SMB_INFO_QUERY_EA_SIZE:
4369 unsigned int ea_size =
4370 estimate_ea_size(conn, fsp,
4371 smb_fname->base_name);
4372 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4373 data_size = 26;
4374 srv_put_dos_date2(pdata,0,create_time);
4375 srv_put_dos_date2(pdata,4,atime);
4376 srv_put_dos_date2(pdata,8,mtime); /* write time */
4377 SIVAL(pdata,12,(uint32)file_size);
4378 SIVAL(pdata,16,(uint32)allocation_size);
4379 SSVAL(pdata,20,mode);
4380 SIVAL(pdata,22,ea_size);
4381 break;
4384 case SMB_INFO_IS_NAME_VALID:
4385 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4386 if (fsp) {
4387 /* os/2 needs this ? really ?*/
4388 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4390 /* This is only reached for qpathinfo */
4391 data_size = 0;
4392 break;
4394 case SMB_INFO_QUERY_EAS_FROM_LIST:
4396 size_t total_ea_len = 0;
4397 struct ea_list *ea_file_list = NULL;
4399 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4401 ea_file_list =
4402 get_ea_list_from_file(mem_ctx, conn, fsp,
4403 smb_fname->base_name,
4404 &total_ea_len);
4405 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4407 if (!ea_list || (total_ea_len > data_size)) {
4408 data_size = 4;
4409 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4410 break;
4413 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4414 break;
4417 case SMB_INFO_QUERY_ALL_EAS:
4419 /* We have data_size bytes to put EA's into. */
4420 size_t total_ea_len = 0;
4422 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4424 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4425 smb_fname->base_name,
4426 &total_ea_len);
4427 if (!ea_list || (total_ea_len > data_size)) {
4428 data_size = 4;
4429 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4430 break;
4433 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4434 break;
4437 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4439 /* This is FileFullEaInformation - 0xF which maps to
4440 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4442 /* We have data_size bytes to put EA's into. */
4443 size_t total_ea_len = 0;
4444 struct ea_list *ea_file_list = NULL;
4446 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4448 /*TODO: add filtering and index handling */
4450 ea_file_list =
4451 get_ea_list_from_file(mem_ctx, conn, fsp,
4452 smb_fname->base_name,
4453 &total_ea_len);
4454 if (!ea_file_list) {
4455 return NT_STATUS_NO_EAS_ON_FILE;
4458 status = fill_ea_chained_buffer(mem_ctx,
4459 pdata,
4460 data_size,
4461 &data_size,
4462 conn, ea_file_list);
4463 if (!NT_STATUS_IS_OK(status)) {
4464 return status;
4466 break;
4469 case SMB_FILE_BASIC_INFORMATION:
4470 case SMB_QUERY_FILE_BASIC_INFO:
4472 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4473 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4474 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4475 } else {
4476 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4477 data_size = 40;
4478 SIVAL(pdata,36,0);
4480 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4481 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4482 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4483 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4484 SIVAL(pdata,32,mode);
4486 DEBUG(5,("SMB_QFBI - "));
4487 DEBUG(5,("create: %s ", ctime(&create_time)));
4488 DEBUG(5,("access: %s ", ctime(&atime)));
4489 DEBUG(5,("write: %s ", ctime(&mtime)));
4490 DEBUG(5,("change: %s ", ctime(&c_time)));
4491 DEBUG(5,("mode: %x\n", mode));
4492 break;
4494 case SMB_FILE_STANDARD_INFORMATION:
4495 case SMB_QUERY_FILE_STANDARD_INFO:
4497 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4498 data_size = 24;
4499 SOFF_T(pdata,0,allocation_size);
4500 SOFF_T(pdata,8,file_size);
4501 SIVAL(pdata,16,nlink);
4502 SCVAL(pdata,20,delete_pending?1:0);
4503 SCVAL(pdata,21,(mode&aDIR)?1:0);
4504 SSVAL(pdata,22,0); /* Padding. */
4505 break;
4507 case SMB_FILE_EA_INFORMATION:
4508 case SMB_QUERY_FILE_EA_INFO:
4510 unsigned int ea_size =
4511 estimate_ea_size(conn, fsp, smb_fname->base_name);
4512 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4513 data_size = 4;
4514 SIVAL(pdata,0,ea_size);
4515 break;
4518 /* Get the 8.3 name - used if NT SMB was negotiated. */
4519 case SMB_QUERY_FILE_ALT_NAME_INFO:
4520 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4522 int len;
4523 char mangled_name[13];
4524 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4525 if (!name_to_8_3(base_name,mangled_name,
4526 True,conn->params)) {
4527 return NT_STATUS_NO_MEMORY;
4529 len = srvstr_push(dstart, flags2,
4530 pdata+4, mangled_name,
4531 PTR_DIFF(dend, pdata+4),
4532 STR_UNICODE);
4533 data_size = 4 + len;
4534 SIVAL(pdata,0,len);
4535 break;
4538 case SMB_QUERY_FILE_NAME_INFO:
4540 int len;
4542 this must be *exactly* right for ACLs on mapped drives to work
4544 len = srvstr_push(dstart, flags2,
4545 pdata+4, dos_fname,
4546 PTR_DIFF(dend, pdata+4),
4547 STR_UNICODE);
4548 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4549 data_size = 4 + len;
4550 SIVAL(pdata,0,len);
4551 break;
4554 case SMB_FILE_ALLOCATION_INFORMATION:
4555 case SMB_QUERY_FILE_ALLOCATION_INFO:
4556 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4557 data_size = 8;
4558 SOFF_T(pdata,0,allocation_size);
4559 break;
4561 case SMB_FILE_END_OF_FILE_INFORMATION:
4562 case SMB_QUERY_FILE_END_OF_FILEINFO:
4563 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4564 data_size = 8;
4565 SOFF_T(pdata,0,file_size);
4566 break;
4568 case SMB_QUERY_FILE_ALL_INFO:
4569 case SMB_FILE_ALL_INFORMATION:
4571 int len;
4572 unsigned int ea_size =
4573 estimate_ea_size(conn, fsp, smb_fname->base_name);
4574 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4575 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4576 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4577 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4578 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4579 SIVAL(pdata,32,mode);
4580 SIVAL(pdata,36,0); /* padding. */
4581 pdata += 40;
4582 SOFF_T(pdata,0,allocation_size);
4583 SOFF_T(pdata,8,file_size);
4584 SIVAL(pdata,16,nlink);
4585 SCVAL(pdata,20,delete_pending);
4586 SCVAL(pdata,21,(mode&aDIR)?1:0);
4587 SSVAL(pdata,22,0);
4588 pdata += 24;
4589 SIVAL(pdata,0,ea_size);
4590 pdata += 4; /* EA info */
4591 len = srvstr_push(dstart, flags2,
4592 pdata+4, dos_fname,
4593 PTR_DIFF(dend, pdata+4),
4594 STR_UNICODE);
4595 SIVAL(pdata,0,len);
4596 pdata += 4 + len;
4597 data_size = PTR_DIFF(pdata,(*ppdata));
4598 break;
4601 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4603 int len;
4604 unsigned int ea_size =
4605 estimate_ea_size(conn, fsp, smb_fname->base_name);
4606 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4607 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4608 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4609 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4610 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4611 SIVAL(pdata, 0x20, mode);
4612 SIVAL(pdata, 0x24, 0); /* padding. */
4613 SBVAL(pdata, 0x28, allocation_size);
4614 SBVAL(pdata, 0x30, file_size);
4615 SIVAL(pdata, 0x38, nlink);
4616 SCVAL(pdata, 0x3C, delete_pending);
4617 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4618 SSVAL(pdata, 0x3E, 0); /* padding */
4619 SBVAL(pdata, 0x40, file_index);
4620 SIVAL(pdata, 0x48, ea_size);
4621 SIVAL(pdata, 0x4C, access_mask);
4622 SBVAL(pdata, 0x50, pos);
4623 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4624 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4626 pdata += 0x60;
4628 len = srvstr_push(dstart, flags2,
4629 pdata+4, dos_fname,
4630 PTR_DIFF(dend, pdata+4),
4631 STR_UNICODE);
4632 SIVAL(pdata,0,len);
4633 pdata += 4 + len;
4634 data_size = PTR_DIFF(pdata,(*ppdata));
4635 break;
4637 case SMB_FILE_INTERNAL_INFORMATION:
4639 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4640 SBVAL(pdata, 0, file_index);
4641 data_size = 8;
4642 break;
4644 case SMB_FILE_ACCESS_INFORMATION:
4645 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4646 SIVAL(pdata, 0, access_mask);
4647 data_size = 4;
4648 break;
4650 case SMB_FILE_NAME_INFORMATION:
4651 /* Pathname with leading '\'. */
4653 size_t byte_len;
4654 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4655 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4656 SIVAL(pdata,0,byte_len);
4657 data_size = 4 + byte_len;
4658 break;
4661 case SMB_FILE_DISPOSITION_INFORMATION:
4662 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4663 data_size = 1;
4664 SCVAL(pdata,0,delete_pending);
4665 break;
4667 case SMB_FILE_POSITION_INFORMATION:
4668 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4669 data_size = 8;
4670 SOFF_T(pdata,0,pos);
4671 break;
4673 case SMB_FILE_MODE_INFORMATION:
4674 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4675 SIVAL(pdata,0,mode);
4676 data_size = 4;
4677 break;
4679 case SMB_FILE_ALIGNMENT_INFORMATION:
4680 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4681 SIVAL(pdata,0,0); /* No alignment needed. */
4682 data_size = 4;
4683 break;
4686 * NT4 server just returns "invalid query" to this - if we try
4687 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4688 * want this. JRA.
4690 /* The first statement above is false - verified using Thursby
4691 * client against NT4 -- gcolley.
4693 case SMB_QUERY_FILE_STREAM_INFO:
4694 case SMB_FILE_STREAM_INFORMATION: {
4695 unsigned int num_streams;
4696 struct stream_struct *streams;
4698 DEBUG(10,("smbd_do_qfilepathinfo: "
4699 "SMB_FILE_STREAM_INFORMATION\n"));
4701 if (is_ntfs_stream_smb_fname(smb_fname)) {
4702 return NT_STATUS_INVALID_PARAMETER;
4705 status = SMB_VFS_STREAMINFO(
4706 conn, fsp, smb_fname->base_name, talloc_tos(),
4707 &num_streams, &streams);
4709 if (!NT_STATUS_IS_OK(status)) {
4710 DEBUG(10, ("could not get stream info: %s\n",
4711 nt_errstr(status)));
4712 return status;
4715 status = marshall_stream_info(num_streams, streams,
4716 pdata, max_data_bytes,
4717 &data_size);
4719 if (!NT_STATUS_IS_OK(status)) {
4720 DEBUG(10, ("marshall_stream_info failed: %s\n",
4721 nt_errstr(status)));
4722 return status;
4725 TALLOC_FREE(streams);
4727 break;
4729 case SMB_QUERY_COMPRESSION_INFO:
4730 case SMB_FILE_COMPRESSION_INFORMATION:
4731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4732 SOFF_T(pdata,0,file_size);
4733 SIVAL(pdata,8,0); /* ??? */
4734 SIVAL(pdata,12,0); /* ??? */
4735 data_size = 16;
4736 break;
4738 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4739 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4740 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4741 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4742 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4743 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4744 SOFF_T(pdata,32,allocation_size);
4745 SOFF_T(pdata,40,file_size);
4746 SIVAL(pdata,48,mode);
4747 SIVAL(pdata,52,0); /* ??? */
4748 data_size = 56;
4749 break;
4751 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4752 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4753 SIVAL(pdata,0,mode);
4754 SIVAL(pdata,4,0);
4755 data_size = 8;
4756 break;
4759 * CIFS UNIX Extensions.
4762 case SMB_QUERY_FILE_UNIX_BASIC:
4764 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4765 data_size = PTR_DIFF(pdata,(*ppdata));
4767 DEBUG(4,("smbd_do_qfilepathinfo: "
4768 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4769 dump_data(4, (uint8_t *)(*ppdata), data_size);
4771 break;
4773 case SMB_QUERY_FILE_UNIX_INFO2:
4775 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4776 data_size = PTR_DIFF(pdata,(*ppdata));
4779 int i;
4780 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4782 for (i=0; i<100; i++)
4783 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4784 DEBUG(4,("\n"));
4787 break;
4789 case SMB_QUERY_FILE_UNIX_LINK:
4791 int len;
4792 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4794 if (!buffer) {
4795 return NT_STATUS_NO_MEMORY;
4798 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4799 #ifdef S_ISLNK
4800 if(!S_ISLNK(psbuf->st_ex_mode)) {
4801 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4803 #else
4804 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4805 #endif
4806 len = SMB_VFS_READLINK(conn,
4807 smb_fname->base_name,
4808 buffer, PATH_MAX);
4809 if (len == -1) {
4810 return map_nt_error_from_unix(errno);
4812 buffer[len] = 0;
4813 len = srvstr_push(dstart, flags2,
4814 pdata, buffer,
4815 PTR_DIFF(dend, pdata),
4816 STR_TERMINATE);
4817 pdata += len;
4818 data_size = PTR_DIFF(pdata,(*ppdata));
4820 break;
4823 #if defined(HAVE_POSIX_ACLS)
4824 case SMB_QUERY_POSIX_ACL:
4826 SMB_ACL_T file_acl = NULL;
4827 SMB_ACL_T def_acl = NULL;
4828 uint16 num_file_acls = 0;
4829 uint16 num_def_acls = 0;
4831 if (fsp && fsp->fh->fd != -1) {
4832 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4833 } else {
4834 file_acl =
4835 SMB_VFS_SYS_ACL_GET_FILE(conn,
4836 smb_fname->base_name,
4837 SMB_ACL_TYPE_ACCESS);
4840 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4841 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4842 "not implemented on "
4843 "filesystem containing %s\n",
4844 smb_fname->base_name));
4845 return NT_STATUS_NOT_IMPLEMENTED;
4848 if (S_ISDIR(psbuf->st_ex_mode)) {
4849 if (fsp && fsp->is_directory) {
4850 def_acl =
4851 SMB_VFS_SYS_ACL_GET_FILE(
4852 conn,
4853 fsp->fsp_name->base_name,
4854 SMB_ACL_TYPE_DEFAULT);
4855 } else {
4856 def_acl =
4857 SMB_VFS_SYS_ACL_GET_FILE(
4858 conn,
4859 smb_fname->base_name,
4860 SMB_ACL_TYPE_DEFAULT);
4862 def_acl = free_empty_sys_acl(conn, def_acl);
4865 num_file_acls = count_acl_entries(conn, file_acl);
4866 num_def_acls = count_acl_entries(conn, def_acl);
4868 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4869 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4870 data_size,
4871 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4872 SMB_POSIX_ACL_HEADER_SIZE) ));
4873 if (file_acl) {
4874 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4876 if (def_acl) {
4877 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4879 return NT_STATUS_BUFFER_TOO_SMALL;
4882 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4883 SSVAL(pdata,2,num_file_acls);
4884 SSVAL(pdata,4,num_def_acls);
4885 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4886 if (file_acl) {
4887 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4889 if (def_acl) {
4890 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4892 return NT_STATUS_INTERNAL_ERROR;
4894 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4895 if (file_acl) {
4896 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4898 if (def_acl) {
4899 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4901 return NT_STATUS_INTERNAL_ERROR;
4904 if (file_acl) {
4905 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4907 if (def_acl) {
4908 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4910 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4911 break;
4913 #endif
4916 case SMB_QUERY_POSIX_LOCK:
4918 uint64_t count;
4919 uint64_t offset;
4920 uint64_t smblctx;
4921 enum brl_type lock_type;
4923 /* We need an open file with a real fd for this. */
4924 if (!fsp || fsp->fh->fd == -1) {
4925 return NT_STATUS_INVALID_LEVEL;
4928 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4929 return NT_STATUS_INVALID_PARAMETER;
4932 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4933 case POSIX_LOCK_TYPE_READ:
4934 lock_type = READ_LOCK;
4935 break;
4936 case POSIX_LOCK_TYPE_WRITE:
4937 lock_type = WRITE_LOCK;
4938 break;
4939 case POSIX_LOCK_TYPE_UNLOCK:
4940 default:
4941 /* There's no point in asking for an unlock... */
4942 return NT_STATUS_INVALID_PARAMETER;
4945 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4946 #if defined(HAVE_LONGLONG)
4947 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4948 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4949 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4950 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4951 #else /* HAVE_LONGLONG */
4952 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4953 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4954 #endif /* HAVE_LONGLONG */
4956 status = query_lock(fsp,
4957 &smblctx,
4958 &count,
4959 &offset,
4960 &lock_type,
4961 POSIX_LOCK);
4963 if (ERROR_WAS_LOCK_DENIED(status)) {
4964 /* Here we need to report who has it locked... */
4965 data_size = POSIX_LOCK_DATA_SIZE;
4967 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4968 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4969 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4970 #if defined(HAVE_LONGLONG)
4971 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4972 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4973 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4974 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4975 #else /* HAVE_LONGLONG */
4976 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4977 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4978 #endif /* HAVE_LONGLONG */
4980 } else if (NT_STATUS_IS_OK(status)) {
4981 /* For success we just return a copy of what we sent
4982 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4983 data_size = POSIX_LOCK_DATA_SIZE;
4984 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4985 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4986 } else {
4987 return status;
4989 break;
4992 default:
4993 return NT_STATUS_INVALID_LEVEL;
4996 *pdata_size = data_size;
4997 return NT_STATUS_OK;
5000 /****************************************************************************
5001 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5002 file name or file id).
5003 ****************************************************************************/
5005 static void call_trans2qfilepathinfo(connection_struct *conn,
5006 struct smb_request *req,
5007 unsigned int tran_call,
5008 char **pparams, int total_params,
5009 char **ppdata, int total_data,
5010 unsigned int max_data_bytes)
5012 char *params = *pparams;
5013 char *pdata = *ppdata;
5014 uint16 info_level;
5015 unsigned int data_size = 0;
5016 unsigned int param_size = 2;
5017 struct smb_filename *smb_fname = NULL;
5018 bool delete_pending = False;
5019 struct timespec write_time_ts;
5020 files_struct *fsp = NULL;
5021 struct file_id fileid;
5022 struct ea_list *ea_list = NULL;
5023 int lock_data_count = 0;
5024 char *lock_data = NULL;
5025 NTSTATUS status = NT_STATUS_OK;
5027 if (!params) {
5028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5029 return;
5032 ZERO_STRUCT(write_time_ts);
5034 if (tran_call == TRANSACT2_QFILEINFO) {
5035 if (total_params < 4) {
5036 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5037 return;
5040 if (IS_IPC(conn)) {
5041 call_trans2qpipeinfo(conn, req, tran_call,
5042 pparams, total_params,
5043 ppdata, total_data,
5044 max_data_bytes);
5045 return;
5048 fsp = file_fsp(req, SVAL(params,0));
5049 info_level = SVAL(params,2);
5051 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5053 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5054 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5055 return;
5058 /* Initial check for valid fsp ptr. */
5059 if (!check_fsp_open(conn, req, fsp)) {
5060 return;
5063 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5064 &smb_fname);
5065 if (!NT_STATUS_IS_OK(status)) {
5066 reply_nterror(req, status);
5067 return;
5070 if(fsp->fake_file_handle) {
5072 * This is actually for the QUOTA_FAKE_FILE --metze
5075 /* We know this name is ok, it's already passed the checks. */
5077 } else if(fsp->fh->fd == -1) {
5079 * This is actually a QFILEINFO on a directory
5080 * handle (returned from an NT SMB). NT5.0 seems
5081 * to do this call. JRA.
5084 if (INFO_LEVEL_IS_UNIX(info_level)) {
5085 /* Always do lstat for UNIX calls. */
5086 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5087 DEBUG(3,("call_trans2qfilepathinfo: "
5088 "SMB_VFS_LSTAT of %s failed "
5089 "(%s)\n",
5090 smb_fname_str_dbg(smb_fname),
5091 strerror(errno)));
5092 reply_nterror(req,
5093 map_nt_error_from_unix(errno));
5094 return;
5096 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5097 DEBUG(3,("call_trans2qfilepathinfo: "
5098 "SMB_VFS_STAT of %s failed (%s)\n",
5099 smb_fname_str_dbg(smb_fname),
5100 strerror(errno)));
5101 reply_nterror(req,
5102 map_nt_error_from_unix(errno));
5103 return;
5106 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5107 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5108 } else {
5110 * Original code - this is an open file.
5112 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5113 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5114 fsp->fnum, strerror(errno)));
5115 reply_nterror(req,
5116 map_nt_error_from_unix(errno));
5117 return;
5119 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5120 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5123 } else {
5124 uint32_t name_hash;
5125 char *fname = NULL;
5127 /* qpathinfo */
5128 if (total_params < 7) {
5129 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5130 return;
5133 info_level = SVAL(params,0);
5135 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5137 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5138 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5139 return;
5142 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5143 total_params - 6,
5144 STR_TERMINATE, &status);
5145 if (!NT_STATUS_IS_OK(status)) {
5146 reply_nterror(req, status);
5147 return;
5150 status = filename_convert(req,
5151 conn,
5152 req->flags2 & FLAGS2_DFS_PATHNAMES,
5153 fname,
5155 NULL,
5156 &smb_fname);
5157 if (!NT_STATUS_IS_OK(status)) {
5158 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5159 reply_botherror(req,
5160 NT_STATUS_PATH_NOT_COVERED,
5161 ERRSRV, ERRbadpath);
5162 return;
5164 reply_nterror(req, status);
5165 return;
5168 /* If this is a stream, check if there is a delete_pending. */
5169 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5170 && is_ntfs_stream_smb_fname(smb_fname)) {
5171 struct smb_filename *smb_fname_base = NULL;
5173 /* Create an smb_filename with stream_name == NULL. */
5174 status =
5175 create_synthetic_smb_fname(talloc_tos(),
5176 smb_fname->base_name,
5177 NULL, NULL,
5178 &smb_fname_base);
5179 if (!NT_STATUS_IS_OK(status)) {
5180 reply_nterror(req, status);
5181 return;
5184 if (INFO_LEVEL_IS_UNIX(info_level)) {
5185 /* Always do lstat for UNIX calls. */
5186 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5187 DEBUG(3,("call_trans2qfilepathinfo: "
5188 "SMB_VFS_LSTAT of %s failed "
5189 "(%s)\n",
5190 smb_fname_str_dbg(smb_fname_base),
5191 strerror(errno)));
5192 TALLOC_FREE(smb_fname_base);
5193 reply_nterror(req,
5194 map_nt_error_from_unix(errno));
5195 return;
5197 } else {
5198 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5199 DEBUG(3,("call_trans2qfilepathinfo: "
5200 "fileinfo of %s failed "
5201 "(%s)\n",
5202 smb_fname_str_dbg(smb_fname_base),
5203 strerror(errno)));
5204 TALLOC_FREE(smb_fname_base);
5205 reply_nterror(req,
5206 map_nt_error_from_unix(errno));
5207 return;
5211 status = file_name_hash(conn,
5212 smb_fname_str_dbg(smb_fname_base),
5213 &name_hash);
5214 if (!NT_STATUS_IS_OK(status)) {
5215 TALLOC_FREE(smb_fname_base);
5216 reply_nterror(req, status);
5217 return;
5220 fileid = vfs_file_id_from_sbuf(conn,
5221 &smb_fname_base->st);
5222 TALLOC_FREE(smb_fname_base);
5223 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5224 if (delete_pending) {
5225 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5226 return;
5230 if (INFO_LEVEL_IS_UNIX(info_level)) {
5231 /* Always do lstat for UNIX calls. */
5232 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5233 DEBUG(3,("call_trans2qfilepathinfo: "
5234 "SMB_VFS_LSTAT of %s failed (%s)\n",
5235 smb_fname_str_dbg(smb_fname),
5236 strerror(errno)));
5237 reply_nterror(req,
5238 map_nt_error_from_unix(errno));
5239 return;
5242 } else {
5243 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5244 DEBUG(3,("call_trans2qfilepathinfo: "
5245 "SMB_VFS_STAT of %s failed (%s)\n",
5246 smb_fname_str_dbg(smb_fname),
5247 strerror(errno)));
5248 reply_nterror(req,
5249 map_nt_error_from_unix(errno));
5250 return;
5254 status = file_name_hash(conn,
5255 smb_fname_str_dbg(smb_fname),
5256 &name_hash);
5257 if (!NT_STATUS_IS_OK(status)) {
5258 reply_nterror(req, status);
5259 return;
5262 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5263 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5264 if (delete_pending) {
5265 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5266 return;
5270 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5271 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5272 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5274 /* Pull out any data sent here before we realloc. */
5275 switch (info_level) {
5276 case SMB_INFO_QUERY_EAS_FROM_LIST:
5278 /* Pull any EA list from the data portion. */
5279 uint32 ea_size;
5281 if (total_data < 4) {
5282 reply_nterror(
5283 req, NT_STATUS_INVALID_PARAMETER);
5284 return;
5286 ea_size = IVAL(pdata,0);
5288 if (total_data > 0 && ea_size != total_data) {
5289 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5290 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5291 reply_nterror(
5292 req, NT_STATUS_INVALID_PARAMETER);
5293 return;
5296 if (!lp_ea_support(SNUM(conn))) {
5297 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5298 return;
5301 /* Pull out the list of names. */
5302 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5303 if (!ea_list) {
5304 reply_nterror(
5305 req, NT_STATUS_INVALID_PARAMETER);
5306 return;
5308 break;
5311 case SMB_QUERY_POSIX_LOCK:
5313 if (fsp == NULL || fsp->fh->fd == -1) {
5314 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5315 return;
5318 if (total_data != POSIX_LOCK_DATA_SIZE) {
5319 reply_nterror(
5320 req, NT_STATUS_INVALID_PARAMETER);
5321 return;
5324 /* Copy the lock range data. */
5325 lock_data = (char *)TALLOC_MEMDUP(
5326 req, pdata, total_data);
5327 if (!lock_data) {
5328 reply_nterror(req, NT_STATUS_NO_MEMORY);
5329 return;
5331 lock_data_count = total_data;
5333 default:
5334 break;
5337 *pparams = (char *)SMB_REALLOC(*pparams,2);
5338 if (*pparams == NULL) {
5339 reply_nterror(req, NT_STATUS_NO_MEMORY);
5340 return;
5342 params = *pparams;
5343 SSVAL(params,0,0);
5346 * draft-leach-cifs-v1-spec-02.txt
5347 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5348 * says:
5350 * The requested information is placed in the Data portion of the
5351 * transaction response. For the information levels greater than 0x100,
5352 * the transaction response has 1 parameter word which should be
5353 * ignored by the client.
5355 * However Windows only follows this rule for the IS_NAME_VALID call.
5357 switch (info_level) {
5358 case SMB_INFO_IS_NAME_VALID:
5359 param_size = 0;
5360 break;
5363 if ((info_level & 0xFF00) == 0xFF00) {
5365 * We use levels that start with 0xFF00
5366 * internally to represent SMB2 specific levels
5368 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5369 return;
5372 status = smbd_do_qfilepathinfo(conn, req, info_level,
5373 fsp, smb_fname,
5374 delete_pending, write_time_ts,
5375 ea_list,
5376 lock_data_count, lock_data,
5377 req->flags2, max_data_bytes,
5378 ppdata, &data_size);
5379 if (!NT_STATUS_IS_OK(status)) {
5380 reply_nterror(req, status);
5381 return;
5384 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5385 max_data_bytes);
5387 return;
5390 /****************************************************************************
5391 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5392 code.
5393 ****************************************************************************/
5395 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5396 connection_struct *conn,
5397 struct smb_request *req,
5398 bool overwrite_if_exists,
5399 const struct smb_filename *smb_fname_old,
5400 struct smb_filename *smb_fname_new)
5402 NTSTATUS status = NT_STATUS_OK;
5404 /* source must already exist. */
5405 if (!VALID_STAT(smb_fname_old->st)) {
5406 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5409 if (VALID_STAT(smb_fname_new->st)) {
5410 if (overwrite_if_exists) {
5411 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5412 return NT_STATUS_FILE_IS_A_DIRECTORY;
5414 status = unlink_internals(conn,
5415 req,
5416 FILE_ATTRIBUTE_NORMAL,
5417 smb_fname_new,
5418 false);
5419 if (!NT_STATUS_IS_OK(status)) {
5420 return status;
5422 } else {
5423 /* Disallow if newname already exists. */
5424 return NT_STATUS_OBJECT_NAME_COLLISION;
5428 /* No links from a directory. */
5429 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5430 return NT_STATUS_FILE_IS_A_DIRECTORY;
5433 /* Setting a hardlink to/from a stream isn't currently supported. */
5434 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5435 is_ntfs_stream_smb_fname(smb_fname_new)) {
5436 return NT_STATUS_INVALID_PARAMETER;
5439 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5440 smb_fname_old->base_name, smb_fname_new->base_name));
5442 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5443 smb_fname_new->base_name) != 0) {
5444 status = map_nt_error_from_unix(errno);
5445 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5446 nt_errstr(status), smb_fname_old->base_name,
5447 smb_fname_new->base_name));
5449 return status;
5452 /****************************************************************************
5453 Deal with setting the time from any of the setfilepathinfo functions.
5454 ****************************************************************************/
5456 NTSTATUS smb_set_file_time(connection_struct *conn,
5457 files_struct *fsp,
5458 const struct smb_filename *smb_fname,
5459 struct smb_file_time *ft,
5460 bool setting_write_time)
5462 struct smb_filename smb_fname_base;
5463 uint32 action =
5464 FILE_NOTIFY_CHANGE_LAST_ACCESS
5465 |FILE_NOTIFY_CHANGE_LAST_WRITE
5466 |FILE_NOTIFY_CHANGE_CREATION;
5468 if (!VALID_STAT(smb_fname->st)) {
5469 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5472 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5473 return NT_STATUS_ACCESS_DENIED;
5476 /* get some defaults (no modifications) if any info is zero or -1. */
5477 if (null_timespec(ft->create_time)) {
5478 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5481 if (null_timespec(ft->atime)) {
5482 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5485 if (null_timespec(ft->mtime)) {
5486 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5489 if (!setting_write_time) {
5490 /* ft->mtime comes from change time, not write time. */
5491 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5494 /* Ensure the resolution is the correct for
5495 * what we can store on this filesystem. */
5497 round_timespec(conn->ts_res, &ft->create_time);
5498 round_timespec(conn->ts_res, &ft->ctime);
5499 round_timespec(conn->ts_res, &ft->atime);
5500 round_timespec(conn->ts_res, &ft->mtime);
5502 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5503 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5504 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5505 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5506 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5507 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5508 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5509 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5511 if (setting_write_time) {
5513 * This was a Windows setfileinfo on an open file.
5514 * NT does this a lot. We also need to
5515 * set the time here, as it can be read by
5516 * FindFirst/FindNext and with the patch for bug #2045
5517 * in smbd/fileio.c it ensures that this timestamp is
5518 * kept sticky even after a write. We save the request
5519 * away and will set it on file close and after a write. JRA.
5522 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5523 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5525 if (fsp != NULL) {
5526 if (fsp->base_fsp) {
5527 set_sticky_write_time_fsp(fsp->base_fsp,
5528 ft->mtime);
5529 } else {
5530 set_sticky_write_time_fsp(fsp, ft->mtime);
5532 } else {
5533 set_sticky_write_time_path(
5534 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5535 ft->mtime);
5539 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5541 /* Always call ntimes on the base, even if a stream was passed in. */
5542 smb_fname_base = *smb_fname;
5543 smb_fname_base.stream_name = NULL;
5545 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5546 return map_nt_error_from_unix(errno);
5549 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5550 smb_fname->base_name);
5551 return NT_STATUS_OK;
5554 /****************************************************************************
5555 Deal with setting the dosmode from any of the setfilepathinfo functions.
5556 ****************************************************************************/
5558 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5559 const struct smb_filename *smb_fname,
5560 uint32 dosmode)
5562 struct smb_filename *smb_fname_base = NULL;
5563 NTSTATUS status;
5565 if (!VALID_STAT(smb_fname->st)) {
5566 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5569 /* Always operate on the base_name, even if a stream was passed in. */
5570 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5571 NULL, &smb_fname->st,
5572 &smb_fname_base);
5573 if (!NT_STATUS_IS_OK(status)) {
5574 return status;
5577 if (dosmode) {
5578 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5579 dosmode |= aDIR;
5580 } else {
5581 dosmode &= ~aDIR;
5585 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5587 /* check the mode isn't different, before changing it */
5588 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5589 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5590 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5591 (unsigned int)dosmode));
5593 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5594 false)) {
5595 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5596 "%s failed (%s)\n",
5597 smb_fname_str_dbg(smb_fname_base),
5598 strerror(errno)));
5599 status = map_nt_error_from_unix(errno);
5600 goto out;
5603 status = NT_STATUS_OK;
5604 out:
5605 TALLOC_FREE(smb_fname_base);
5606 return status;
5609 /****************************************************************************
5610 Deal with setting the size from any of the setfilepathinfo functions.
5611 ****************************************************************************/
5613 static NTSTATUS smb_set_file_size(connection_struct *conn,
5614 struct smb_request *req,
5615 files_struct *fsp,
5616 const struct smb_filename *smb_fname,
5617 const SMB_STRUCT_STAT *psbuf,
5618 SMB_OFF_T size,
5619 bool fail_after_createfile)
5621 NTSTATUS status = NT_STATUS_OK;
5622 struct smb_filename *smb_fname_tmp = NULL;
5623 files_struct *new_fsp = NULL;
5625 if (!VALID_STAT(*psbuf)) {
5626 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5629 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5630 return NT_STATUS_ACCESS_DENIED;
5633 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5635 if (size == get_file_size_stat(psbuf)) {
5636 return NT_STATUS_OK;
5639 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5640 smb_fname_str_dbg(smb_fname), (double)size));
5642 if (fsp && fsp->fh->fd != -1) {
5643 /* Handle based call. */
5644 if (vfs_set_filelen(fsp, size) == -1) {
5645 return map_nt_error_from_unix(errno);
5647 trigger_write_time_update_immediate(fsp);
5648 return NT_STATUS_OK;
5651 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5652 if (!NT_STATUS_IS_OK(status)) {
5653 return status;
5656 smb_fname_tmp->st = *psbuf;
5658 status = SMB_VFS_CREATE_FILE(
5659 conn, /* conn */
5660 req, /* req */
5661 0, /* root_dir_fid */
5662 smb_fname_tmp, /* fname */
5663 FILE_WRITE_DATA, /* access_mask */
5664 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5665 FILE_SHARE_DELETE),
5666 FILE_OPEN, /* create_disposition*/
5667 0, /* create_options */
5668 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5669 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5670 0, /* allocation_size */
5671 0, /* private_flags */
5672 NULL, /* sd */
5673 NULL, /* ea_list */
5674 &new_fsp, /* result */
5675 NULL); /* pinfo */
5677 TALLOC_FREE(smb_fname_tmp);
5679 if (!NT_STATUS_IS_OK(status)) {
5680 /* NB. We check for open_was_deferred in the caller. */
5681 return status;
5684 /* See RAW-SFILEINFO-END-OF-FILE */
5685 if (fail_after_createfile) {
5686 close_file(req, new_fsp,NORMAL_CLOSE);
5687 return NT_STATUS_INVALID_LEVEL;
5690 if (vfs_set_filelen(new_fsp, size) == -1) {
5691 status = map_nt_error_from_unix(errno);
5692 close_file(req, new_fsp,NORMAL_CLOSE);
5693 return status;
5696 trigger_write_time_update_immediate(new_fsp);
5697 close_file(req, new_fsp,NORMAL_CLOSE);
5698 return NT_STATUS_OK;
5701 /****************************************************************************
5702 Deal with SMB_INFO_SET_EA.
5703 ****************************************************************************/
5705 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5706 const char *pdata,
5707 int total_data,
5708 files_struct *fsp,
5709 const struct smb_filename *smb_fname)
5711 struct ea_list *ea_list = NULL;
5712 TALLOC_CTX *ctx = NULL;
5713 NTSTATUS status = NT_STATUS_OK;
5715 if (total_data < 10) {
5717 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5718 length. They seem to have no effect. Bug #3212. JRA */
5720 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5721 /* We're done. We only get EA info in this call. */
5722 return NT_STATUS_OK;
5725 return NT_STATUS_INVALID_PARAMETER;
5728 if (IVAL(pdata,0) > total_data) {
5729 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5730 IVAL(pdata,0), (unsigned int)total_data));
5731 return NT_STATUS_INVALID_PARAMETER;
5734 ctx = talloc_tos();
5735 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5736 if (!ea_list) {
5737 return NT_STATUS_INVALID_PARAMETER;
5740 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5741 return NT_STATUS_ACCESS_DENIED;
5744 status = set_ea(conn, fsp, smb_fname, ea_list);
5746 return status;
5749 /****************************************************************************
5750 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5751 ****************************************************************************/
5753 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5754 const char *pdata,
5755 int total_data,
5756 files_struct *fsp)
5758 struct ea_list *ea_list = NULL;
5759 NTSTATUS status;
5761 if (!fsp) {
5762 return NT_STATUS_INVALID_HANDLE;
5765 if (!lp_ea_support(SNUM(conn))) {
5766 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5767 "EA's not supported.\n",
5768 (unsigned int)total_data));
5769 return NT_STATUS_EAS_NOT_SUPPORTED;
5772 if (total_data < 10) {
5773 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5774 "too small.\n",
5775 (unsigned int)total_data));
5776 return NT_STATUS_INVALID_PARAMETER;
5779 ea_list = read_nttrans_ea_list(talloc_tos(),
5780 pdata,
5781 total_data);
5783 if (!ea_list) {
5784 return NT_STATUS_INVALID_PARAMETER;
5787 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5788 return NT_STATUS_ACCESS_DENIED;
5791 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5793 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5794 smb_fname_str_dbg(fsp->fsp_name),
5795 nt_errstr(status) ));
5797 return status;
5801 /****************************************************************************
5802 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5803 ****************************************************************************/
5805 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5806 const char *pdata,
5807 int total_data,
5808 files_struct *fsp,
5809 struct smb_filename *smb_fname)
5811 NTSTATUS status = NT_STATUS_OK;
5812 bool delete_on_close;
5813 uint32 dosmode = 0;
5815 if (total_data < 1) {
5816 return NT_STATUS_INVALID_PARAMETER;
5819 if (fsp == NULL) {
5820 return NT_STATUS_INVALID_HANDLE;
5823 delete_on_close = (CVAL(pdata,0) ? True : False);
5824 dosmode = dos_mode(conn, smb_fname);
5826 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5827 "delete_on_close = %u\n",
5828 smb_fname_str_dbg(smb_fname),
5829 (unsigned int)dosmode,
5830 (unsigned int)delete_on_close ));
5832 if (delete_on_close) {
5833 status = can_set_delete_on_close(fsp, dosmode);
5834 if (!NT_STATUS_IS_OK(status)) {
5835 return status;
5839 /* The set is across all open files on this dev/inode pair. */
5840 if (!set_delete_on_close(fsp, delete_on_close,
5841 &conn->session_info->utok)) {
5842 return NT_STATUS_ACCESS_DENIED;
5844 return NT_STATUS_OK;
5847 /****************************************************************************
5848 Deal with SMB_FILE_POSITION_INFORMATION.
5849 ****************************************************************************/
5851 static NTSTATUS smb_file_position_information(connection_struct *conn,
5852 const char *pdata,
5853 int total_data,
5854 files_struct *fsp)
5856 uint64_t position_information;
5858 if (total_data < 8) {
5859 return NT_STATUS_INVALID_PARAMETER;
5862 if (fsp == NULL) {
5863 /* Ignore on pathname based set. */
5864 return NT_STATUS_OK;
5867 position_information = (uint64_t)IVAL(pdata,0);
5868 #ifdef LARGE_SMB_OFF_T
5869 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5870 #else /* LARGE_SMB_OFF_T */
5871 if (IVAL(pdata,4) != 0) {
5872 /* more than 32 bits? */
5873 return NT_STATUS_INVALID_PARAMETER;
5875 #endif /* LARGE_SMB_OFF_T */
5877 DEBUG(10,("smb_file_position_information: Set file position "
5878 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5879 (double)position_information));
5880 fsp->fh->position_information = position_information;
5881 return NT_STATUS_OK;
5884 /****************************************************************************
5885 Deal with SMB_FILE_MODE_INFORMATION.
5886 ****************************************************************************/
5888 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5889 const char *pdata,
5890 int total_data)
5892 uint32 mode;
5894 if (total_data < 4) {
5895 return NT_STATUS_INVALID_PARAMETER;
5897 mode = IVAL(pdata,0);
5898 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5899 return NT_STATUS_INVALID_PARAMETER;
5901 return NT_STATUS_OK;
5904 /****************************************************************************
5905 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5906 ****************************************************************************/
5908 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5909 struct smb_request *req,
5910 const char *pdata,
5911 int total_data,
5912 const struct smb_filename *smb_fname)
5914 char *link_target = NULL;
5915 const char *newname = smb_fname->base_name;
5916 TALLOC_CTX *ctx = talloc_tos();
5918 /* Set a symbolic link. */
5919 /* Don't allow this if follow links is false. */
5921 if (total_data == 0) {
5922 return NT_STATUS_INVALID_PARAMETER;
5925 if (!lp_symlinks(SNUM(conn))) {
5926 return NT_STATUS_ACCESS_DENIED;
5929 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5930 total_data, STR_TERMINATE);
5932 if (!link_target) {
5933 return NT_STATUS_INVALID_PARAMETER;
5936 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5937 newname, link_target ));
5939 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5940 return map_nt_error_from_unix(errno);
5943 return NT_STATUS_OK;
5946 /****************************************************************************
5947 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5948 ****************************************************************************/
5950 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5951 struct smb_request *req,
5952 const char *pdata, int total_data,
5953 struct smb_filename *smb_fname_new)
5955 char *oldname = NULL;
5956 struct smb_filename *smb_fname_old = NULL;
5957 TALLOC_CTX *ctx = talloc_tos();
5958 NTSTATUS status = NT_STATUS_OK;
5960 /* Set a hard link. */
5961 if (total_data == 0) {
5962 return NT_STATUS_INVALID_PARAMETER;
5965 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5966 total_data, STR_TERMINATE, &status);
5967 if (!NT_STATUS_IS_OK(status)) {
5968 return status;
5971 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5972 smb_fname_str_dbg(smb_fname_new), oldname));
5974 status = filename_convert(ctx,
5975 conn,
5976 req->flags2 & FLAGS2_DFS_PATHNAMES,
5977 oldname,
5979 NULL,
5980 &smb_fname_old);
5981 if (!NT_STATUS_IS_OK(status)) {
5982 return status;
5985 return hardlink_internals(ctx, conn, req, false,
5986 smb_fname_old, smb_fname_new);
5989 /****************************************************************************
5990 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5991 ****************************************************************************/
5993 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5994 struct smb_request *req,
5995 const char *pdata,
5996 int total_data,
5997 files_struct *fsp,
5998 struct smb_filename *smb_fname_src)
6000 bool overwrite;
6001 uint32_t len;
6002 char *newname = NULL;
6003 struct smb_filename *smb_fname_dst = NULL;
6004 NTSTATUS status = NT_STATUS_OK;
6005 TALLOC_CTX *ctx = talloc_tos();
6007 if (!fsp) {
6008 return NT_STATUS_INVALID_HANDLE;
6011 if (total_data < 20) {
6012 return NT_STATUS_INVALID_PARAMETER;
6015 overwrite = (CVAL(pdata,0) ? True : False);
6016 len = IVAL(pdata,16);
6018 if (len > (total_data - 20) || (len == 0)) {
6019 return NT_STATUS_INVALID_PARAMETER;
6022 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6023 &pdata[20], len, STR_TERMINATE,
6024 &status);
6025 if (!NT_STATUS_IS_OK(status)) {
6026 return status;
6029 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6030 newname));
6032 status = filename_convert(ctx,
6033 conn,
6034 req->flags2 & FLAGS2_DFS_PATHNAMES,
6035 newname,
6036 UCF_SAVE_LCOMP,
6037 NULL,
6038 &smb_fname_dst);
6039 if (!NT_STATUS_IS_OK(status)) {
6040 return status;
6043 if (fsp->base_fsp) {
6044 /* newname must be a stream name. */
6045 if (newname[0] != ':') {
6046 return NT_STATUS_NOT_SUPPORTED;
6049 /* Create an smb_fname to call rename_internals_fsp() with. */
6050 status = create_synthetic_smb_fname(talloc_tos(),
6051 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6052 &smb_fname_dst);
6053 if (!NT_STATUS_IS_OK(status)) {
6054 goto out;
6058 * Set the original last component, since
6059 * rename_internals_fsp() requires it.
6061 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6062 newname);
6063 if (smb_fname_dst->original_lcomp == NULL) {
6064 status = NT_STATUS_NO_MEMORY;
6065 goto out;
6070 DEBUG(10,("smb2_file_rename_information: "
6071 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6072 fsp->fnum, fsp_str_dbg(fsp),
6073 smb_fname_str_dbg(smb_fname_dst)));
6074 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6075 overwrite);
6077 out:
6078 TALLOC_FREE(smb_fname_dst);
6079 return status;
6082 static NTSTATUS smb_file_link_information(connection_struct *conn,
6083 struct smb_request *req,
6084 const char *pdata,
6085 int total_data,
6086 files_struct *fsp,
6087 struct smb_filename *smb_fname_src)
6089 bool overwrite;
6090 uint32_t len;
6091 char *newname = NULL;
6092 struct smb_filename *smb_fname_dst = NULL;
6093 NTSTATUS status = NT_STATUS_OK;
6094 TALLOC_CTX *ctx = talloc_tos();
6096 if (!fsp) {
6097 return NT_STATUS_INVALID_HANDLE;
6100 if (total_data < 20) {
6101 return NT_STATUS_INVALID_PARAMETER;
6104 overwrite = (CVAL(pdata,0) ? true : false);
6105 len = IVAL(pdata,16);
6107 if (len > (total_data - 20) || (len == 0)) {
6108 return NT_STATUS_INVALID_PARAMETER;
6111 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6112 &pdata[20], len, STR_TERMINATE,
6113 &status);
6114 if (!NT_STATUS_IS_OK(status)) {
6115 return status;
6118 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6119 newname));
6121 status = filename_convert(ctx,
6122 conn,
6123 req->flags2 & FLAGS2_DFS_PATHNAMES,
6124 newname,
6125 UCF_SAVE_LCOMP,
6126 NULL,
6127 &smb_fname_dst);
6128 if (!NT_STATUS_IS_OK(status)) {
6129 return status;
6132 if (fsp->base_fsp) {
6133 /* No stream names. */
6134 return NT_STATUS_NOT_SUPPORTED;
6137 DEBUG(10,("smb_file_link_information: "
6138 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6139 fsp->fnum, fsp_str_dbg(fsp),
6140 smb_fname_str_dbg(smb_fname_dst)));
6141 status = hardlink_internals(ctx,
6142 conn,
6143 req,
6144 overwrite,
6145 fsp->fsp_name,
6146 smb_fname_dst);
6148 TALLOC_FREE(smb_fname_dst);
6149 return status;
6152 /****************************************************************************
6153 Deal with SMB_FILE_RENAME_INFORMATION.
6154 ****************************************************************************/
6156 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6157 struct smb_request *req,
6158 const char *pdata,
6159 int total_data,
6160 files_struct *fsp,
6161 struct smb_filename *smb_fname_src)
6163 bool overwrite;
6164 uint32 root_fid;
6165 uint32 len;
6166 char *newname = NULL;
6167 struct smb_filename *smb_fname_dst = NULL;
6168 bool dest_has_wcard = False;
6169 NTSTATUS status = NT_STATUS_OK;
6170 char *p;
6171 TALLOC_CTX *ctx = talloc_tos();
6173 if (total_data < 13) {
6174 return NT_STATUS_INVALID_PARAMETER;
6177 overwrite = (CVAL(pdata,0) ? True : False);
6178 root_fid = IVAL(pdata,4);
6179 len = IVAL(pdata,8);
6181 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6182 return NT_STATUS_INVALID_PARAMETER;
6185 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6186 len, 0, &status,
6187 &dest_has_wcard);
6188 if (!NT_STATUS_IS_OK(status)) {
6189 return status;
6192 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6193 newname));
6195 status = resolve_dfspath_wcard(ctx, conn,
6196 req->flags2 & FLAGS2_DFS_PATHNAMES,
6197 newname,
6198 true,
6199 &newname,
6200 &dest_has_wcard);
6201 if (!NT_STATUS_IS_OK(status)) {
6202 return status;
6205 /* Check the new name has no '/' characters. */
6206 if (strchr_m(newname, '/')) {
6207 return NT_STATUS_NOT_SUPPORTED;
6210 if (fsp && fsp->base_fsp) {
6211 /* newname must be a stream name. */
6212 if (newname[0] != ':') {
6213 return NT_STATUS_NOT_SUPPORTED;
6216 /* Create an smb_fname to call rename_internals_fsp() with. */
6217 status = create_synthetic_smb_fname(talloc_tos(),
6218 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6219 &smb_fname_dst);
6220 if (!NT_STATUS_IS_OK(status)) {
6221 goto out;
6225 * Set the original last component, since
6226 * rename_internals_fsp() requires it.
6228 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6229 newname);
6230 if (smb_fname_dst->original_lcomp == NULL) {
6231 status = NT_STATUS_NO_MEMORY;
6232 goto out;
6235 } else {
6237 * Build up an smb_fname_dst based on the filename passed in.
6238 * We basically just strip off the last component, and put on
6239 * the newname instead.
6241 char *base_name = NULL;
6243 /* newname must *not* be a stream name. */
6244 if (newname[0] == ':') {
6245 return NT_STATUS_NOT_SUPPORTED;
6249 * Strip off the last component (filename) of the path passed
6250 * in.
6252 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6253 if (!base_name) {
6254 return NT_STATUS_NO_MEMORY;
6256 p = strrchr_m(base_name, '/');
6257 if (p) {
6258 p[1] = '\0';
6259 } else {
6260 base_name = talloc_strdup(ctx, "");
6261 if (!base_name) {
6262 return NT_STATUS_NO_MEMORY;
6265 /* Append the new name. */
6266 base_name = talloc_asprintf_append(base_name,
6267 "%s",
6268 newname);
6269 if (!base_name) {
6270 return NT_STATUS_NO_MEMORY;
6273 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6274 (UCF_SAVE_LCOMP |
6275 (dest_has_wcard ?
6276 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6277 0)));
6279 /* If an error we expect this to be
6280 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6282 if (!NT_STATUS_IS_OK(status)) {
6283 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6284 status)) {
6285 goto out;
6287 /* Create an smb_fname to call rename_internals_fsp() */
6288 status = create_synthetic_smb_fname(ctx,
6289 base_name, NULL,
6290 NULL,
6291 &smb_fname_dst);
6292 if (!NT_STATUS_IS_OK(status)) {
6293 goto out;
6298 if (fsp) {
6299 DEBUG(10,("smb_file_rename_information: "
6300 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6301 fsp->fnum, fsp_str_dbg(fsp),
6302 smb_fname_str_dbg(smb_fname_dst)));
6303 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6304 overwrite);
6305 } else {
6306 DEBUG(10,("smb_file_rename_information: "
6307 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6308 smb_fname_str_dbg(smb_fname_src),
6309 smb_fname_str_dbg(smb_fname_dst)));
6310 status = rename_internals(ctx, conn, req, smb_fname_src,
6311 smb_fname_dst, 0, overwrite, false,
6312 dest_has_wcard,
6313 FILE_WRITE_ATTRIBUTES);
6315 out:
6316 TALLOC_FREE(smb_fname_dst);
6317 return status;
6320 /****************************************************************************
6321 Deal with SMB_SET_POSIX_ACL.
6322 ****************************************************************************/
6324 #if defined(HAVE_POSIX_ACLS)
6325 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6326 const char *pdata,
6327 int total_data,
6328 files_struct *fsp,
6329 const struct smb_filename *smb_fname)
6331 uint16 posix_acl_version;
6332 uint16 num_file_acls;
6333 uint16 num_def_acls;
6334 bool valid_file_acls = True;
6335 bool valid_def_acls = True;
6337 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6338 return NT_STATUS_INVALID_PARAMETER;
6340 posix_acl_version = SVAL(pdata,0);
6341 num_file_acls = SVAL(pdata,2);
6342 num_def_acls = SVAL(pdata,4);
6344 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6345 valid_file_acls = False;
6346 num_file_acls = 0;
6349 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6350 valid_def_acls = False;
6351 num_def_acls = 0;
6354 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6355 return NT_STATUS_INVALID_PARAMETER;
6358 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6359 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6360 return NT_STATUS_INVALID_PARAMETER;
6363 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6364 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6365 (unsigned int)num_file_acls,
6366 (unsigned int)num_def_acls));
6368 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6369 smb_fname->base_name, num_file_acls,
6370 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6371 return map_nt_error_from_unix(errno);
6374 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6375 smb_fname->base_name, &smb_fname->st, num_def_acls,
6376 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6377 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6378 return map_nt_error_from_unix(errno);
6380 return NT_STATUS_OK;
6382 #endif
6384 /****************************************************************************
6385 Deal with SMB_SET_POSIX_LOCK.
6386 ****************************************************************************/
6388 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6389 struct smb_request *req,
6390 const char *pdata,
6391 int total_data,
6392 files_struct *fsp)
6394 uint64_t count;
6395 uint64_t offset;
6396 uint64_t smblctx;
6397 bool blocking_lock = False;
6398 enum brl_type lock_type;
6400 NTSTATUS status = NT_STATUS_OK;
6402 if (fsp == NULL || fsp->fh->fd == -1) {
6403 return NT_STATUS_INVALID_HANDLE;
6406 if (total_data != POSIX_LOCK_DATA_SIZE) {
6407 return NT_STATUS_INVALID_PARAMETER;
6410 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6411 case POSIX_LOCK_TYPE_READ:
6412 lock_type = READ_LOCK;
6413 break;
6414 case POSIX_LOCK_TYPE_WRITE:
6415 /* Return the right POSIX-mappable error code for files opened read-only. */
6416 if (!fsp->can_write) {
6417 return NT_STATUS_INVALID_HANDLE;
6419 lock_type = WRITE_LOCK;
6420 break;
6421 case POSIX_LOCK_TYPE_UNLOCK:
6422 lock_type = UNLOCK_LOCK;
6423 break;
6424 default:
6425 return NT_STATUS_INVALID_PARAMETER;
6428 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6429 blocking_lock = False;
6430 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6431 blocking_lock = True;
6432 } else {
6433 return NT_STATUS_INVALID_PARAMETER;
6436 if (!lp_blocking_locks(SNUM(conn))) {
6437 blocking_lock = False;
6440 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6441 #if defined(HAVE_LONGLONG)
6442 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6443 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6444 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6445 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6446 #else /* HAVE_LONGLONG */
6447 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6448 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6449 #endif /* HAVE_LONGLONG */
6451 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6452 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6453 fsp_str_dbg(fsp),
6454 (unsigned int)lock_type,
6455 (unsigned long long)smblctx,
6456 (double)count,
6457 (double)offset ));
6459 if (lock_type == UNLOCK_LOCK) {
6460 status = do_unlock(req->sconn->msg_ctx,
6461 fsp,
6462 smblctx,
6463 count,
6464 offset,
6465 POSIX_LOCK);
6466 } else {
6467 uint64_t block_smblctx;
6469 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6470 fsp,
6471 smblctx,
6472 count,
6473 offset,
6474 lock_type,
6475 POSIX_LOCK,
6476 blocking_lock,
6477 &status,
6478 &block_smblctx,
6479 NULL);
6481 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6483 * A blocking lock was requested. Package up
6484 * this smb into a queued request and push it
6485 * onto the blocking lock queue.
6487 if(push_blocking_lock_request(br_lck,
6488 req,
6489 fsp,
6490 -1, /* infinite timeout. */
6492 smblctx,
6493 lock_type,
6494 POSIX_LOCK,
6495 offset,
6496 count,
6497 block_smblctx)) {
6498 TALLOC_FREE(br_lck);
6499 return status;
6502 TALLOC_FREE(br_lck);
6505 return status;
6508 /****************************************************************************
6509 Deal with SMB_SET_FILE_BASIC_INFO.
6510 ****************************************************************************/
6512 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6513 const char *pdata,
6514 int total_data,
6515 files_struct *fsp,
6516 const struct smb_filename *smb_fname)
6518 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6519 struct smb_file_time ft;
6520 uint32 dosmode = 0;
6521 NTSTATUS status = NT_STATUS_OK;
6523 ZERO_STRUCT(ft);
6525 if (total_data < 36) {
6526 return NT_STATUS_INVALID_PARAMETER;
6529 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6530 return NT_STATUS_ACCESS_DENIED;
6533 /* Set the attributes */
6534 dosmode = IVAL(pdata,32);
6535 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6536 if (!NT_STATUS_IS_OK(status)) {
6537 return status;
6540 /* create time */
6541 ft.create_time = interpret_long_date(pdata);
6543 /* access time */
6544 ft.atime = interpret_long_date(pdata+8);
6546 /* write time. */
6547 ft.mtime = interpret_long_date(pdata+16);
6549 /* change time. */
6550 ft.ctime = interpret_long_date(pdata+24);
6552 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6553 smb_fname_str_dbg(smb_fname)));
6555 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6556 true);
6559 /****************************************************************************
6560 Deal with SMB_INFO_STANDARD.
6561 ****************************************************************************/
6563 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6564 const char *pdata,
6565 int total_data,
6566 files_struct *fsp,
6567 const struct smb_filename *smb_fname)
6569 struct smb_file_time ft;
6571 ZERO_STRUCT(ft);
6573 if (total_data < 12) {
6574 return NT_STATUS_INVALID_PARAMETER;
6577 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6578 return NT_STATUS_ACCESS_DENIED;
6581 /* create time */
6582 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6583 /* access time */
6584 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6585 /* write time */
6586 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6588 DEBUG(10,("smb_set_info_standard: file %s\n",
6589 smb_fname_str_dbg(smb_fname)));
6591 return smb_set_file_time(conn,
6592 fsp,
6593 smb_fname,
6594 &ft,
6595 true);
6598 /****************************************************************************
6599 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6600 ****************************************************************************/
6602 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6603 struct smb_request *req,
6604 const char *pdata,
6605 int total_data,
6606 files_struct *fsp,
6607 struct smb_filename *smb_fname)
6609 uint64_t allocation_size = 0;
6610 NTSTATUS status = NT_STATUS_OK;
6611 files_struct *new_fsp = NULL;
6613 if (!VALID_STAT(smb_fname->st)) {
6614 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6617 if (total_data < 8) {
6618 return NT_STATUS_INVALID_PARAMETER;
6621 allocation_size = (uint64_t)IVAL(pdata,0);
6622 #ifdef LARGE_SMB_OFF_T
6623 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6624 #else /* LARGE_SMB_OFF_T */
6625 if (IVAL(pdata,4) != 0) {
6626 /* more than 32 bits? */
6627 return NT_STATUS_INVALID_PARAMETER;
6629 #endif /* LARGE_SMB_OFF_T */
6631 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6632 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6633 (double)allocation_size));
6635 if (allocation_size) {
6636 allocation_size = smb_roundup(conn, allocation_size);
6639 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6640 return NT_STATUS_ACCESS_DENIED;
6643 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6644 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6645 (double)allocation_size));
6647 if (fsp && fsp->fh->fd != -1) {
6648 /* Open file handle. */
6649 /* Only change if needed. */
6650 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6651 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6652 return map_nt_error_from_unix(errno);
6655 /* But always update the time. */
6657 * This is equivalent to a write. Ensure it's seen immediately
6658 * if there are no pending writes.
6660 trigger_write_time_update_immediate(fsp);
6661 return NT_STATUS_OK;
6664 /* Pathname or stat or directory file. */
6665 status = SMB_VFS_CREATE_FILE(
6666 conn, /* conn */
6667 req, /* req */
6668 0, /* root_dir_fid */
6669 smb_fname, /* fname */
6670 FILE_WRITE_DATA, /* access_mask */
6671 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6672 FILE_SHARE_DELETE),
6673 FILE_OPEN, /* create_disposition*/
6674 0, /* create_options */
6675 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6676 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6677 0, /* allocation_size */
6678 0, /* private_flags */
6679 NULL, /* sd */
6680 NULL, /* ea_list */
6681 &new_fsp, /* result */
6682 NULL); /* pinfo */
6684 if (!NT_STATUS_IS_OK(status)) {
6685 /* NB. We check for open_was_deferred in the caller. */
6686 return status;
6689 /* Only change if needed. */
6690 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6691 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6692 status = map_nt_error_from_unix(errno);
6693 close_file(req, new_fsp, NORMAL_CLOSE);
6694 return status;
6698 /* Changing the allocation size should set the last mod time. */
6700 * This is equivalent to a write. Ensure it's seen immediately
6701 * if there are no pending writes.
6703 trigger_write_time_update_immediate(new_fsp);
6705 close_file(req, new_fsp, NORMAL_CLOSE);
6706 return NT_STATUS_OK;
6709 /****************************************************************************
6710 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6711 ****************************************************************************/
6713 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6714 struct smb_request *req,
6715 const char *pdata,
6716 int total_data,
6717 files_struct *fsp,
6718 const struct smb_filename *smb_fname,
6719 bool fail_after_createfile)
6721 SMB_OFF_T size;
6723 if (total_data < 8) {
6724 return NT_STATUS_INVALID_PARAMETER;
6727 size = IVAL(pdata,0);
6728 #ifdef LARGE_SMB_OFF_T
6729 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6730 #else /* LARGE_SMB_OFF_T */
6731 if (IVAL(pdata,4) != 0) {
6732 /* more than 32 bits? */
6733 return NT_STATUS_INVALID_PARAMETER;
6735 #endif /* LARGE_SMB_OFF_T */
6736 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6737 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6738 (double)size));
6740 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6741 return NT_STATUS_ACCESS_DENIED;
6744 return smb_set_file_size(conn, req,
6745 fsp,
6746 smb_fname,
6747 &smb_fname->st,
6748 size,
6749 fail_after_createfile);
6752 /****************************************************************************
6753 Allow a UNIX info mknod.
6754 ****************************************************************************/
6756 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6757 const char *pdata,
6758 int total_data,
6759 const struct smb_filename *smb_fname)
6761 uint32 file_type = IVAL(pdata,56);
6762 #if defined(HAVE_MAKEDEV)
6763 uint32 dev_major = IVAL(pdata,60);
6764 uint32 dev_minor = IVAL(pdata,68);
6765 #endif
6766 SMB_DEV_T dev = (SMB_DEV_T)0;
6767 uint32 raw_unixmode = IVAL(pdata,84);
6768 NTSTATUS status;
6769 mode_t unixmode;
6771 if (total_data < 100) {
6772 return NT_STATUS_INVALID_PARAMETER;
6775 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6776 PERM_NEW_FILE, &unixmode);
6777 if (!NT_STATUS_IS_OK(status)) {
6778 return status;
6781 #if defined(HAVE_MAKEDEV)
6782 dev = makedev(dev_major, dev_minor);
6783 #endif
6785 switch (file_type) {
6786 #if defined(S_IFIFO)
6787 case UNIX_TYPE_FIFO:
6788 unixmode |= S_IFIFO;
6789 break;
6790 #endif
6791 #if defined(S_IFSOCK)
6792 case UNIX_TYPE_SOCKET:
6793 unixmode |= S_IFSOCK;
6794 break;
6795 #endif
6796 #if defined(S_IFCHR)
6797 case UNIX_TYPE_CHARDEV:
6798 unixmode |= S_IFCHR;
6799 break;
6800 #endif
6801 #if defined(S_IFBLK)
6802 case UNIX_TYPE_BLKDEV:
6803 unixmode |= S_IFBLK;
6804 break;
6805 #endif
6806 default:
6807 return NT_STATUS_INVALID_PARAMETER;
6810 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6811 "%.0f mode 0%o for file %s\n", (double)dev,
6812 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6814 /* Ok - do the mknod. */
6815 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6816 return map_nt_error_from_unix(errno);
6819 /* If any of the other "set" calls fail we
6820 * don't want to end up with a half-constructed mknod.
6823 if (lp_inherit_perms(SNUM(conn))) {
6824 char *parent;
6825 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6826 &parent, NULL)) {
6827 return NT_STATUS_NO_MEMORY;
6829 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6830 unixmode);
6831 TALLOC_FREE(parent);
6834 return NT_STATUS_OK;
6837 /****************************************************************************
6838 Deal with SMB_SET_FILE_UNIX_BASIC.
6839 ****************************************************************************/
6841 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6842 struct smb_request *req,
6843 const char *pdata,
6844 int total_data,
6845 files_struct *fsp,
6846 const struct smb_filename *smb_fname)
6848 struct smb_file_time ft;
6849 uint32 raw_unixmode;
6850 mode_t unixmode;
6851 SMB_OFF_T size = 0;
6852 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6853 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6854 NTSTATUS status = NT_STATUS_OK;
6855 bool delete_on_fail = False;
6856 enum perm_type ptype;
6857 files_struct *all_fsps = NULL;
6858 bool modify_mtime = true;
6859 struct file_id id;
6860 struct smb_filename *smb_fname_tmp = NULL;
6861 SMB_STRUCT_STAT sbuf;
6863 ZERO_STRUCT(ft);
6865 if (total_data < 100) {
6866 return NT_STATUS_INVALID_PARAMETER;
6869 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6870 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6871 size=IVAL(pdata,0); /* first 8 Bytes are size */
6872 #ifdef LARGE_SMB_OFF_T
6873 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6874 #else /* LARGE_SMB_OFF_T */
6875 if (IVAL(pdata,4) != 0) {
6876 /* more than 32 bits? */
6877 return NT_STATUS_INVALID_PARAMETER;
6879 #endif /* LARGE_SMB_OFF_T */
6882 ft.atime = interpret_long_date(pdata+24); /* access_time */
6883 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6884 set_owner = (uid_t)IVAL(pdata,40);
6885 set_grp = (gid_t)IVAL(pdata,48);
6886 raw_unixmode = IVAL(pdata,84);
6888 if (VALID_STAT(smb_fname->st)) {
6889 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6890 ptype = PERM_EXISTING_DIR;
6891 } else {
6892 ptype = PERM_EXISTING_FILE;
6894 } else {
6895 ptype = PERM_NEW_FILE;
6898 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6899 ptype, &unixmode);
6900 if (!NT_STATUS_IS_OK(status)) {
6901 return status;
6904 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6905 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6906 smb_fname_str_dbg(smb_fname), (double)size,
6907 (unsigned int)set_owner, (unsigned int)set_grp,
6908 (int)raw_unixmode));
6910 sbuf = smb_fname->st;
6912 if (!VALID_STAT(sbuf)) {
6914 * The only valid use of this is to create character and block
6915 * devices, and named pipes. This is deprecated (IMHO) and
6916 * a new info level should be used for mknod. JRA.
6919 status = smb_unix_mknod(conn,
6920 pdata,
6921 total_data,
6922 smb_fname);
6923 if (!NT_STATUS_IS_OK(status)) {
6924 return status;
6927 status = copy_smb_filename(talloc_tos(), smb_fname,
6928 &smb_fname_tmp);
6929 if (!NT_STATUS_IS_OK(status)) {
6930 return status;
6933 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6934 status = map_nt_error_from_unix(errno);
6935 TALLOC_FREE(smb_fname_tmp);
6936 SMB_VFS_UNLINK(conn, smb_fname);
6937 return status;
6940 sbuf = smb_fname_tmp->st;
6941 smb_fname = smb_fname_tmp;
6943 /* Ensure we don't try and change anything else. */
6944 raw_unixmode = SMB_MODE_NO_CHANGE;
6945 size = get_file_size_stat(&sbuf);
6946 ft.atime = sbuf.st_ex_atime;
6947 ft.mtime = sbuf.st_ex_mtime;
6949 * We continue here as we might want to change the
6950 * owner uid/gid.
6952 delete_on_fail = True;
6955 #if 1
6956 /* Horrible backwards compatibility hack as an old server bug
6957 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6958 * */
6960 if (!size) {
6961 size = get_file_size_stat(&sbuf);
6963 #endif
6966 * Deal with the UNIX specific mode set.
6969 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6970 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6971 "setting mode 0%o for file %s\n",
6972 (unsigned int)unixmode,
6973 smb_fname_str_dbg(smb_fname)));
6974 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6975 return map_nt_error_from_unix(errno);
6980 * Deal with the UNIX specific uid set.
6983 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6984 (sbuf.st_ex_uid != set_owner)) {
6985 int ret;
6987 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6988 "changing owner %u for path %s\n",
6989 (unsigned int)set_owner,
6990 smb_fname_str_dbg(smb_fname)));
6992 if (S_ISLNK(sbuf.st_ex_mode)) {
6993 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6994 set_owner, (gid_t)-1);
6995 } else {
6996 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6997 set_owner, (gid_t)-1);
7000 if (ret != 0) {
7001 status = map_nt_error_from_unix(errno);
7002 if (delete_on_fail) {
7003 SMB_VFS_UNLINK(conn, smb_fname);
7005 return status;
7010 * Deal with the UNIX specific gid set.
7013 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7014 (sbuf.st_ex_gid != set_grp)) {
7015 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7016 "changing group %u for file %s\n",
7017 (unsigned int)set_owner,
7018 smb_fname_str_dbg(smb_fname)));
7019 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7020 set_grp) != 0) {
7021 status = map_nt_error_from_unix(errno);
7022 if (delete_on_fail) {
7023 SMB_VFS_UNLINK(conn, smb_fname);
7025 return status;
7029 /* Deal with any size changes. */
7031 status = smb_set_file_size(conn, req,
7032 fsp,
7033 smb_fname,
7034 &sbuf,
7035 size,
7036 false);
7037 if (!NT_STATUS_IS_OK(status)) {
7038 return status;
7041 /* Deal with any time changes. */
7042 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7043 /* No change, don't cancel anything. */
7044 return status;
7047 id = vfs_file_id_from_sbuf(conn, &sbuf);
7048 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7049 all_fsps = file_find_di_next(all_fsps)) {
7051 * We're setting the time explicitly for UNIX.
7052 * Cancel any pending changes over all handles.
7054 all_fsps->update_write_time_on_close = false;
7055 TALLOC_FREE(all_fsps->update_write_time_event);
7059 * Override the "setting_write_time"
7060 * parameter here as it almost does what
7061 * we need. Just remember if we modified
7062 * mtime and send the notify ourselves.
7064 if (null_timespec(ft.mtime)) {
7065 modify_mtime = false;
7068 status = smb_set_file_time(conn,
7069 fsp,
7070 smb_fname,
7071 &ft,
7072 false);
7073 if (modify_mtime) {
7074 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7075 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7077 return status;
7080 /****************************************************************************
7081 Deal with SMB_SET_FILE_UNIX_INFO2.
7082 ****************************************************************************/
7084 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7085 struct smb_request *req,
7086 const char *pdata,
7087 int total_data,
7088 files_struct *fsp,
7089 const struct smb_filename *smb_fname)
7091 NTSTATUS status;
7092 uint32 smb_fflags;
7093 uint32 smb_fmask;
7095 if (total_data < 116) {
7096 return NT_STATUS_INVALID_PARAMETER;
7099 /* Start by setting all the fields that are common between UNIX_BASIC
7100 * and UNIX_INFO2.
7102 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7103 fsp, smb_fname);
7104 if (!NT_STATUS_IS_OK(status)) {
7105 return status;
7108 smb_fflags = IVAL(pdata, 108);
7109 smb_fmask = IVAL(pdata, 112);
7111 /* NB: We should only attempt to alter the file flags if the client
7112 * sends a non-zero mask.
7114 if (smb_fmask != 0) {
7115 int stat_fflags = 0;
7117 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7118 smb_fmask, &stat_fflags)) {
7119 /* Client asked to alter a flag we don't understand. */
7120 return NT_STATUS_INVALID_PARAMETER;
7123 if (fsp && fsp->fh->fd != -1) {
7124 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7125 return NT_STATUS_NOT_SUPPORTED;
7126 } else {
7127 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7128 stat_fflags) != 0) {
7129 return map_nt_error_from_unix(errno);
7134 /* XXX: need to add support for changing the create_time here. You
7135 * can do this for paths on Darwin with setattrlist(2). The right way
7136 * to hook this up is probably by extending the VFS utimes interface.
7139 return NT_STATUS_OK;
7142 /****************************************************************************
7143 Create a directory with POSIX semantics.
7144 ****************************************************************************/
7146 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7147 struct smb_request *req,
7148 char **ppdata,
7149 int total_data,
7150 struct smb_filename *smb_fname,
7151 int *pdata_return_size)
7153 NTSTATUS status = NT_STATUS_OK;
7154 uint32 raw_unixmode = 0;
7155 uint32 mod_unixmode = 0;
7156 mode_t unixmode = (mode_t)0;
7157 files_struct *fsp = NULL;
7158 uint16 info_level_return = 0;
7159 int info;
7160 char *pdata = *ppdata;
7162 if (total_data < 18) {
7163 return NT_STATUS_INVALID_PARAMETER;
7166 raw_unixmode = IVAL(pdata,8);
7167 /* Next 4 bytes are not yet defined. */
7169 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7170 PERM_NEW_DIR, &unixmode);
7171 if (!NT_STATUS_IS_OK(status)) {
7172 return status;
7175 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7177 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7178 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7180 status = SMB_VFS_CREATE_FILE(
7181 conn, /* conn */
7182 req, /* req */
7183 0, /* root_dir_fid */
7184 smb_fname, /* fname */
7185 FILE_READ_ATTRIBUTES, /* access_mask */
7186 FILE_SHARE_NONE, /* share_access */
7187 FILE_CREATE, /* create_disposition*/
7188 FILE_DIRECTORY_FILE, /* create_options */
7189 mod_unixmode, /* file_attributes */
7190 0, /* oplock_request */
7191 0, /* allocation_size */
7192 0, /* private_flags */
7193 NULL, /* sd */
7194 NULL, /* ea_list */
7195 &fsp, /* result */
7196 &info); /* pinfo */
7198 if (NT_STATUS_IS_OK(status)) {
7199 close_file(req, fsp, NORMAL_CLOSE);
7202 info_level_return = SVAL(pdata,16);
7204 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7205 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7206 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7207 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7208 } else {
7209 *pdata_return_size = 12;
7212 /* Realloc the data size */
7213 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7214 if (*ppdata == NULL) {
7215 *pdata_return_size = 0;
7216 return NT_STATUS_NO_MEMORY;
7218 pdata = *ppdata;
7220 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7221 SSVAL(pdata,2,0); /* No fnum. */
7222 SIVAL(pdata,4,info); /* Was directory created. */
7224 switch (info_level_return) {
7225 case SMB_QUERY_FILE_UNIX_BASIC:
7226 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7227 SSVAL(pdata,10,0); /* Padding. */
7228 store_file_unix_basic(conn, pdata + 12, fsp,
7229 &smb_fname->st);
7230 break;
7231 case SMB_QUERY_FILE_UNIX_INFO2:
7232 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7233 SSVAL(pdata,10,0); /* Padding. */
7234 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7235 &smb_fname->st);
7236 break;
7237 default:
7238 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7239 SSVAL(pdata,10,0); /* Padding. */
7240 break;
7243 return status;
7246 /****************************************************************************
7247 Open/Create a file with POSIX semantics.
7248 ****************************************************************************/
7250 static NTSTATUS smb_posix_open(connection_struct *conn,
7251 struct smb_request *req,
7252 char **ppdata,
7253 int total_data,
7254 struct smb_filename *smb_fname,
7255 int *pdata_return_size)
7257 bool extended_oplock_granted = False;
7258 char *pdata = *ppdata;
7259 uint32 flags = 0;
7260 uint32 wire_open_mode = 0;
7261 uint32 raw_unixmode = 0;
7262 uint32 mod_unixmode = 0;
7263 uint32 create_disp = 0;
7264 uint32 access_mask = 0;
7265 uint32 create_options = 0;
7266 NTSTATUS status = NT_STATUS_OK;
7267 mode_t unixmode = (mode_t)0;
7268 files_struct *fsp = NULL;
7269 int oplock_request = 0;
7270 int info = 0;
7271 uint16 info_level_return = 0;
7273 if (total_data < 18) {
7274 return NT_STATUS_INVALID_PARAMETER;
7277 flags = IVAL(pdata,0);
7278 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7279 if (oplock_request) {
7280 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7283 wire_open_mode = IVAL(pdata,4);
7285 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7286 return smb_posix_mkdir(conn, req,
7287 ppdata,
7288 total_data,
7289 smb_fname,
7290 pdata_return_size);
7293 switch (wire_open_mode & SMB_ACCMODE) {
7294 case SMB_O_RDONLY:
7295 access_mask = FILE_READ_DATA;
7296 break;
7297 case SMB_O_WRONLY:
7298 access_mask = FILE_WRITE_DATA;
7299 break;
7300 case SMB_O_RDWR:
7301 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7302 break;
7303 default:
7304 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7305 (unsigned int)wire_open_mode ));
7306 return NT_STATUS_INVALID_PARAMETER;
7309 wire_open_mode &= ~SMB_ACCMODE;
7311 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7312 create_disp = FILE_CREATE;
7313 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7314 create_disp = FILE_OVERWRITE_IF;
7315 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7316 create_disp = FILE_OPEN_IF;
7317 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7318 create_disp = FILE_OPEN;
7319 } else {
7320 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7321 (unsigned int)wire_open_mode ));
7322 return NT_STATUS_INVALID_PARAMETER;
7325 raw_unixmode = IVAL(pdata,8);
7326 /* Next 4 bytes are not yet defined. */
7328 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7329 (VALID_STAT(smb_fname->st) ?
7330 PERM_EXISTING_FILE : PERM_NEW_FILE),
7331 &unixmode);
7333 if (!NT_STATUS_IS_OK(status)) {
7334 return status;
7337 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7339 if (wire_open_mode & SMB_O_SYNC) {
7340 create_options |= FILE_WRITE_THROUGH;
7342 if (wire_open_mode & SMB_O_APPEND) {
7343 access_mask |= FILE_APPEND_DATA;
7345 if (wire_open_mode & SMB_O_DIRECT) {
7346 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7349 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7350 smb_fname_str_dbg(smb_fname),
7351 (unsigned int)wire_open_mode,
7352 (unsigned int)unixmode ));
7354 status = SMB_VFS_CREATE_FILE(
7355 conn, /* conn */
7356 req, /* req */
7357 0, /* root_dir_fid */
7358 smb_fname, /* fname */
7359 access_mask, /* access_mask */
7360 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7361 FILE_SHARE_DELETE),
7362 create_disp, /* create_disposition*/
7363 FILE_NON_DIRECTORY_FILE, /* create_options */
7364 mod_unixmode, /* file_attributes */
7365 oplock_request, /* oplock_request */
7366 0, /* allocation_size */
7367 0, /* private_flags */
7368 NULL, /* sd */
7369 NULL, /* ea_list */
7370 &fsp, /* result */
7371 &info); /* pinfo */
7373 if (!NT_STATUS_IS_OK(status)) {
7374 return status;
7377 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7378 extended_oplock_granted = True;
7381 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7382 extended_oplock_granted = True;
7385 info_level_return = SVAL(pdata,16);
7387 /* Allocate the correct return size. */
7389 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7390 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7391 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7392 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7393 } else {
7394 *pdata_return_size = 12;
7397 /* Realloc the data size */
7398 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7399 if (*ppdata == NULL) {
7400 close_file(req, fsp, ERROR_CLOSE);
7401 *pdata_return_size = 0;
7402 return NT_STATUS_NO_MEMORY;
7404 pdata = *ppdata;
7406 if (extended_oplock_granted) {
7407 if (flags & REQUEST_BATCH_OPLOCK) {
7408 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7409 } else {
7410 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7412 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7413 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7414 } else {
7415 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7418 SSVAL(pdata,2,fsp->fnum);
7419 SIVAL(pdata,4,info); /* Was file created etc. */
7421 switch (info_level_return) {
7422 case SMB_QUERY_FILE_UNIX_BASIC:
7423 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7424 SSVAL(pdata,10,0); /* padding. */
7425 store_file_unix_basic(conn, pdata + 12, fsp,
7426 &smb_fname->st);
7427 break;
7428 case SMB_QUERY_FILE_UNIX_INFO2:
7429 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7430 SSVAL(pdata,10,0); /* padding. */
7431 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7432 &smb_fname->st);
7433 break;
7434 default:
7435 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7436 SSVAL(pdata,10,0); /* padding. */
7437 break;
7439 return NT_STATUS_OK;
7442 /****************************************************************************
7443 Delete a file with POSIX semantics.
7444 ****************************************************************************/
7446 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7447 struct smb_request *req,
7448 const char *pdata,
7449 int total_data,
7450 struct smb_filename *smb_fname)
7452 NTSTATUS status = NT_STATUS_OK;
7453 files_struct *fsp = NULL;
7454 uint16 flags = 0;
7455 char del = 1;
7456 int info = 0;
7457 int create_options = 0;
7458 int i;
7459 struct share_mode_lock *lck = NULL;
7461 if (total_data < 2) {
7462 return NT_STATUS_INVALID_PARAMETER;
7465 flags = SVAL(pdata,0);
7467 if (!VALID_STAT(smb_fname->st)) {
7468 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7471 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7472 !VALID_STAT_OF_DIR(smb_fname->st)) {
7473 return NT_STATUS_NOT_A_DIRECTORY;
7476 DEBUG(10,("smb_posix_unlink: %s %s\n",
7477 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7478 smb_fname_str_dbg(smb_fname)));
7480 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7481 create_options |= FILE_DIRECTORY_FILE;
7484 status = SMB_VFS_CREATE_FILE(
7485 conn, /* conn */
7486 req, /* req */
7487 0, /* root_dir_fid */
7488 smb_fname, /* fname */
7489 DELETE_ACCESS, /* access_mask */
7490 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7491 FILE_SHARE_DELETE),
7492 FILE_OPEN, /* create_disposition*/
7493 create_options, /* create_options */
7494 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7495 0, /* oplock_request */
7496 0, /* allocation_size */
7497 0, /* private_flags */
7498 NULL, /* sd */
7499 NULL, /* ea_list */
7500 &fsp, /* result */
7501 &info); /* pinfo */
7503 if (!NT_STATUS_IS_OK(status)) {
7504 return status;
7508 * Don't lie to client. If we can't really delete due to
7509 * non-POSIX opens return SHARING_VIOLATION.
7512 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7513 NULL);
7514 if (lck == NULL) {
7515 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7516 "lock for file %s\n", fsp_str_dbg(fsp)));
7517 close_file(req, fsp, NORMAL_CLOSE);
7518 return NT_STATUS_INVALID_PARAMETER;
7522 * See if others still have the file open. If this is the case, then
7523 * don't delete. If all opens are POSIX delete we can set the delete
7524 * on close disposition.
7526 for (i=0; i<lck->num_share_modes; i++) {
7527 struct share_mode_entry *e = &lck->share_modes[i];
7528 if (is_valid_share_mode_entry(e)) {
7529 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7530 continue;
7532 /* Fail with sharing violation. */
7533 close_file(req, fsp, NORMAL_CLOSE);
7534 TALLOC_FREE(lck);
7535 return NT_STATUS_SHARING_VIOLATION;
7540 * Set the delete on close.
7542 status = smb_set_file_disposition_info(conn,
7543 &del,
7545 fsp,
7546 smb_fname);
7548 if (!NT_STATUS_IS_OK(status)) {
7549 close_file(req, fsp, NORMAL_CLOSE);
7550 TALLOC_FREE(lck);
7551 return status;
7553 TALLOC_FREE(lck);
7554 return close_file(req, fsp, NORMAL_CLOSE);
7557 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7558 struct smb_request *req,
7559 TALLOC_CTX *mem_ctx,
7560 uint16_t info_level,
7561 files_struct *fsp,
7562 struct smb_filename *smb_fname,
7563 char **ppdata, int total_data,
7564 int *ret_data_size)
7566 char *pdata = *ppdata;
7567 NTSTATUS status = NT_STATUS_OK;
7568 int data_return_size = 0;
7570 *ret_data_size = 0;
7572 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7573 return NT_STATUS_INVALID_LEVEL;
7576 if (!CAN_WRITE(conn)) {
7577 /* Allow POSIX opens. The open path will deny
7578 * any non-readonly opens. */
7579 if (info_level != SMB_POSIX_PATH_OPEN) {
7580 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7584 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7585 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7586 fsp ? fsp->fnum : -1, info_level, total_data));
7588 switch (info_level) {
7590 case SMB_INFO_STANDARD:
7592 status = smb_set_info_standard(conn,
7593 pdata,
7594 total_data,
7595 fsp,
7596 smb_fname);
7597 break;
7600 case SMB_INFO_SET_EA:
7602 status = smb_info_set_ea(conn,
7603 pdata,
7604 total_data,
7605 fsp,
7606 smb_fname);
7607 break;
7610 case SMB_SET_FILE_BASIC_INFO:
7611 case SMB_FILE_BASIC_INFORMATION:
7613 status = smb_set_file_basic_info(conn,
7614 pdata,
7615 total_data,
7616 fsp,
7617 smb_fname);
7618 break;
7621 case SMB_FILE_ALLOCATION_INFORMATION:
7622 case SMB_SET_FILE_ALLOCATION_INFO:
7624 status = smb_set_file_allocation_info(conn, req,
7625 pdata,
7626 total_data,
7627 fsp,
7628 smb_fname);
7629 break;
7632 case SMB_FILE_END_OF_FILE_INFORMATION:
7633 case SMB_SET_FILE_END_OF_FILE_INFO:
7636 * XP/Win7 both fail after the createfile with
7637 * SMB_SET_FILE_END_OF_FILE_INFO but not
7638 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7639 * The level is known here, so pass it down
7640 * appropriately.
7642 bool should_fail =
7643 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7645 status = smb_set_file_end_of_file_info(conn, req,
7646 pdata,
7647 total_data,
7648 fsp,
7649 smb_fname,
7650 should_fail);
7651 break;
7654 case SMB_FILE_DISPOSITION_INFORMATION:
7655 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7657 #if 0
7658 /* JRA - We used to just ignore this on a path ?
7659 * Shouldn't this be invalid level on a pathname
7660 * based call ?
7662 if (tran_call != TRANSACT2_SETFILEINFO) {
7663 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7665 #endif
7666 status = smb_set_file_disposition_info(conn,
7667 pdata,
7668 total_data,
7669 fsp,
7670 smb_fname);
7671 break;
7674 case SMB_FILE_POSITION_INFORMATION:
7676 status = smb_file_position_information(conn,
7677 pdata,
7678 total_data,
7679 fsp);
7680 break;
7683 case SMB_FILE_FULL_EA_INFORMATION:
7685 status = smb_set_file_full_ea_info(conn,
7686 pdata,
7687 total_data,
7688 fsp);
7689 break;
7692 /* From tridge Samba4 :
7693 * MODE_INFORMATION in setfileinfo (I have no
7694 * idea what "mode information" on a file is - it takes a value of 0,
7695 * 2, 4 or 6. What could it be?).
7698 case SMB_FILE_MODE_INFORMATION:
7700 status = smb_file_mode_information(conn,
7701 pdata,
7702 total_data);
7703 break;
7707 * CIFS UNIX extensions.
7710 case SMB_SET_FILE_UNIX_BASIC:
7712 status = smb_set_file_unix_basic(conn, req,
7713 pdata,
7714 total_data,
7715 fsp,
7716 smb_fname);
7717 break;
7720 case SMB_SET_FILE_UNIX_INFO2:
7722 status = smb_set_file_unix_info2(conn, req,
7723 pdata,
7724 total_data,
7725 fsp,
7726 smb_fname);
7727 break;
7730 case SMB_SET_FILE_UNIX_LINK:
7732 if (fsp) {
7733 /* We must have a pathname for this. */
7734 return NT_STATUS_INVALID_LEVEL;
7736 status = smb_set_file_unix_link(conn, req, pdata,
7737 total_data, smb_fname);
7738 break;
7741 case SMB_SET_FILE_UNIX_HLINK:
7743 if (fsp) {
7744 /* We must have a pathname for this. */
7745 return NT_STATUS_INVALID_LEVEL;
7747 status = smb_set_file_unix_hlink(conn, req,
7748 pdata, total_data,
7749 smb_fname);
7750 break;
7753 case SMB_FILE_RENAME_INFORMATION:
7755 status = smb_file_rename_information(conn, req,
7756 pdata, total_data,
7757 fsp, smb_fname);
7758 break;
7761 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7763 /* SMB2 rename information. */
7764 status = smb2_file_rename_information(conn, req,
7765 pdata, total_data,
7766 fsp, smb_fname);
7767 break;
7770 case SMB_FILE_LINK_INFORMATION:
7772 status = smb_file_link_information(conn, req,
7773 pdata, total_data,
7774 fsp, smb_fname);
7775 break;
7778 #if defined(HAVE_POSIX_ACLS)
7779 case SMB_SET_POSIX_ACL:
7781 status = smb_set_posix_acl(conn,
7782 pdata,
7783 total_data,
7784 fsp,
7785 smb_fname);
7786 break;
7788 #endif
7790 case SMB_SET_POSIX_LOCK:
7792 if (!fsp) {
7793 return NT_STATUS_INVALID_LEVEL;
7795 status = smb_set_posix_lock(conn, req,
7796 pdata, total_data, fsp);
7797 break;
7800 case SMB_POSIX_PATH_OPEN:
7802 if (fsp) {
7803 /* We must have a pathname for this. */
7804 return NT_STATUS_INVALID_LEVEL;
7807 status = smb_posix_open(conn, req,
7808 ppdata,
7809 total_data,
7810 smb_fname,
7811 &data_return_size);
7812 break;
7815 case SMB_POSIX_PATH_UNLINK:
7817 if (fsp) {
7818 /* We must have a pathname for this. */
7819 return NT_STATUS_INVALID_LEVEL;
7822 status = smb_posix_unlink(conn, req,
7823 pdata,
7824 total_data,
7825 smb_fname);
7826 break;
7829 default:
7830 return NT_STATUS_INVALID_LEVEL;
7833 if (!NT_STATUS_IS_OK(status)) {
7834 return status;
7837 *ret_data_size = data_return_size;
7838 return NT_STATUS_OK;
7841 /****************************************************************************
7842 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7843 ****************************************************************************/
7845 static void call_trans2setfilepathinfo(connection_struct *conn,
7846 struct smb_request *req,
7847 unsigned int tran_call,
7848 char **pparams, int total_params,
7849 char **ppdata, int total_data,
7850 unsigned int max_data_bytes)
7852 char *params = *pparams;
7853 char *pdata = *ppdata;
7854 uint16 info_level;
7855 struct smb_filename *smb_fname = NULL;
7856 files_struct *fsp = NULL;
7857 NTSTATUS status = NT_STATUS_OK;
7858 int data_return_size = 0;
7860 if (!params) {
7861 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7862 return;
7865 if (tran_call == TRANSACT2_SETFILEINFO) {
7866 if (total_params < 4) {
7867 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7868 return;
7871 fsp = file_fsp(req, SVAL(params,0));
7872 /* Basic check for non-null fsp. */
7873 if (!check_fsp_open(conn, req, fsp)) {
7874 return;
7876 info_level = SVAL(params,2);
7878 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7879 &smb_fname);
7880 if (!NT_STATUS_IS_OK(status)) {
7881 reply_nterror(req, status);
7882 return;
7885 if(fsp->fh->fd == -1) {
7887 * This is actually a SETFILEINFO on a directory
7888 * handle (returned from an NT SMB). NT5.0 seems
7889 * to do this call. JRA.
7891 if (INFO_LEVEL_IS_UNIX(info_level)) {
7892 /* Always do lstat for UNIX calls. */
7893 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7894 DEBUG(3,("call_trans2setfilepathinfo: "
7895 "SMB_VFS_LSTAT of %s failed "
7896 "(%s)\n",
7897 smb_fname_str_dbg(smb_fname),
7898 strerror(errno)));
7899 reply_nterror(req, map_nt_error_from_unix(errno));
7900 return;
7902 } else {
7903 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7904 DEBUG(3,("call_trans2setfilepathinfo: "
7905 "fileinfo of %s failed (%s)\n",
7906 smb_fname_str_dbg(smb_fname),
7907 strerror(errno)));
7908 reply_nterror(req, map_nt_error_from_unix(errno));
7909 return;
7912 } else if (fsp->print_file) {
7914 * Doing a DELETE_ON_CLOSE should cancel a print job.
7916 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7917 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7919 DEBUG(3,("call_trans2setfilepathinfo: "
7920 "Cancelling print job (%s)\n",
7921 fsp_str_dbg(fsp)));
7923 SSVAL(params,0,0);
7924 send_trans2_replies(conn, req, params, 2,
7925 *ppdata, 0,
7926 max_data_bytes);
7927 return;
7928 } else {
7929 reply_nterror(req,
7930 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7931 return;
7933 } else {
7935 * Original code - this is an open file.
7937 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7938 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7939 "of fnum %d failed (%s)\n", fsp->fnum,
7940 strerror(errno)));
7941 reply_nterror(req, map_nt_error_from_unix(errno));
7942 return;
7945 } else {
7946 char *fname = NULL;
7948 /* set path info */
7949 if (total_params < 7) {
7950 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7951 return;
7954 info_level = SVAL(params,0);
7955 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7956 total_params - 6, STR_TERMINATE,
7957 &status);
7958 if (!NT_STATUS_IS_OK(status)) {
7959 reply_nterror(req, status);
7960 return;
7963 status = filename_convert(req, conn,
7964 req->flags2 & FLAGS2_DFS_PATHNAMES,
7965 fname,
7967 NULL,
7968 &smb_fname);
7969 if (!NT_STATUS_IS_OK(status)) {
7970 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7971 reply_botherror(req,
7972 NT_STATUS_PATH_NOT_COVERED,
7973 ERRSRV, ERRbadpath);
7974 return;
7976 reply_nterror(req, status);
7977 return;
7980 if (INFO_LEVEL_IS_UNIX(info_level)) {
7982 * For CIFS UNIX extensions the target name may not exist.
7985 /* Always do lstat for UNIX calls. */
7986 SMB_VFS_LSTAT(conn, smb_fname);
7988 } else if (!VALID_STAT(smb_fname->st) &&
7989 SMB_VFS_STAT(conn, smb_fname)) {
7990 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7991 "%s failed (%s)\n",
7992 smb_fname_str_dbg(smb_fname),
7993 strerror(errno)));
7994 reply_nterror(req, map_nt_error_from_unix(errno));
7995 return;
7999 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8000 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8001 fsp ? fsp->fnum : -1, info_level,total_data));
8003 /* Realloc the parameter size */
8004 *pparams = (char *)SMB_REALLOC(*pparams,2);
8005 if (*pparams == NULL) {
8006 reply_nterror(req, NT_STATUS_NO_MEMORY);
8007 return;
8009 params = *pparams;
8011 SSVAL(params,0,0);
8013 status = smbd_do_setfilepathinfo(conn, req, req,
8014 info_level,
8015 fsp,
8016 smb_fname,
8017 ppdata, total_data,
8018 &data_return_size);
8019 if (!NT_STATUS_IS_OK(status)) {
8020 if (open_was_deferred(req->mid)) {
8021 /* We have re-scheduled this call. */
8022 return;
8024 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8025 /* We have re-scheduled this call. */
8026 return;
8028 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8029 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8030 ERRSRV, ERRbadpath);
8031 return;
8033 if (info_level == SMB_POSIX_PATH_OPEN) {
8034 reply_openerror(req, status);
8035 return;
8038 reply_nterror(req, status);
8039 return;
8042 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8043 max_data_bytes);
8045 return;
8048 /****************************************************************************
8049 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8050 ****************************************************************************/
8052 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8053 char **pparams, int total_params,
8054 char **ppdata, int total_data,
8055 unsigned int max_data_bytes)
8057 struct smb_filename *smb_dname = NULL;
8058 char *params = *pparams;
8059 char *pdata = *ppdata;
8060 char *directory = NULL;
8061 NTSTATUS status = NT_STATUS_OK;
8062 struct ea_list *ea_list = NULL;
8063 TALLOC_CTX *ctx = talloc_tos();
8065 if (!CAN_WRITE(conn)) {
8066 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8067 return;
8070 if (total_params < 5) {
8071 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8072 return;
8075 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8076 total_params - 4, STR_TERMINATE,
8077 &status);
8078 if (!NT_STATUS_IS_OK(status)) {
8079 reply_nterror(req, status);
8080 return;
8083 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8085 status = filename_convert(ctx,
8086 conn,
8087 req->flags2 & FLAGS2_DFS_PATHNAMES,
8088 directory,
8090 NULL,
8091 &smb_dname);
8093 if (!NT_STATUS_IS_OK(status)) {
8094 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8095 reply_botherror(req,
8096 NT_STATUS_PATH_NOT_COVERED,
8097 ERRSRV, ERRbadpath);
8098 return;
8100 reply_nterror(req, status);
8101 return;
8105 * OS/2 workplace shell seems to send SET_EA requests of "null"
8106 * length (4 bytes containing IVAL 4).
8107 * They seem to have no effect. Bug #3212. JRA.
8110 if (total_data && (total_data != 4)) {
8111 /* Any data in this call is an EA list. */
8112 if (total_data < 10) {
8113 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8114 goto out;
8117 if (IVAL(pdata,0) > total_data) {
8118 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8119 IVAL(pdata,0), (unsigned int)total_data));
8120 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8121 goto out;
8124 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8125 total_data - 4);
8126 if (!ea_list) {
8127 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8128 goto out;
8131 if (!lp_ea_support(SNUM(conn))) {
8132 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8133 goto out;
8136 /* If total_data == 4 Windows doesn't care what values
8137 * are placed in that field, it just ignores them.
8138 * The System i QNTC IBM SMB client puts bad values here,
8139 * so ignore them. */
8141 status = create_directory(conn, req, smb_dname);
8143 if (!NT_STATUS_IS_OK(status)) {
8144 reply_nterror(req, status);
8145 goto out;
8148 /* Try and set any given EA. */
8149 if (ea_list) {
8150 status = set_ea(conn, NULL, smb_dname, ea_list);
8151 if (!NT_STATUS_IS_OK(status)) {
8152 reply_nterror(req, status);
8153 goto out;
8157 /* Realloc the parameter and data sizes */
8158 *pparams = (char *)SMB_REALLOC(*pparams,2);
8159 if(*pparams == NULL) {
8160 reply_nterror(req, NT_STATUS_NO_MEMORY);
8161 goto out;
8163 params = *pparams;
8165 SSVAL(params,0,0);
8167 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8169 out:
8170 TALLOC_FREE(smb_dname);
8171 return;
8174 /****************************************************************************
8175 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8176 We don't actually do this - we just send a null response.
8177 ****************************************************************************/
8179 static void call_trans2findnotifyfirst(connection_struct *conn,
8180 struct smb_request *req,
8181 char **pparams, int total_params,
8182 char **ppdata, int total_data,
8183 unsigned int max_data_bytes)
8185 char *params = *pparams;
8186 uint16 info_level;
8188 if (total_params < 6) {
8189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8190 return;
8193 info_level = SVAL(params,4);
8194 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8196 switch (info_level) {
8197 case 1:
8198 case 2:
8199 break;
8200 default:
8201 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8202 return;
8205 /* Realloc the parameter and data sizes */
8206 *pparams = (char *)SMB_REALLOC(*pparams,6);
8207 if (*pparams == NULL) {
8208 reply_nterror(req, NT_STATUS_NO_MEMORY);
8209 return;
8211 params = *pparams;
8213 SSVAL(params,0,fnf_handle);
8214 SSVAL(params,2,0); /* No changes */
8215 SSVAL(params,4,0); /* No EA errors */
8217 fnf_handle++;
8219 if(fnf_handle == 0)
8220 fnf_handle = 257;
8222 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8224 return;
8227 /****************************************************************************
8228 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8229 changes). Currently this does nothing.
8230 ****************************************************************************/
8232 static void call_trans2findnotifynext(connection_struct *conn,
8233 struct smb_request *req,
8234 char **pparams, int total_params,
8235 char **ppdata, int total_data,
8236 unsigned int max_data_bytes)
8238 char *params = *pparams;
8240 DEBUG(3,("call_trans2findnotifynext\n"));
8242 /* Realloc the parameter and data sizes */
8243 *pparams = (char *)SMB_REALLOC(*pparams,4);
8244 if (*pparams == NULL) {
8245 reply_nterror(req, NT_STATUS_NO_MEMORY);
8246 return;
8248 params = *pparams;
8250 SSVAL(params,0,0); /* No changes */
8251 SSVAL(params,2,0); /* No EA errors */
8253 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8255 return;
8258 /****************************************************************************
8259 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8260 ****************************************************************************/
8262 static void call_trans2getdfsreferral(connection_struct *conn,
8263 struct smb_request *req,
8264 char **pparams, int total_params,
8265 char **ppdata, int total_data,
8266 unsigned int max_data_bytes)
8268 char *params = *pparams;
8269 char *pathname = NULL;
8270 int reply_size = 0;
8271 int max_referral_level;
8272 NTSTATUS status = NT_STATUS_OK;
8273 TALLOC_CTX *ctx = talloc_tos();
8275 DEBUG(10,("call_trans2getdfsreferral\n"));
8277 if (total_params < 3) {
8278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8279 return;
8282 max_referral_level = SVAL(params,0);
8284 if(!lp_host_msdfs()) {
8285 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8286 return;
8289 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8290 total_params - 2, STR_TERMINATE);
8291 if (!pathname) {
8292 reply_nterror(req, NT_STATUS_NOT_FOUND);
8293 return;
8295 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8296 ppdata,&status)) < 0) {
8297 reply_nterror(req, status);
8298 return;
8301 SSVAL(req->inbuf, smb_flg2,
8302 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8303 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8305 return;
8308 #define LMCAT_SPL 0x53
8309 #define LMFUNC_GETJOBID 0x60
8311 /****************************************************************************
8312 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8313 ****************************************************************************/
8315 static void call_trans2ioctl(connection_struct *conn,
8316 struct smb_request *req,
8317 char **pparams, int total_params,
8318 char **ppdata, int total_data,
8319 unsigned int max_data_bytes)
8321 char *pdata = *ppdata;
8322 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8324 /* check for an invalid fid before proceeding */
8326 if (!fsp) {
8327 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8328 return;
8331 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8332 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8333 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8334 if (*ppdata == NULL) {
8335 reply_nterror(req, NT_STATUS_NO_MEMORY);
8336 return;
8338 pdata = *ppdata;
8340 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8341 CAN ACCEPT THIS IN UNICODE. JRA. */
8343 /* Job number */
8344 if (fsp->print_file) {
8345 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8346 } else {
8347 SSVAL(pdata, 0, 0);
8349 srvstr_push(pdata, req->flags2, pdata + 2,
8350 global_myname(), 15,
8351 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8352 srvstr_push(pdata, req->flags2, pdata+18,
8353 lp_servicename(SNUM(conn)), 13,
8354 STR_ASCII|STR_TERMINATE); /* Service name */
8355 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8356 max_data_bytes);
8357 return;
8360 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8361 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8364 /****************************************************************************
8365 Reply to a SMBfindclose (stop trans2 directory search).
8366 ****************************************************************************/
8368 void reply_findclose(struct smb_request *req)
8370 int dptr_num;
8371 struct smbd_server_connection *sconn = req->sconn;
8373 START_PROFILE(SMBfindclose);
8375 if (req->wct < 1) {
8376 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8377 END_PROFILE(SMBfindclose);
8378 return;
8381 dptr_num = SVALS(req->vwv+0, 0);
8383 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8385 dptr_close(sconn, &dptr_num);
8387 reply_outbuf(req, 0, 0);
8389 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8391 END_PROFILE(SMBfindclose);
8392 return;
8395 /****************************************************************************
8396 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8397 ****************************************************************************/
8399 void reply_findnclose(struct smb_request *req)
8401 int dptr_num;
8403 START_PROFILE(SMBfindnclose);
8405 if (req->wct < 1) {
8406 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8407 END_PROFILE(SMBfindnclose);
8408 return;
8411 dptr_num = SVAL(req->vwv+0, 0);
8413 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8415 /* We never give out valid handles for a
8416 findnotifyfirst - so any dptr_num is ok here.
8417 Just ignore it. */
8419 reply_outbuf(req, 0, 0);
8421 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8423 END_PROFILE(SMBfindnclose);
8424 return;
8427 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8428 struct trans_state *state)
8430 if (get_Protocol() >= PROTOCOL_NT1) {
8431 req->flags2 |= 0x40; /* IS_LONG_NAME */
8432 SSVAL(req->inbuf,smb_flg2,req->flags2);
8435 if (conn->encrypt_level == Required && !req->encrypted) {
8436 if (state->call != TRANSACT2_QFSINFO &&
8437 state->call != TRANSACT2_SETFSINFO) {
8438 DEBUG(0,("handle_trans2: encryption required "
8439 "with call 0x%x\n",
8440 (unsigned int)state->call));
8441 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8442 return;
8446 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8448 /* Now we must call the relevant TRANS2 function */
8449 switch(state->call) {
8450 case TRANSACT2_OPEN:
8452 START_PROFILE(Trans2_open);
8453 call_trans2open(conn, req,
8454 &state->param, state->total_param,
8455 &state->data, state->total_data,
8456 state->max_data_return);
8457 END_PROFILE(Trans2_open);
8458 break;
8461 case TRANSACT2_FINDFIRST:
8463 START_PROFILE(Trans2_findfirst);
8464 call_trans2findfirst(conn, req,
8465 &state->param, state->total_param,
8466 &state->data, state->total_data,
8467 state->max_data_return);
8468 END_PROFILE(Trans2_findfirst);
8469 break;
8472 case TRANSACT2_FINDNEXT:
8474 START_PROFILE(Trans2_findnext);
8475 call_trans2findnext(conn, req,
8476 &state->param, state->total_param,
8477 &state->data, state->total_data,
8478 state->max_data_return);
8479 END_PROFILE(Trans2_findnext);
8480 break;
8483 case TRANSACT2_QFSINFO:
8485 START_PROFILE(Trans2_qfsinfo);
8486 call_trans2qfsinfo(conn, req,
8487 &state->param, state->total_param,
8488 &state->data, state->total_data,
8489 state->max_data_return);
8490 END_PROFILE(Trans2_qfsinfo);
8491 break;
8494 case TRANSACT2_SETFSINFO:
8496 START_PROFILE(Trans2_setfsinfo);
8497 call_trans2setfsinfo(conn, req,
8498 &state->param, state->total_param,
8499 &state->data, state->total_data,
8500 state->max_data_return);
8501 END_PROFILE(Trans2_setfsinfo);
8502 break;
8505 case TRANSACT2_QPATHINFO:
8506 case TRANSACT2_QFILEINFO:
8508 START_PROFILE(Trans2_qpathinfo);
8509 call_trans2qfilepathinfo(conn, req, state->call,
8510 &state->param, state->total_param,
8511 &state->data, state->total_data,
8512 state->max_data_return);
8513 END_PROFILE(Trans2_qpathinfo);
8514 break;
8517 case TRANSACT2_SETPATHINFO:
8518 case TRANSACT2_SETFILEINFO:
8520 START_PROFILE(Trans2_setpathinfo);
8521 call_trans2setfilepathinfo(conn, req, state->call,
8522 &state->param, state->total_param,
8523 &state->data, state->total_data,
8524 state->max_data_return);
8525 END_PROFILE(Trans2_setpathinfo);
8526 break;
8529 case TRANSACT2_FINDNOTIFYFIRST:
8531 START_PROFILE(Trans2_findnotifyfirst);
8532 call_trans2findnotifyfirst(conn, req,
8533 &state->param, state->total_param,
8534 &state->data, state->total_data,
8535 state->max_data_return);
8536 END_PROFILE(Trans2_findnotifyfirst);
8537 break;
8540 case TRANSACT2_FINDNOTIFYNEXT:
8542 START_PROFILE(Trans2_findnotifynext);
8543 call_trans2findnotifynext(conn, req,
8544 &state->param, state->total_param,
8545 &state->data, state->total_data,
8546 state->max_data_return);
8547 END_PROFILE(Trans2_findnotifynext);
8548 break;
8551 case TRANSACT2_MKDIR:
8553 START_PROFILE(Trans2_mkdir);
8554 call_trans2mkdir(conn, req,
8555 &state->param, state->total_param,
8556 &state->data, state->total_data,
8557 state->max_data_return);
8558 END_PROFILE(Trans2_mkdir);
8559 break;
8562 case TRANSACT2_GET_DFS_REFERRAL:
8564 START_PROFILE(Trans2_get_dfs_referral);
8565 call_trans2getdfsreferral(conn, req,
8566 &state->param, state->total_param,
8567 &state->data, state->total_data,
8568 state->max_data_return);
8569 END_PROFILE(Trans2_get_dfs_referral);
8570 break;
8573 case TRANSACT2_IOCTL:
8575 START_PROFILE(Trans2_ioctl);
8576 call_trans2ioctl(conn, req,
8577 &state->param, state->total_param,
8578 &state->data, state->total_data,
8579 state->max_data_return);
8580 END_PROFILE(Trans2_ioctl);
8581 break;
8584 default:
8585 /* Error in request */
8586 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8587 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8591 /****************************************************************************
8592 Reply to a SMBtrans2.
8593 ****************************************************************************/
8595 void reply_trans2(struct smb_request *req)
8597 connection_struct *conn = req->conn;
8598 unsigned int dsoff;
8599 unsigned int dscnt;
8600 unsigned int psoff;
8601 unsigned int pscnt;
8602 unsigned int tran_call;
8603 struct trans_state *state;
8604 NTSTATUS result;
8606 START_PROFILE(SMBtrans2);
8608 if (req->wct < 14) {
8609 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8610 END_PROFILE(SMBtrans2);
8611 return;
8614 dsoff = SVAL(req->vwv+12, 0);
8615 dscnt = SVAL(req->vwv+11, 0);
8616 psoff = SVAL(req->vwv+10, 0);
8617 pscnt = SVAL(req->vwv+9, 0);
8618 tran_call = SVAL(req->vwv+14, 0);
8620 result = allow_new_trans(conn->pending_trans, req->mid);
8621 if (!NT_STATUS_IS_OK(result)) {
8622 DEBUG(2, ("Got invalid trans2 request: %s\n",
8623 nt_errstr(result)));
8624 reply_nterror(req, result);
8625 END_PROFILE(SMBtrans2);
8626 return;
8629 if (IS_IPC(conn)) {
8630 switch (tran_call) {
8631 /* List the allowed trans2 calls on IPC$ */
8632 case TRANSACT2_OPEN:
8633 case TRANSACT2_GET_DFS_REFERRAL:
8634 case TRANSACT2_QFILEINFO:
8635 case TRANSACT2_QFSINFO:
8636 case TRANSACT2_SETFSINFO:
8637 break;
8638 default:
8639 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8640 END_PROFILE(SMBtrans2);
8641 return;
8645 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8646 DEBUG(0, ("talloc failed\n"));
8647 reply_nterror(req, NT_STATUS_NO_MEMORY);
8648 END_PROFILE(SMBtrans2);
8649 return;
8652 state->cmd = SMBtrans2;
8654 state->mid = req->mid;
8655 state->vuid = req->vuid;
8656 state->setup_count = SVAL(req->vwv+13, 0);
8657 state->setup = NULL;
8658 state->total_param = SVAL(req->vwv+0, 0);
8659 state->param = NULL;
8660 state->total_data = SVAL(req->vwv+1, 0);
8661 state->data = NULL;
8662 state->max_param_return = SVAL(req->vwv+2, 0);
8663 state->max_data_return = SVAL(req->vwv+3, 0);
8664 state->max_setup_return = SVAL(req->vwv+4, 0);
8665 state->close_on_completion = BITSETW(req->vwv+5, 0);
8666 state->one_way = BITSETW(req->vwv+5, 1);
8668 state->call = tran_call;
8670 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8671 is so as a sanity check */
8672 if (state->setup_count != 1) {
8674 * Need to have rc=0 for ioctl to get job id for OS/2.
8675 * Network printing will fail if function is not successful.
8676 * Similar function in reply.c will be used if protocol
8677 * is LANMAN1.0 instead of LM1.2X002.
8678 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8679 * outbuf doesn't have to be set(only job id is used).
8681 if ( (state->setup_count == 4)
8682 && (tran_call == TRANSACT2_IOCTL)
8683 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8684 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8685 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8686 } else {
8687 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8688 DEBUG(2,("Transaction is %d\n",tran_call));
8689 TALLOC_FREE(state);
8690 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8691 END_PROFILE(SMBtrans2);
8692 return;
8696 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8697 goto bad_param;
8699 if (state->total_data) {
8701 if (trans_oob(state->total_data, 0, dscnt)
8702 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8703 goto bad_param;
8706 /* Can't use talloc here, the core routines do realloc on the
8707 * params and data. */
8708 state->data = (char *)SMB_MALLOC(state->total_data);
8709 if (state->data == NULL) {
8710 DEBUG(0,("reply_trans2: data malloc fail for %u "
8711 "bytes !\n", (unsigned int)state->total_data));
8712 TALLOC_FREE(state);
8713 reply_nterror(req, NT_STATUS_NO_MEMORY);
8714 END_PROFILE(SMBtrans2);
8715 return;
8718 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8721 if (state->total_param) {
8723 if (trans_oob(state->total_param, 0, pscnt)
8724 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8725 goto bad_param;
8728 /* Can't use talloc here, the core routines do realloc on the
8729 * params and data. */
8730 state->param = (char *)SMB_MALLOC(state->total_param);
8731 if (state->param == NULL) {
8732 DEBUG(0,("reply_trans: param malloc fail for %u "
8733 "bytes !\n", (unsigned int)state->total_param));
8734 SAFE_FREE(state->data);
8735 TALLOC_FREE(state);
8736 reply_nterror(req, NT_STATUS_NO_MEMORY);
8737 END_PROFILE(SMBtrans2);
8738 return;
8741 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8744 state->received_data = dscnt;
8745 state->received_param = pscnt;
8747 if ((state->received_param == state->total_param) &&
8748 (state->received_data == state->total_data)) {
8750 handle_trans2(conn, req, state);
8752 SAFE_FREE(state->data);
8753 SAFE_FREE(state->param);
8754 TALLOC_FREE(state);
8755 END_PROFILE(SMBtrans2);
8756 return;
8759 DLIST_ADD(conn->pending_trans, state);
8761 /* We need to send an interim response then receive the rest
8762 of the parameter/data bytes */
8763 reply_outbuf(req, 0, 0);
8764 show_msg((char *)req->outbuf);
8765 END_PROFILE(SMBtrans2);
8766 return;
8768 bad_param:
8770 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8771 SAFE_FREE(state->data);
8772 SAFE_FREE(state->param);
8773 TALLOC_FREE(state);
8774 END_PROFILE(SMBtrans2);
8775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8779 /****************************************************************************
8780 Reply to a SMBtranss2
8781 ****************************************************************************/
8783 void reply_transs2(struct smb_request *req)
8785 connection_struct *conn = req->conn;
8786 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8787 struct trans_state *state;
8789 START_PROFILE(SMBtranss2);
8791 show_msg((char *)req->inbuf);
8793 if (req->wct < 8) {
8794 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8795 END_PROFILE(SMBtranss2);
8796 return;
8799 for (state = conn->pending_trans; state != NULL;
8800 state = state->next) {
8801 if (state->mid == req->mid) {
8802 break;
8806 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8808 END_PROFILE(SMBtranss2);
8809 return;
8812 /* Revise state->total_param and state->total_data in case they have
8813 changed downwards */
8815 if (SVAL(req->vwv+0, 0) < state->total_param)
8816 state->total_param = SVAL(req->vwv+0, 0);
8817 if (SVAL(req->vwv+1, 0) < state->total_data)
8818 state->total_data = SVAL(req->vwv+1, 0);
8820 pcnt = SVAL(req->vwv+2, 0);
8821 poff = SVAL(req->vwv+3, 0);
8822 pdisp = SVAL(req->vwv+4, 0);
8824 dcnt = SVAL(req->vwv+5, 0);
8825 doff = SVAL(req->vwv+6, 0);
8826 ddisp = SVAL(req->vwv+7, 0);
8828 state->received_param += pcnt;
8829 state->received_data += dcnt;
8831 if ((state->received_data > state->total_data) ||
8832 (state->received_param > state->total_param))
8833 goto bad_param;
8835 if (pcnt) {
8836 if (trans_oob(state->total_param, pdisp, pcnt)
8837 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8838 goto bad_param;
8840 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8843 if (dcnt) {
8844 if (trans_oob(state->total_data, ddisp, dcnt)
8845 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8846 goto bad_param;
8848 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8851 if ((state->received_param < state->total_param) ||
8852 (state->received_data < state->total_data)) {
8853 END_PROFILE(SMBtranss2);
8854 return;
8857 handle_trans2(conn, req, state);
8859 DLIST_REMOVE(conn->pending_trans, state);
8860 SAFE_FREE(state->data);
8861 SAFE_FREE(state->param);
8862 TALLOC_FREE(state);
8864 END_PROFILE(SMBtranss2);
8865 return;
8867 bad_param:
8869 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8870 DLIST_REMOVE(conn->pending_trans, state);
8871 SAFE_FREE(state->data);
8872 SAFE_FREE(state->param);
8873 TALLOC_FREE(state);
8874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8875 END_PROFILE(SMBtranss2);
8876 return;