s3: add FILE_ATTRIBUTE_SPARSE to get_stat_dos_flags
[Samba/wip.git] / source3 / smbd / trans2.c
blobddae99d7cced30b6123f755eac79fd500ed74d04
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 directory = talloc_strdup(talloc_tos(), "./");
2356 if (!directory) {
2357 reply_nterror(req, NT_STATUS_NO_MEMORY);
2358 goto out;
2360 } else {
2361 *p = 0;
2364 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2366 if (info_level == SMB_FIND_EA_LIST) {
2367 uint32 ea_size;
2369 if (total_data < 4) {
2370 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2371 goto out;
2374 ea_size = IVAL(pdata,0);
2375 if (ea_size != total_data) {
2376 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2377 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2378 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2379 goto out;
2382 if (!lp_ea_support(SNUM(conn))) {
2383 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2384 goto out;
2387 /* Pull out the list of names. */
2388 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2389 if (!ea_list) {
2390 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2391 goto out;
2395 *ppdata = (char *)SMB_REALLOC(
2396 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2397 if(*ppdata == NULL ) {
2398 reply_nterror(req, NT_STATUS_NO_MEMORY);
2399 goto out;
2401 pdata = *ppdata;
2402 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2404 /* Realloc the params space */
2405 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2406 if (*pparams == NULL) {
2407 reply_nterror(req, NT_STATUS_NO_MEMORY);
2408 goto out;
2410 params = *pparams;
2412 /* Save the wildcard match and attribs we are using on this directory -
2413 needed as lanman2 assumes these are being saved between calls */
2415 ntstatus = dptr_create(conn,
2416 directory,
2417 False,
2418 True,
2419 req->smbpid,
2420 mask,
2421 mask_contains_wcard,
2422 dirtype,
2423 &dirptr);
2425 if (!NT_STATUS_IS_OK(ntstatus)) {
2426 reply_nterror(req, ntstatus);
2427 goto out;
2430 dptr_num = dptr_dnum(dirptr);
2431 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2433 /* Initialize per TRANS2_FIND_FIRST operation data */
2434 dptr_init_search_op(dirptr);
2436 /* We don't need to check for VOL here as this is returned by
2437 a different TRANS2 call. */
2439 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2440 directory,lp_dontdescend(SNUM(conn))));
2441 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2442 dont_descend = True;
2444 p = pdata;
2445 space_remaining = max_data_bytes;
2446 out_of_space = False;
2448 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2449 bool got_exact_match = False;
2451 /* this is a heuristic to avoid seeking the dirptr except when
2452 absolutely necessary. It allows for a filename of about 40 chars */
2453 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2454 out_of_space = True;
2455 finished = False;
2456 } else {
2457 finished = !get_lanman2_dir_entry(ctx,
2458 conn,
2459 dirptr,
2460 req->flags2,
2461 mask,dirtype,info_level,
2462 requires_resume_key,dont_descend,
2463 ask_sharemode,
2464 &p,pdata,data_end,
2465 space_remaining, &out_of_space,
2466 &got_exact_match,
2467 &last_entry_off, ea_list);
2470 if (finished && out_of_space)
2471 finished = False;
2473 if (!finished && !out_of_space)
2474 numentries++;
2477 * As an optimisation if we know we aren't looking
2478 * for a wildcard name (ie. the name matches the wildcard exactly)
2479 * then we can finish on any (first) match.
2480 * This speeds up large directory searches. JRA.
2483 if(got_exact_match)
2484 finished = True;
2486 /* Ensure space_remaining never goes -ve. */
2487 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2488 space_remaining = 0;
2489 out_of_space = true;
2490 } else {
2491 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2495 /* Check if we can close the dirptr */
2496 if(close_after_first || (finished && close_if_end)) {
2497 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2498 dptr_close(sconn, &dptr_num);
2502 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2503 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2504 * the protocol level is less than NT1. Tested with smbclient. JRA.
2505 * This should fix the OS/2 client bug #2335.
2508 if(numentries == 0) {
2509 dptr_close(sconn, &dptr_num);
2510 if (get_Protocol() < PROTOCOL_NT1) {
2511 reply_force_doserror(req, ERRDOS, ERRnofiles);
2512 goto out;
2513 } else {
2514 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2515 ERRDOS, ERRbadfile);
2516 goto out;
2520 /* At this point pdata points to numentries directory entries. */
2522 /* Set up the return parameter block */
2523 SSVAL(params,0,dptr_num);
2524 SSVAL(params,2,numentries);
2525 SSVAL(params,4,finished);
2526 SSVAL(params,6,0); /* Never an EA error */
2527 SSVAL(params,8,last_entry_off);
2529 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2530 max_data_bytes);
2532 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2533 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2534 if (!directory) {
2535 reply_nterror(req, NT_STATUS_NO_MEMORY);
2539 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2540 smb_fn_name(req->cmd),
2541 mask, directory, dirtype, numentries ) );
2544 * Force a name mangle here to ensure that the
2545 * mask as an 8.3 name is top of the mangled cache.
2546 * The reasons for this are subtle. Don't remove
2547 * this code unless you know what you are doing
2548 * (see PR#13758). JRA.
2551 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2552 char mangled_name[13];
2553 name_to_8_3(mask, mangled_name, True, conn->params);
2555 out:
2556 TALLOC_FREE(smb_dname);
2557 return;
2560 /****************************************************************************
2561 Reply to a TRANS2_FINDNEXT.
2562 ****************************************************************************/
2564 static void call_trans2findnext(connection_struct *conn,
2565 struct smb_request *req,
2566 char **pparams, int total_params,
2567 char **ppdata, int total_data,
2568 unsigned int max_data_bytes)
2570 /* We must be careful here that we don't return more than the
2571 allowed number of data bytes. If this means returning fewer than
2572 maxentries then so be it. We assume that the redirector has
2573 enough room for the fixed number of parameter bytes it has
2574 requested. */
2575 char *params = *pparams;
2576 char *pdata = *ppdata;
2577 char *data_end;
2578 int dptr_num;
2579 int maxentries;
2580 uint16 info_level;
2581 uint32 resume_key;
2582 uint16 findnext_flags;
2583 bool close_after_request;
2584 bool close_if_end;
2585 bool requires_resume_key;
2586 bool continue_bit;
2587 bool mask_contains_wcard = False;
2588 char *resume_name = NULL;
2589 const char *mask = NULL;
2590 const char *directory = NULL;
2591 char *p = NULL;
2592 uint16 dirtype;
2593 int numentries = 0;
2594 int i, last_entry_off=0;
2595 bool finished = False;
2596 bool dont_descend = False;
2597 bool out_of_space = False;
2598 int space_remaining;
2599 struct ea_list *ea_list = NULL;
2600 NTSTATUS ntstatus = NT_STATUS_OK;
2601 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2602 TALLOC_CTX *ctx = talloc_tos();
2603 struct dptr_struct *dirptr;
2604 struct smbd_server_connection *sconn = req->sconn;
2606 if (total_params < 13) {
2607 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2608 return;
2611 dptr_num = SVAL(params,0);
2612 maxentries = SVAL(params,2);
2613 info_level = SVAL(params,4);
2614 resume_key = IVAL(params,6);
2615 findnext_flags = SVAL(params,10);
2616 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2617 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2618 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2619 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2621 if (!continue_bit) {
2622 /* We only need resume_name if continue_bit is zero. */
2623 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2624 params+12,
2625 total_params - 12, STR_TERMINATE, &ntstatus,
2626 &mask_contains_wcard);
2627 if (!NT_STATUS_IS_OK(ntstatus)) {
2628 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2629 complain (it thinks we're asking for the directory above the shared
2630 path or an invalid name). Catch this as the resume name is only compared, never used in
2631 a file access. JRA. */
2632 srvstr_pull_talloc(ctx, params, req->flags2,
2633 &resume_name, params+12,
2634 total_params - 12,
2635 STR_TERMINATE);
2637 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2638 reply_nterror(req, ntstatus);
2639 return;
2644 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2645 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2646 resume_key = %d resume name = %s continue=%d level = %d\n",
2647 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2648 requires_resume_key, resume_key,
2649 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2651 if (!maxentries) {
2652 /* W2K3 seems to treat zero as 1. */
2653 maxentries = 1;
2656 switch (info_level) {
2657 case SMB_FIND_INFO_STANDARD:
2658 case SMB_FIND_EA_SIZE:
2659 case SMB_FIND_EA_LIST:
2660 case SMB_FIND_FILE_DIRECTORY_INFO:
2661 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2662 case SMB_FIND_FILE_NAMES_INFO:
2663 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2664 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2665 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2666 break;
2667 case SMB_FIND_FILE_UNIX:
2668 case SMB_FIND_FILE_UNIX_INFO2:
2669 /* Always use filesystem for UNIX mtime query. */
2670 ask_sharemode = false;
2671 if (!lp_unix_extensions()) {
2672 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2673 return;
2675 break;
2676 default:
2677 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2678 return;
2681 if (info_level == SMB_FIND_EA_LIST) {
2682 uint32 ea_size;
2684 if (total_data < 4) {
2685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2686 return;
2689 ea_size = IVAL(pdata,0);
2690 if (ea_size != total_data) {
2691 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2692 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2693 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2694 return;
2697 if (!lp_ea_support(SNUM(conn))) {
2698 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2699 return;
2702 /* Pull out the list of names. */
2703 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2704 if (!ea_list) {
2705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2706 return;
2710 *ppdata = (char *)SMB_REALLOC(
2711 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2712 if(*ppdata == NULL) {
2713 reply_nterror(req, NT_STATUS_NO_MEMORY);
2714 return;
2717 pdata = *ppdata;
2718 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2720 /* Realloc the params space */
2721 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2722 if(*pparams == NULL ) {
2723 reply_nterror(req, NT_STATUS_NO_MEMORY);
2724 return;
2727 params = *pparams;
2729 /* Check that the dptr is valid */
2730 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2731 reply_nterror(req, STATUS_NO_MORE_FILES);
2732 return;
2735 directory = dptr_path(sconn, dptr_num);
2737 /* Get the wildcard mask from the dptr */
2738 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2739 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2740 reply_nterror(req, STATUS_NO_MORE_FILES);
2741 return;
2744 mask = p;
2746 /* Get the attr mask from the dptr */
2747 dirtype = dptr_attr(sconn, dptr_num);
2749 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2750 dptr_num, mask, dirtype,
2751 (long)dirptr,
2752 dptr_TellDir(dirptr)));
2754 /* Initialize per TRANS2_FIND_NEXT operation data */
2755 dptr_init_search_op(dirptr);
2757 /* We don't need to check for VOL here as this is returned by
2758 a different TRANS2 call. */
2760 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2761 directory,lp_dontdescend(SNUM(conn))));
2762 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2763 dont_descend = True;
2765 p = pdata;
2766 space_remaining = max_data_bytes;
2767 out_of_space = False;
2770 * Seek to the correct position. We no longer use the resume key but
2771 * depend on the last file name instead.
2774 if(!continue_bit && resume_name && *resume_name) {
2775 SMB_STRUCT_STAT st;
2777 long current_pos = 0;
2779 * Remember, name_to_8_3 is called by
2780 * get_lanman2_dir_entry(), so the resume name
2781 * could be mangled. Ensure we check the unmangled name.
2784 if (mangle_is_mangled(resume_name, conn->params)) {
2785 char *new_resume_name = NULL;
2786 mangle_lookup_name_from_8_3(ctx,
2787 resume_name,
2788 &new_resume_name,
2789 conn->params);
2790 if (new_resume_name) {
2791 resume_name = new_resume_name;
2796 * Fix for NT redirector problem triggered by resume key indexes
2797 * changing between directory scans. We now return a resume key of 0
2798 * and instead look for the filename to continue from (also given
2799 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2800 * findfirst/findnext (as is usual) then the directory pointer
2801 * should already be at the correct place.
2804 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2805 } /* end if resume_name && !continue_bit */
2807 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2808 bool got_exact_match = False;
2810 /* this is a heuristic to avoid seeking the dirptr except when
2811 absolutely necessary. It allows for a filename of about 40 chars */
2812 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2813 out_of_space = True;
2814 finished = False;
2815 } else {
2816 finished = !get_lanman2_dir_entry(ctx,
2817 conn,
2818 dirptr,
2819 req->flags2,
2820 mask,dirtype,info_level,
2821 requires_resume_key,dont_descend,
2822 ask_sharemode,
2823 &p,pdata,data_end,
2824 space_remaining, &out_of_space,
2825 &got_exact_match,
2826 &last_entry_off, ea_list);
2829 if (finished && out_of_space)
2830 finished = False;
2832 if (!finished && !out_of_space)
2833 numentries++;
2836 * As an optimisation if we know we aren't looking
2837 * for a wildcard name (ie. the name matches the wildcard exactly)
2838 * then we can finish on any (first) match.
2839 * This speeds up large directory searches. JRA.
2842 if(got_exact_match)
2843 finished = True;
2845 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2848 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2849 smb_fn_name(req->cmd),
2850 mask, directory, dirtype, numentries ) );
2852 /* Check if we can close the dirptr */
2853 if(close_after_request || (finished && close_if_end)) {
2854 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2855 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2858 /* Set up the return parameter block */
2859 SSVAL(params,0,numentries);
2860 SSVAL(params,2,finished);
2861 SSVAL(params,4,0); /* Never an EA error */
2862 SSVAL(params,6,last_entry_off);
2864 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2865 max_data_bytes);
2867 return;
2870 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2872 E_md4hash(lp_servicename(SNUM(conn)),objid);
2873 return objid;
2876 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2878 SMB_ASSERT(extended_info != NULL);
2880 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2881 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2882 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2883 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2884 #ifdef SAMBA_VERSION_REVISION
2885 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2886 #endif
2887 extended_info->samba_subversion = 0;
2888 #ifdef SAMBA_VERSION_RC_RELEASE
2889 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2890 #else
2891 #ifdef SAMBA_VERSION_PRE_RELEASE
2892 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2893 #endif
2894 #endif
2895 #ifdef SAMBA_VERSION_VENDOR_PATCH
2896 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2897 #endif
2898 extended_info->samba_gitcommitdate = 0;
2899 #ifdef SAMBA_VERSION_COMMIT_TIME
2900 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2901 #endif
2903 memset(extended_info->samba_version_string, 0,
2904 sizeof(extended_info->samba_version_string));
2906 snprintf (extended_info->samba_version_string,
2907 sizeof(extended_info->samba_version_string),
2908 "%s", samba_version_string());
2911 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2912 TALLOC_CTX *mem_ctx,
2913 uint16_t info_level,
2914 uint16_t flags2,
2915 unsigned int max_data_bytes,
2916 char **ppdata,
2917 int *ret_data_len)
2919 char *pdata, *end_data;
2920 int data_len = 0, len;
2921 const char *vname = volume_label(SNUM(conn));
2922 int snum = SNUM(conn);
2923 char *fstype = lp_fstype(SNUM(conn));
2924 uint32 additional_flags = 0;
2925 struct smb_filename smb_fname_dot;
2926 SMB_STRUCT_STAT st;
2928 if (IS_IPC(conn)) {
2929 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2930 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2931 "info level (0x%x) on IPC$.\n",
2932 (unsigned int)info_level));
2933 return NT_STATUS_ACCESS_DENIED;
2937 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2939 ZERO_STRUCT(smb_fname_dot);
2940 smb_fname_dot.base_name = discard_const_p(char, ".");
2942 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2943 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2944 return map_nt_error_from_unix(errno);
2947 st = smb_fname_dot.st;
2949 *ppdata = (char *)SMB_REALLOC(
2950 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2951 if (*ppdata == NULL) {
2952 return NT_STATUS_NO_MEMORY;
2955 pdata = *ppdata;
2956 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2957 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2959 switch (info_level) {
2960 case SMB_INFO_ALLOCATION:
2962 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2963 data_len = 18;
2964 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2965 return map_nt_error_from_unix(errno);
2968 block_size = lp_block_size(snum);
2969 if (bsize < block_size) {
2970 uint64_t factor = block_size/bsize;
2971 bsize = block_size;
2972 dsize /= factor;
2973 dfree /= factor;
2975 if (bsize > block_size) {
2976 uint64_t factor = bsize/block_size;
2977 bsize = block_size;
2978 dsize *= factor;
2979 dfree *= factor;
2981 bytes_per_sector = 512;
2982 sectors_per_unit = bsize/bytes_per_sector;
2984 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2985 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2986 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2988 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2989 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2990 SIVAL(pdata,l1_cUnit,dsize);
2991 SIVAL(pdata,l1_cUnitAvail,dfree);
2992 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2993 break;
2996 case SMB_INFO_VOLUME:
2997 /* Return volume name */
2999 * Add volume serial number - hash of a combination of
3000 * the called hostname and the service name.
3002 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3004 * Win2k3 and previous mess this up by sending a name length
3005 * one byte short. I believe only older clients (OS/2 Win9x) use
3006 * this call so try fixing this by adding a terminating null to
3007 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3009 len = srvstr_push(
3010 pdata, flags2,
3011 pdata+l2_vol_szVolLabel, vname,
3012 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3013 STR_NOALIGN|STR_TERMINATE);
3014 SCVAL(pdata,l2_vol_cch,len);
3015 data_len = l2_vol_szVolLabel + len;
3016 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3017 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3018 len, vname));
3019 break;
3021 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3022 case SMB_FS_ATTRIBUTE_INFORMATION:
3024 additional_flags = 0;
3025 #if defined(HAVE_SYS_QUOTAS)
3026 additional_flags |= FILE_VOLUME_QUOTAS;
3027 #endif
3029 if(lp_nt_acl_support(SNUM(conn))) {
3030 additional_flags |= FILE_PERSISTENT_ACLS;
3033 /* Capabilities are filled in at connection time through STATVFS call */
3034 additional_flags |= conn->fs_capabilities;
3035 additional_flags |= lp_parm_int(conn->params->service,
3036 "share", "fake_fscaps",
3039 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3040 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3041 additional_flags); /* FS ATTRIBUTES */
3043 SIVAL(pdata,4,255); /* Max filename component length */
3044 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3045 and will think we can't do long filenames */
3046 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3047 PTR_DIFF(end_data, pdata+12),
3048 STR_UNICODE);
3049 SIVAL(pdata,8,len);
3050 data_len = 12 + len;
3051 break;
3053 case SMB_QUERY_FS_LABEL_INFO:
3054 case SMB_FS_LABEL_INFORMATION:
3055 len = srvstr_push(pdata, flags2, pdata+4, vname,
3056 PTR_DIFF(end_data, pdata+4), 0);
3057 data_len = 4 + len;
3058 SIVAL(pdata,0,len);
3059 break;
3061 case SMB_QUERY_FS_VOLUME_INFO:
3062 case SMB_FS_VOLUME_INFORMATION:
3065 * Add volume serial number - hash of a combination of
3066 * the called hostname and the service name.
3068 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3069 (str_checksum(get_local_machine_name())<<16));
3071 /* Max label len is 32 characters. */
3072 len = srvstr_push(pdata, flags2, pdata+18, vname,
3073 PTR_DIFF(end_data, pdata+18),
3074 STR_UNICODE);
3075 SIVAL(pdata,12,len);
3076 data_len = 18+len;
3078 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3079 (int)strlen(vname),vname, lp_servicename(snum)));
3080 break;
3082 case SMB_QUERY_FS_SIZE_INFO:
3083 case SMB_FS_SIZE_INFORMATION:
3085 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3086 data_len = 24;
3087 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3088 return map_nt_error_from_unix(errno);
3090 block_size = lp_block_size(snum);
3091 if (bsize < block_size) {
3092 uint64_t factor = block_size/bsize;
3093 bsize = block_size;
3094 dsize /= factor;
3095 dfree /= factor;
3097 if (bsize > block_size) {
3098 uint64_t factor = bsize/block_size;
3099 bsize = block_size;
3100 dsize *= factor;
3101 dfree *= factor;
3103 bytes_per_sector = 512;
3104 sectors_per_unit = bsize/bytes_per_sector;
3105 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3106 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3107 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3108 SBIG_UINT(pdata,0,dsize);
3109 SBIG_UINT(pdata,8,dfree);
3110 SIVAL(pdata,16,sectors_per_unit);
3111 SIVAL(pdata,20,bytes_per_sector);
3112 break;
3115 case SMB_FS_FULL_SIZE_INFORMATION:
3117 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3118 data_len = 32;
3119 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3120 return map_nt_error_from_unix(errno);
3122 block_size = lp_block_size(snum);
3123 if (bsize < block_size) {
3124 uint64_t factor = block_size/bsize;
3125 bsize = block_size;
3126 dsize /= factor;
3127 dfree /= factor;
3129 if (bsize > block_size) {
3130 uint64_t factor = bsize/block_size;
3131 bsize = block_size;
3132 dsize *= factor;
3133 dfree *= factor;
3135 bytes_per_sector = 512;
3136 sectors_per_unit = bsize/bytes_per_sector;
3137 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3138 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3139 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3140 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3141 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3142 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3143 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3144 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3145 break;
3148 case SMB_QUERY_FS_DEVICE_INFO:
3149 case SMB_FS_DEVICE_INFORMATION:
3151 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3153 if (!CAN_WRITE(conn)) {
3154 characteristics |= FILE_READ_ONLY_DEVICE;
3156 data_len = 8;
3157 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3158 SIVAL(pdata,4,characteristics);
3159 break;
3162 #ifdef HAVE_SYS_QUOTAS
3163 case SMB_FS_QUOTA_INFORMATION:
3165 * what we have to send --metze:
3167 * Unknown1: 24 NULL bytes
3168 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3169 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3170 * Quota Flags: 2 byte :
3171 * Unknown3: 6 NULL bytes
3173 * 48 bytes total
3175 * details for Quota Flags:
3177 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3178 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3179 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3180 * 0x0001 Enable Quotas: enable quota for this fs
3184 /* we need to fake up a fsp here,
3185 * because its not send in this call
3187 files_struct fsp;
3188 SMB_NTQUOTA_STRUCT quotas;
3190 ZERO_STRUCT(fsp);
3191 ZERO_STRUCT(quotas);
3193 fsp.conn = conn;
3194 fsp.fnum = -1;
3196 /* access check */
3197 if (conn->server_info->utok.uid != sec_initial_uid()) {
3198 DEBUG(0,("set_user_quota: access_denied "
3199 "service [%s] user [%s]\n",
3200 lp_servicename(SNUM(conn)),
3201 conn->server_info->unix_name));
3202 return NT_STATUS_ACCESS_DENIED;
3205 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3206 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3207 return map_nt_error_from_unix(errno);
3210 data_len = 48;
3212 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3213 lp_servicename(SNUM(conn))));
3215 /* Unknown1 24 NULL bytes*/
3216 SBIG_UINT(pdata,0,(uint64_t)0);
3217 SBIG_UINT(pdata,8,(uint64_t)0);
3218 SBIG_UINT(pdata,16,(uint64_t)0);
3220 /* Default Soft Quota 8 bytes */
3221 SBIG_UINT(pdata,24,quotas.softlim);
3223 /* Default Hard Quota 8 bytes */
3224 SBIG_UINT(pdata,32,quotas.hardlim);
3226 /* Quota flag 2 bytes */
3227 SSVAL(pdata,40,quotas.qflags);
3229 /* Unknown3 6 NULL bytes */
3230 SSVAL(pdata,42,0);
3231 SIVAL(pdata,44,0);
3233 break;
3235 #endif /* HAVE_SYS_QUOTAS */
3236 case SMB_FS_OBJECTID_INFORMATION:
3238 unsigned char objid[16];
3239 struct smb_extended_info extended_info;
3240 memcpy(pdata,create_volume_objectid(conn, objid),16);
3241 samba_extended_info_version (&extended_info);
3242 SIVAL(pdata,16,extended_info.samba_magic);
3243 SIVAL(pdata,20,extended_info.samba_version);
3244 SIVAL(pdata,24,extended_info.samba_subversion);
3245 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3246 memcpy(pdata+36,extended_info.samba_version_string,28);
3247 data_len = 64;
3248 break;
3252 * Query the version and capabilities of the CIFS UNIX extensions
3253 * in use.
3256 case SMB_QUERY_CIFS_UNIX_INFO:
3258 bool large_write = lp_min_receive_file_size() &&
3259 !srv_is_signing_active(conn->sconn);
3260 bool large_read = !srv_is_signing_active(conn->sconn);
3261 int encrypt_caps = 0;
3263 if (!lp_unix_extensions()) {
3264 return NT_STATUS_INVALID_LEVEL;
3267 switch (conn->encrypt_level) {
3268 case 0:
3269 encrypt_caps = 0;
3270 break;
3271 case 1:
3272 case Auto:
3273 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3274 break;
3275 case Required:
3276 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3277 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3278 large_write = false;
3279 large_read = false;
3280 break;
3283 data_len = 12;
3284 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3285 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3287 /* We have POSIX ACLs, pathname, encryption,
3288 * large read/write, and locking capability. */
3290 SBIG_UINT(pdata,4,((uint64_t)(
3291 CIFS_UNIX_POSIX_ACLS_CAP|
3292 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3293 CIFS_UNIX_FCNTL_LOCKS_CAP|
3294 CIFS_UNIX_EXTATTR_CAP|
3295 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3296 encrypt_caps|
3297 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3298 (large_write ?
3299 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3300 break;
3303 case SMB_QUERY_POSIX_FS_INFO:
3305 int rc;
3306 vfs_statvfs_struct svfs;
3308 if (!lp_unix_extensions()) {
3309 return NT_STATUS_INVALID_LEVEL;
3312 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3314 if (!rc) {
3315 data_len = 56;
3316 SIVAL(pdata,0,svfs.OptimalTransferSize);
3317 SIVAL(pdata,4,svfs.BlockSize);
3318 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3319 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3320 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3321 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3322 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3323 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3324 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3325 #ifdef EOPNOTSUPP
3326 } else if (rc == EOPNOTSUPP) {
3327 return NT_STATUS_INVALID_LEVEL;
3328 #endif /* EOPNOTSUPP */
3329 } else {
3330 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3331 return NT_STATUS_DOS(ERRSRV, ERRerror);
3333 break;
3336 case SMB_QUERY_POSIX_WHOAMI:
3338 uint32_t flags = 0;
3339 uint32_t sid_bytes;
3340 int i;
3342 if (!lp_unix_extensions()) {
3343 return NT_STATUS_INVALID_LEVEL;
3346 if (max_data_bytes < 40) {
3347 return NT_STATUS_BUFFER_TOO_SMALL;
3350 /* We ARE guest if global_sid_Builtin_Guests is
3351 * in our list of SIDs.
3353 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3354 conn->server_info->ptok)) {
3355 flags |= SMB_WHOAMI_GUEST;
3358 /* We are NOT guest if global_sid_Authenticated_Users
3359 * is in our list of SIDs.
3361 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3362 conn->server_info->ptok)) {
3363 flags &= ~SMB_WHOAMI_GUEST;
3366 /* NOTE: 8 bytes for UID/GID, irrespective of native
3367 * platform size. This matches
3368 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3370 data_len = 4 /* flags */
3371 + 4 /* flag mask */
3372 + 8 /* uid */
3373 + 8 /* gid */
3374 + 4 /* ngroups */
3375 + 4 /* num_sids */
3376 + 4 /* SID bytes */
3377 + 4 /* pad/reserved */
3378 + (conn->server_info->utok.ngroups * 8)
3379 /* groups list */
3380 + (conn->server_info->ptok->num_sids *
3381 SID_MAX_SIZE)
3382 /* SID list */;
3384 SIVAL(pdata, 0, flags);
3385 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3386 SBIG_UINT(pdata, 8,
3387 (uint64_t)conn->server_info->utok.uid);
3388 SBIG_UINT(pdata, 16,
3389 (uint64_t)conn->server_info->utok.gid);
3392 if (data_len >= max_data_bytes) {
3393 /* Potential overflow, skip the GIDs and SIDs. */
3395 SIVAL(pdata, 24, 0); /* num_groups */
3396 SIVAL(pdata, 28, 0); /* num_sids */
3397 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3398 SIVAL(pdata, 36, 0); /* reserved */
3400 data_len = 40;
3401 break;
3404 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3405 SIVAL(pdata, 28, conn->server_info->ptok->num_sids);
3407 /* We walk the SID list twice, but this call is fairly
3408 * infrequent, and I don't expect that it's performance
3409 * sensitive -- jpeach
3411 for (i = 0, sid_bytes = 0;
3412 i < conn->server_info->ptok->num_sids; ++i) {
3413 sid_bytes += ndr_size_dom_sid(
3414 &conn->server_info->ptok->sids[i],
3418 /* SID list byte count */
3419 SIVAL(pdata, 32, sid_bytes);
3421 /* 4 bytes pad/reserved - must be zero */
3422 SIVAL(pdata, 36, 0);
3423 data_len = 40;
3425 /* GID list */
3426 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3427 SBIG_UINT(pdata, data_len,
3428 (uint64_t)conn->server_info->utok.groups[i]);
3429 data_len += 8;
3432 /* SID list */
3433 for (i = 0;
3434 i < conn->server_info->ptok->num_sids; ++i) {
3435 int sid_len = ndr_size_dom_sid(
3436 &conn->server_info->ptok->sids[i],
3439 sid_linearize(pdata + data_len, sid_len,
3440 &conn->server_info->ptok->sids[i]);
3441 data_len += sid_len;
3444 break;
3447 case SMB_MAC_QUERY_FS_INFO:
3449 * Thursby MAC extension... ONLY on NTFS filesystems
3450 * once we do streams then we don't need this
3452 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3453 data_len = 88;
3454 SIVAL(pdata,84,0x100); /* Don't support mac... */
3455 break;
3457 /* drop through */
3458 default:
3459 return NT_STATUS_INVALID_LEVEL;
3462 *ret_data_len = data_len;
3463 return NT_STATUS_OK;
3466 /****************************************************************************
3467 Reply to a TRANS2_QFSINFO (query filesystem info).
3468 ****************************************************************************/
3470 static void call_trans2qfsinfo(connection_struct *conn,
3471 struct smb_request *req,
3472 char **pparams, int total_params,
3473 char **ppdata, int total_data,
3474 unsigned int max_data_bytes)
3476 char *params = *pparams;
3477 uint16_t info_level;
3478 int data_len = 0;
3479 NTSTATUS status;
3481 if (total_params < 2) {
3482 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3483 return;
3486 info_level = SVAL(params,0);
3488 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3489 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3490 DEBUG(0,("call_trans2qfsinfo: encryption required "
3491 "and info level 0x%x sent.\n",
3492 (unsigned int)info_level));
3493 exit_server_cleanly("encryption required "
3494 "on connection");
3495 return;
3499 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3501 status = smbd_do_qfsinfo(conn, req,
3502 info_level,
3503 req->flags2,
3504 max_data_bytes,
3505 ppdata, &data_len);
3506 if (!NT_STATUS_IS_OK(status)) {
3507 reply_nterror(req, status);
3508 return;
3511 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3512 max_data_bytes);
3514 DEBUG( 4, ( "%s info_level = %d\n",
3515 smb_fn_name(req->cmd), info_level) );
3517 return;
3520 /****************************************************************************
3521 Reply to a TRANS2_SETFSINFO (set filesystem info).
3522 ****************************************************************************/
3524 static void call_trans2setfsinfo(connection_struct *conn,
3525 struct smb_request *req,
3526 char **pparams, int total_params,
3527 char **ppdata, int total_data,
3528 unsigned int max_data_bytes)
3530 char *pdata = *ppdata;
3531 char *params = *pparams;
3532 uint16 info_level;
3534 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3536 /* */
3537 if (total_params < 4) {
3538 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3539 total_params));
3540 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3541 return;
3544 info_level = SVAL(params,2);
3546 if (IS_IPC(conn)) {
3547 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3548 info_level != SMB_SET_CIFS_UNIX_INFO) {
3549 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3550 "info level (0x%x) on IPC$.\n",
3551 (unsigned int)info_level));
3552 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3553 return;
3557 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3558 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3559 DEBUG(0,("call_trans2setfsinfo: encryption required "
3560 "and info level 0x%x sent.\n",
3561 (unsigned int)info_level));
3562 exit_server_cleanly("encryption required "
3563 "on connection");
3564 return;
3568 switch(info_level) {
3569 case SMB_SET_CIFS_UNIX_INFO:
3571 uint16 client_unix_major;
3572 uint16 client_unix_minor;
3573 uint32 client_unix_cap_low;
3574 uint32 client_unix_cap_high;
3576 if (!lp_unix_extensions()) {
3577 reply_nterror(req,
3578 NT_STATUS_INVALID_LEVEL);
3579 return;
3582 /* There should be 12 bytes of capabilities set. */
3583 if (total_data < 8) {
3584 reply_nterror(
3585 req,
3586 NT_STATUS_INVALID_PARAMETER);
3587 return;
3589 client_unix_major = SVAL(pdata,0);
3590 client_unix_minor = SVAL(pdata,2);
3591 client_unix_cap_low = IVAL(pdata,4);
3592 client_unix_cap_high = IVAL(pdata,8);
3593 /* Just print these values for now. */
3594 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3595 cap_low = 0x%x, cap_high = 0x%x\n",
3596 (unsigned int)client_unix_major,
3597 (unsigned int)client_unix_minor,
3598 (unsigned int)client_unix_cap_low,
3599 (unsigned int)client_unix_cap_high ));
3601 /* Here is where we must switch to posix pathname processing... */
3602 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3603 lp_set_posix_pathnames();
3604 mangle_change_to_posix();
3607 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3608 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3609 /* Client that knows how to do posix locks,
3610 * but not posix open/mkdir operations. Set a
3611 * default type for read/write checks. */
3613 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3616 break;
3619 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3621 NTSTATUS status;
3622 size_t param_len = 0;
3623 size_t data_len = total_data;
3625 if (!lp_unix_extensions()) {
3626 reply_nterror(
3627 req,
3628 NT_STATUS_INVALID_LEVEL);
3629 return;
3632 if (lp_smb_encrypt(SNUM(conn)) == false) {
3633 reply_nterror(
3634 req,
3635 NT_STATUS_NOT_SUPPORTED);
3636 return;
3639 if (req->sconn->smb1.echo_handler.trusted_fde) {
3640 DEBUG( 2,("call_trans2setfsinfo: "
3641 "request transport encryption disabled"
3642 "with 'fork echo handler = yes'\n"));
3643 reply_nterror(
3644 req,
3645 NT_STATUS_NOT_SUPPORTED);
3646 return;
3649 DEBUG( 4,("call_trans2setfsinfo: "
3650 "request transport encryption.\n"));
3652 status = srv_request_encryption_setup(conn,
3653 (unsigned char **)ppdata,
3654 &data_len,
3655 (unsigned char **)pparams,
3656 &param_len);
3658 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3659 !NT_STATUS_IS_OK(status)) {
3660 reply_nterror(req, status);
3661 return;
3664 send_trans2_replies(conn, req,
3665 *pparams,
3666 param_len,
3667 *ppdata,
3668 data_len,
3669 max_data_bytes);
3671 if (NT_STATUS_IS_OK(status)) {
3672 /* Server-side transport
3673 * encryption is now *on*. */
3674 status = srv_encryption_start(conn);
3675 if (!NT_STATUS_IS_OK(status)) {
3676 exit_server_cleanly(
3677 "Failure in setting "
3678 "up encrypted transport");
3681 return;
3684 case SMB_FS_QUOTA_INFORMATION:
3686 files_struct *fsp = NULL;
3687 SMB_NTQUOTA_STRUCT quotas;
3689 ZERO_STRUCT(quotas);
3691 /* access check */
3692 if ((conn->server_info->utok.uid != sec_initial_uid())
3693 ||!CAN_WRITE(conn)) {
3694 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3695 lp_servicename(SNUM(conn)),
3696 conn->server_info->unix_name));
3697 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3698 return;
3701 /* note: normaly there're 48 bytes,
3702 * but we didn't use the last 6 bytes for now
3703 * --metze
3705 fsp = file_fsp(req, SVAL(params,0));
3707 if (!check_fsp_ntquota_handle(conn, req,
3708 fsp)) {
3709 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3710 reply_nterror(
3711 req, NT_STATUS_INVALID_HANDLE);
3712 return;
3715 if (total_data < 42) {
3716 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3717 total_data));
3718 reply_nterror(
3719 req,
3720 NT_STATUS_INVALID_PARAMETER);
3721 return;
3724 /* unknown_1 24 NULL bytes in pdata*/
3726 /* the soft quotas 8 bytes (uint64_t)*/
3727 quotas.softlim = (uint64_t)IVAL(pdata,24);
3728 #ifdef LARGE_SMB_OFF_T
3729 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3730 #else /* LARGE_SMB_OFF_T */
3731 if ((IVAL(pdata,28) != 0)&&
3732 ((quotas.softlim != 0xFFFFFFFF)||
3733 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3734 /* more than 32 bits? */
3735 reply_nterror(
3736 req,
3737 NT_STATUS_INVALID_PARAMETER);
3738 return;
3740 #endif /* LARGE_SMB_OFF_T */
3742 /* the hard quotas 8 bytes (uint64_t)*/
3743 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3744 #ifdef LARGE_SMB_OFF_T
3745 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3746 #else /* LARGE_SMB_OFF_T */
3747 if ((IVAL(pdata,36) != 0)&&
3748 ((quotas.hardlim != 0xFFFFFFFF)||
3749 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3750 /* more than 32 bits? */
3751 reply_nterror(
3752 req,
3753 NT_STATUS_INVALID_PARAMETER);
3754 return;
3756 #endif /* LARGE_SMB_OFF_T */
3758 /* quota_flags 2 bytes **/
3759 quotas.qflags = SVAL(pdata,40);
3761 /* unknown_2 6 NULL bytes follow*/
3763 /* now set the quotas */
3764 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3765 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3766 reply_nterror(req, map_nt_error_from_unix(errno));
3767 return;
3770 break;
3772 default:
3773 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3774 info_level));
3775 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3776 return;
3777 break;
3781 * sending this reply works fine,
3782 * but I'm not sure it's the same
3783 * like windows do...
3784 * --metze
3786 reply_outbuf(req, 10, 0);
3789 #if defined(HAVE_POSIX_ACLS)
3790 /****************************************************************************
3791 Utility function to count the number of entries in a POSIX acl.
3792 ****************************************************************************/
3794 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3796 unsigned int ace_count = 0;
3797 int entry_id = SMB_ACL_FIRST_ENTRY;
3798 SMB_ACL_ENTRY_T entry;
3800 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3801 /* get_next... */
3802 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3803 entry_id = SMB_ACL_NEXT_ENTRY;
3805 ace_count++;
3807 return ace_count;
3810 /****************************************************************************
3811 Utility function to marshall a POSIX acl into wire format.
3812 ****************************************************************************/
3814 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3816 int entry_id = SMB_ACL_FIRST_ENTRY;
3817 SMB_ACL_ENTRY_T entry;
3819 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3820 SMB_ACL_TAG_T tagtype;
3821 SMB_ACL_PERMSET_T permset;
3822 unsigned char perms = 0;
3823 unsigned int own_grp;
3825 /* get_next... */
3826 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3827 entry_id = SMB_ACL_NEXT_ENTRY;
3830 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3831 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3832 return False;
3835 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3836 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3837 return False;
3840 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3841 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3842 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3844 SCVAL(pdata,1,perms);
3846 switch (tagtype) {
3847 case SMB_ACL_USER_OBJ:
3848 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3849 own_grp = (unsigned int)pst->st_ex_uid;
3850 SIVAL(pdata,2,own_grp);
3851 SIVAL(pdata,6,0);
3852 break;
3853 case SMB_ACL_USER:
3855 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3856 if (!puid) {
3857 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3858 return False;
3860 own_grp = (unsigned int)*puid;
3861 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3862 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3863 SIVAL(pdata,2,own_grp);
3864 SIVAL(pdata,6,0);
3865 break;
3867 case SMB_ACL_GROUP_OBJ:
3868 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3869 own_grp = (unsigned int)pst->st_ex_gid;
3870 SIVAL(pdata,2,own_grp);
3871 SIVAL(pdata,6,0);
3872 break;
3873 case SMB_ACL_GROUP:
3875 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3876 if (!pgid) {
3877 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3878 return False;
3880 own_grp = (unsigned int)*pgid;
3881 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3882 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3883 SIVAL(pdata,2,own_grp);
3884 SIVAL(pdata,6,0);
3885 break;
3887 case SMB_ACL_MASK:
3888 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3889 SIVAL(pdata,2,0xFFFFFFFF);
3890 SIVAL(pdata,6,0xFFFFFFFF);
3891 break;
3892 case SMB_ACL_OTHER:
3893 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3894 SIVAL(pdata,2,0xFFFFFFFF);
3895 SIVAL(pdata,6,0xFFFFFFFF);
3896 break;
3897 default:
3898 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3899 return False;
3901 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3904 return True;
3906 #endif
3908 /****************************************************************************
3909 Store the FILE_UNIX_BASIC info.
3910 ****************************************************************************/
3912 static char *store_file_unix_basic(connection_struct *conn,
3913 char *pdata,
3914 files_struct *fsp,
3915 const SMB_STRUCT_STAT *psbuf)
3917 uint64_t file_index = get_FileIndex(conn, psbuf);
3919 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3920 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3922 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3923 pdata += 8;
3925 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3926 pdata += 8;
3928 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3929 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3930 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3931 pdata += 24;
3933 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3934 SIVAL(pdata,4,0);
3935 pdata += 8;
3937 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3938 SIVAL(pdata,4,0);
3939 pdata += 8;
3941 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3942 pdata += 4;
3944 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3945 SIVAL(pdata,4,0);
3946 pdata += 8;
3948 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3949 SIVAL(pdata,4,0);
3950 pdata += 8;
3952 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3953 pdata += 8;
3955 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3956 SIVAL(pdata,4,0);
3957 pdata += 8;
3959 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3960 SIVAL(pdata,4,0);
3961 pdata += 8;
3963 return pdata;
3966 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3967 * the chflags(2) (or equivalent) flags.
3969 * XXX: this really should be behind the VFS interface. To do this, we would
3970 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3971 * Each VFS module could then implement its own mapping as appropriate for the
3972 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3974 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3975 info2_flags_map[] =
3977 #ifdef UF_NODUMP
3978 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3979 #endif
3981 #ifdef UF_IMMUTABLE
3982 { UF_IMMUTABLE, EXT_IMMUTABLE },
3983 #endif
3985 #ifdef UF_APPEND
3986 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3987 #endif
3989 #ifdef UF_HIDDEN
3990 { UF_HIDDEN, EXT_HIDDEN },
3991 #endif
3993 /* Do not remove. We need to guarantee that this array has at least one
3994 * entry to build on HP-UX.
3996 { 0, 0 }
4000 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4001 uint32 *smb_fflags, uint32 *smb_fmask)
4003 int i;
4005 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4006 *smb_fmask |= info2_flags_map[i].smb_fflag;
4007 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4008 *smb_fflags |= info2_flags_map[i].smb_fflag;
4013 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4014 const uint32 smb_fflags,
4015 const uint32 smb_fmask,
4016 int *stat_fflags)
4018 uint32 max_fmask = 0;
4019 int i;
4021 *stat_fflags = psbuf->st_ex_flags;
4023 /* For each flags requested in smb_fmask, check the state of the
4024 * corresponding flag in smb_fflags and set or clear the matching
4025 * stat flag.
4028 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4029 max_fmask |= info2_flags_map[i].smb_fflag;
4030 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4031 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4032 *stat_fflags |= info2_flags_map[i].stat_fflag;
4033 } else {
4034 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4039 /* If smb_fmask is asking to set any bits that are not supported by
4040 * our flag mappings, we should fail.
4042 if ((smb_fmask & max_fmask) != smb_fmask) {
4043 return False;
4046 return True;
4050 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4051 * of file flags and birth (create) time.
4053 static char *store_file_unix_basic_info2(connection_struct *conn,
4054 char *pdata,
4055 files_struct *fsp,
4056 const SMB_STRUCT_STAT *psbuf)
4058 uint32 file_flags = 0;
4059 uint32 flags_mask = 0;
4061 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4063 /* Create (birth) time 64 bit */
4064 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4065 pdata += 8;
4067 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4068 SIVAL(pdata, 0, file_flags); /* flags */
4069 SIVAL(pdata, 4, flags_mask); /* mask */
4070 pdata += 8;
4072 return pdata;
4075 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4076 const struct stream_struct *streams,
4077 char *data,
4078 unsigned int max_data_bytes,
4079 unsigned int *data_size)
4081 unsigned int i;
4082 unsigned int ofs = 0;
4084 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4085 unsigned int next_offset;
4086 size_t namelen;
4087 smb_ucs2_t *namebuf;
4089 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4090 streams[i].name, &namelen) ||
4091 namelen <= 2)
4093 return NT_STATUS_INVALID_PARAMETER;
4097 * name_buf is now null-terminated, we need to marshall as not
4098 * terminated
4101 namelen -= 2;
4103 SIVAL(data, ofs+4, namelen);
4104 SOFF_T(data, ofs+8, streams[i].size);
4105 SOFF_T(data, ofs+16, streams[i].alloc_size);
4106 memcpy(data+ofs+24, namebuf, namelen);
4107 TALLOC_FREE(namebuf);
4109 next_offset = ofs + 24 + namelen;
4111 if (i == num_streams-1) {
4112 SIVAL(data, ofs, 0);
4114 else {
4115 unsigned int align = ndr_align_size(next_offset, 8);
4117 memset(data+next_offset, 0, align);
4118 next_offset += align;
4120 SIVAL(data, ofs, next_offset - ofs);
4121 ofs = next_offset;
4124 ofs = next_offset;
4127 *data_size = ofs;
4129 return NT_STATUS_OK;
4132 /****************************************************************************
4133 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4134 ****************************************************************************/
4136 static void call_trans2qpipeinfo(connection_struct *conn,
4137 struct smb_request *req,
4138 unsigned int tran_call,
4139 char **pparams, int total_params,
4140 char **ppdata, int total_data,
4141 unsigned int max_data_bytes)
4143 char *params = *pparams;
4144 char *pdata = *ppdata;
4145 unsigned int data_size = 0;
4146 unsigned int param_size = 2;
4147 uint16 info_level;
4148 files_struct *fsp;
4150 if (!params) {
4151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4152 return;
4155 if (total_params < 4) {
4156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4157 return;
4160 fsp = file_fsp(req, SVAL(params,0));
4161 if (!fsp_is_np(fsp)) {
4162 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4163 return;
4166 info_level = SVAL(params,2);
4168 *pparams = (char *)SMB_REALLOC(*pparams,2);
4169 if (*pparams == NULL) {
4170 reply_nterror(req, NT_STATUS_NO_MEMORY);
4171 return;
4173 params = *pparams;
4174 SSVAL(params,0,0);
4175 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4176 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4177 if (*ppdata == NULL ) {
4178 reply_nterror(req, NT_STATUS_NO_MEMORY);
4179 return;
4181 pdata = *ppdata;
4183 switch (info_level) {
4184 case SMB_FILE_STANDARD_INFORMATION:
4185 memset(pdata,0,24);
4186 SOFF_T(pdata,0,4096LL);
4187 SIVAL(pdata,16,1);
4188 SIVAL(pdata,20,1);
4189 data_size = 24;
4190 break;
4192 default:
4193 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4194 return;
4197 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4198 max_data_bytes);
4200 return;
4203 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4204 TALLOC_CTX *mem_ctx,
4205 uint16_t info_level,
4206 files_struct *fsp,
4207 struct smb_filename *smb_fname,
4208 bool delete_pending,
4209 struct timespec write_time_ts,
4210 struct ea_list *ea_list,
4211 int lock_data_count,
4212 char *lock_data,
4213 uint16_t flags2,
4214 unsigned int max_data_bytes,
4215 char **ppdata,
4216 unsigned int *pdata_size)
4218 char *pdata = *ppdata;
4219 char *dstart, *dend;
4220 unsigned int data_size;
4221 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4222 time_t create_time, mtime, atime, c_time;
4223 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4224 char *p;
4225 char *base_name;
4226 char *dos_fname;
4227 int mode;
4228 int nlink;
4229 NTSTATUS status;
4230 uint64_t file_size = 0;
4231 uint64_t pos = 0;
4232 uint64_t allocation_size = 0;
4233 uint64_t file_index = 0;
4234 uint32_t access_mask = 0;
4236 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4237 return NT_STATUS_INVALID_LEVEL;
4240 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4241 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4242 info_level, max_data_bytes));
4244 mode = dos_mode(conn, smb_fname);
4245 nlink = psbuf->st_ex_nlink;
4247 if (nlink && (mode&aDIR)) {
4248 nlink = 1;
4251 if ((nlink > 0) && delete_pending) {
4252 nlink -= 1;
4255 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4256 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4257 if (*ppdata == NULL) {
4258 return NT_STATUS_NO_MEMORY;
4260 pdata = *ppdata;
4261 dstart = pdata;
4262 dend = dstart + data_size - 1;
4264 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4265 update_stat_ex_mtime(psbuf, write_time_ts);
4268 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4269 mtime_ts = psbuf->st_ex_mtime;
4270 atime_ts = psbuf->st_ex_atime;
4271 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4273 if (lp_dos_filetime_resolution(SNUM(conn))) {
4274 dos_filetime_timespec(&create_time_ts);
4275 dos_filetime_timespec(&mtime_ts);
4276 dos_filetime_timespec(&atime_ts);
4277 dos_filetime_timespec(&ctime_ts);
4280 create_time = convert_timespec_to_time_t(create_time_ts);
4281 mtime = convert_timespec_to_time_t(mtime_ts);
4282 atime = convert_timespec_to_time_t(atime_ts);
4283 c_time = convert_timespec_to_time_t(ctime_ts);
4285 p = strrchr_m(smb_fname->base_name,'/');
4286 if (!p)
4287 base_name = smb_fname->base_name;
4288 else
4289 base_name = p+1;
4291 /* NT expects the name to be in an exact form of the *full*
4292 filename. See the trans2 torture test */
4293 if (ISDOT(base_name)) {
4294 dos_fname = talloc_strdup(mem_ctx, "\\");
4295 if (!dos_fname) {
4296 return NT_STATUS_NO_MEMORY;
4298 } else {
4299 dos_fname = talloc_asprintf(mem_ctx,
4300 "\\%s",
4301 smb_fname->base_name);
4302 if (!dos_fname) {
4303 return NT_STATUS_NO_MEMORY;
4305 if (is_ntfs_stream_smb_fname(smb_fname)) {
4306 dos_fname = talloc_asprintf(dos_fname, "%s",
4307 smb_fname->stream_name);
4308 if (!dos_fname) {
4309 return NT_STATUS_NO_MEMORY;
4313 string_replace(dos_fname, '/', '\\');
4316 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4318 if (!fsp) {
4319 /* Do we have this path open ? */
4320 files_struct *fsp1;
4321 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4322 fsp1 = file_find_di_first(conn->sconn, fileid);
4323 if (fsp1 && fsp1->initial_allocation_size) {
4324 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4328 if (!(mode & aDIR)) {
4329 file_size = get_file_size_stat(psbuf);
4332 if (fsp) {
4333 pos = fsp->fh->position_information;
4336 if (fsp) {
4337 access_mask = fsp->access_mask;
4338 } else {
4339 /* GENERIC_EXECUTE mapping from Windows */
4340 access_mask = 0x12019F;
4343 /* This should be an index number - looks like
4344 dev/ino to me :-)
4346 I think this causes us to fail the IFSKIT
4347 BasicFileInformationTest. -tpot */
4348 file_index = get_FileIndex(conn, psbuf);
4350 switch (info_level) {
4351 case SMB_INFO_STANDARD:
4352 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4353 data_size = 22;
4354 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4355 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4356 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4357 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4358 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4359 SSVAL(pdata,l1_attrFile,mode);
4360 break;
4362 case SMB_INFO_QUERY_EA_SIZE:
4364 unsigned int ea_size =
4365 estimate_ea_size(conn, fsp,
4366 smb_fname->base_name);
4367 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4368 data_size = 26;
4369 srv_put_dos_date2(pdata,0,create_time);
4370 srv_put_dos_date2(pdata,4,atime);
4371 srv_put_dos_date2(pdata,8,mtime); /* write time */
4372 SIVAL(pdata,12,(uint32)file_size);
4373 SIVAL(pdata,16,(uint32)allocation_size);
4374 SSVAL(pdata,20,mode);
4375 SIVAL(pdata,22,ea_size);
4376 break;
4379 case SMB_INFO_IS_NAME_VALID:
4380 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4381 if (fsp) {
4382 /* os/2 needs this ? really ?*/
4383 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4385 /* This is only reached for qpathinfo */
4386 data_size = 0;
4387 break;
4389 case SMB_INFO_QUERY_EAS_FROM_LIST:
4391 size_t total_ea_len = 0;
4392 struct ea_list *ea_file_list = NULL;
4394 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4396 ea_file_list =
4397 get_ea_list_from_file(mem_ctx, conn, fsp,
4398 smb_fname->base_name,
4399 &total_ea_len);
4400 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4402 if (!ea_list || (total_ea_len > data_size)) {
4403 data_size = 4;
4404 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4405 break;
4408 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4409 break;
4412 case SMB_INFO_QUERY_ALL_EAS:
4414 /* We have data_size bytes to put EA's into. */
4415 size_t total_ea_len = 0;
4417 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4419 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4420 smb_fname->base_name,
4421 &total_ea_len);
4422 if (!ea_list || (total_ea_len > data_size)) {
4423 data_size = 4;
4424 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4425 break;
4428 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4429 break;
4432 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4434 /* This is FileFullEaInformation - 0xF which maps to
4435 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4437 /* We have data_size bytes to put EA's into. */
4438 size_t total_ea_len = 0;
4439 struct ea_list *ea_file_list = NULL;
4441 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4443 /*TODO: add filtering and index handling */
4445 ea_file_list =
4446 get_ea_list_from_file(mem_ctx, conn, fsp,
4447 smb_fname->base_name,
4448 &total_ea_len);
4449 if (!ea_file_list) {
4450 return NT_STATUS_NO_EAS_ON_FILE;
4453 status = fill_ea_chained_buffer(mem_ctx,
4454 pdata,
4455 data_size,
4456 &data_size,
4457 conn, ea_file_list);
4458 if (!NT_STATUS_IS_OK(status)) {
4459 return status;
4461 break;
4464 case SMB_FILE_BASIC_INFORMATION:
4465 case SMB_QUERY_FILE_BASIC_INFO:
4467 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4468 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4469 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4470 } else {
4471 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4472 data_size = 40;
4473 SIVAL(pdata,36,0);
4475 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4476 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4477 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4478 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4479 SIVAL(pdata,32,mode);
4481 DEBUG(5,("SMB_QFBI - "));
4482 DEBUG(5,("create: %s ", ctime(&create_time)));
4483 DEBUG(5,("access: %s ", ctime(&atime)));
4484 DEBUG(5,("write: %s ", ctime(&mtime)));
4485 DEBUG(5,("change: %s ", ctime(&c_time)));
4486 DEBUG(5,("mode: %x\n", mode));
4487 break;
4489 case SMB_FILE_STANDARD_INFORMATION:
4490 case SMB_QUERY_FILE_STANDARD_INFO:
4492 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4493 data_size = 24;
4494 SOFF_T(pdata,0,allocation_size);
4495 SOFF_T(pdata,8,file_size);
4496 SIVAL(pdata,16,nlink);
4497 SCVAL(pdata,20,delete_pending?1:0);
4498 SCVAL(pdata,21,(mode&aDIR)?1:0);
4499 SSVAL(pdata,22,0); /* Padding. */
4500 break;
4502 case SMB_FILE_EA_INFORMATION:
4503 case SMB_QUERY_FILE_EA_INFO:
4505 unsigned int ea_size =
4506 estimate_ea_size(conn, fsp, smb_fname->base_name);
4507 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4508 data_size = 4;
4509 SIVAL(pdata,0,ea_size);
4510 break;
4513 /* Get the 8.3 name - used if NT SMB was negotiated. */
4514 case SMB_QUERY_FILE_ALT_NAME_INFO:
4515 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4517 int len;
4518 char mangled_name[13];
4519 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4520 if (!name_to_8_3(base_name,mangled_name,
4521 True,conn->params)) {
4522 return NT_STATUS_NO_MEMORY;
4524 len = srvstr_push(dstart, flags2,
4525 pdata+4, mangled_name,
4526 PTR_DIFF(dend, pdata+4),
4527 STR_UNICODE);
4528 data_size = 4 + len;
4529 SIVAL(pdata,0,len);
4530 break;
4533 case SMB_QUERY_FILE_NAME_INFO:
4535 int len;
4537 this must be *exactly* right for ACLs on mapped drives to work
4539 len = srvstr_push(dstart, flags2,
4540 pdata+4, dos_fname,
4541 PTR_DIFF(dend, pdata+4),
4542 STR_UNICODE);
4543 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4544 data_size = 4 + len;
4545 SIVAL(pdata,0,len);
4546 break;
4549 case SMB_FILE_ALLOCATION_INFORMATION:
4550 case SMB_QUERY_FILE_ALLOCATION_INFO:
4551 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4552 data_size = 8;
4553 SOFF_T(pdata,0,allocation_size);
4554 break;
4556 case SMB_FILE_END_OF_FILE_INFORMATION:
4557 case SMB_QUERY_FILE_END_OF_FILEINFO:
4558 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4559 data_size = 8;
4560 SOFF_T(pdata,0,file_size);
4561 break;
4563 case SMB_QUERY_FILE_ALL_INFO:
4564 case SMB_FILE_ALL_INFORMATION:
4566 int len;
4567 unsigned int ea_size =
4568 estimate_ea_size(conn, fsp, smb_fname->base_name);
4569 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4570 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4571 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4572 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4573 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4574 SIVAL(pdata,32,mode);
4575 SIVAL(pdata,36,0); /* padding. */
4576 pdata += 40;
4577 SOFF_T(pdata,0,allocation_size);
4578 SOFF_T(pdata,8,file_size);
4579 SIVAL(pdata,16,nlink);
4580 SCVAL(pdata,20,delete_pending);
4581 SCVAL(pdata,21,(mode&aDIR)?1:0);
4582 SSVAL(pdata,22,0);
4583 pdata += 24;
4584 SIVAL(pdata,0,ea_size);
4585 pdata += 4; /* EA info */
4586 len = srvstr_push(dstart, flags2,
4587 pdata+4, dos_fname,
4588 PTR_DIFF(dend, pdata+4),
4589 STR_UNICODE);
4590 SIVAL(pdata,0,len);
4591 pdata += 4 + len;
4592 data_size = PTR_DIFF(pdata,(*ppdata));
4593 break;
4596 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4598 int len;
4599 unsigned int ea_size =
4600 estimate_ea_size(conn, fsp, smb_fname->base_name);
4601 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4602 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4603 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4604 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4605 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4606 SIVAL(pdata, 0x20, mode);
4607 SIVAL(pdata, 0x24, 0); /* padding. */
4608 SBVAL(pdata, 0x28, allocation_size);
4609 SBVAL(pdata, 0x30, file_size);
4610 SIVAL(pdata, 0x38, nlink);
4611 SCVAL(pdata, 0x3C, delete_pending);
4612 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4613 SSVAL(pdata, 0x3E, 0); /* padding */
4614 SBVAL(pdata, 0x40, file_index);
4615 SIVAL(pdata, 0x48, ea_size);
4616 SIVAL(pdata, 0x4C, access_mask);
4617 SBVAL(pdata, 0x50, pos);
4618 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4619 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4621 pdata += 0x60;
4623 len = srvstr_push(dstart, flags2,
4624 pdata+4, dos_fname,
4625 PTR_DIFF(dend, pdata+4),
4626 STR_UNICODE);
4627 SIVAL(pdata,0,len);
4628 pdata += 4 + len;
4629 data_size = PTR_DIFF(pdata,(*ppdata));
4630 break;
4632 case SMB_FILE_INTERNAL_INFORMATION:
4634 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4635 SBVAL(pdata, 0, file_index);
4636 data_size = 8;
4637 break;
4639 case SMB_FILE_ACCESS_INFORMATION:
4640 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4641 SIVAL(pdata, 0, access_mask);
4642 data_size = 4;
4643 break;
4645 case SMB_FILE_NAME_INFORMATION:
4646 /* Pathname with leading '\'. */
4648 size_t byte_len;
4649 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4650 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4651 SIVAL(pdata,0,byte_len);
4652 data_size = 4 + byte_len;
4653 break;
4656 case SMB_FILE_DISPOSITION_INFORMATION:
4657 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4658 data_size = 1;
4659 SCVAL(pdata,0,delete_pending);
4660 break;
4662 case SMB_FILE_POSITION_INFORMATION:
4663 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4664 data_size = 8;
4665 SOFF_T(pdata,0,pos);
4666 break;
4668 case SMB_FILE_MODE_INFORMATION:
4669 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4670 SIVAL(pdata,0,mode);
4671 data_size = 4;
4672 break;
4674 case SMB_FILE_ALIGNMENT_INFORMATION:
4675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4676 SIVAL(pdata,0,0); /* No alignment needed. */
4677 data_size = 4;
4678 break;
4681 * NT4 server just returns "invalid query" to this - if we try
4682 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4683 * want this. JRA.
4685 /* The first statement above is false - verified using Thursby
4686 * client against NT4 -- gcolley.
4688 case SMB_QUERY_FILE_STREAM_INFO:
4689 case SMB_FILE_STREAM_INFORMATION: {
4690 unsigned int num_streams;
4691 struct stream_struct *streams;
4693 DEBUG(10,("smbd_do_qfilepathinfo: "
4694 "SMB_FILE_STREAM_INFORMATION\n"));
4696 if (is_ntfs_stream_smb_fname(smb_fname)) {
4697 return NT_STATUS_INVALID_PARAMETER;
4700 status = SMB_VFS_STREAMINFO(
4701 conn, fsp, smb_fname->base_name, talloc_tos(),
4702 &num_streams, &streams);
4704 if (!NT_STATUS_IS_OK(status)) {
4705 DEBUG(10, ("could not get stream info: %s\n",
4706 nt_errstr(status)));
4707 return status;
4710 status = marshall_stream_info(num_streams, streams,
4711 pdata, max_data_bytes,
4712 &data_size);
4714 if (!NT_STATUS_IS_OK(status)) {
4715 DEBUG(10, ("marshall_stream_info failed: %s\n",
4716 nt_errstr(status)));
4717 return status;
4720 TALLOC_FREE(streams);
4722 break;
4724 case SMB_QUERY_COMPRESSION_INFO:
4725 case SMB_FILE_COMPRESSION_INFORMATION:
4726 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4727 SOFF_T(pdata,0,file_size);
4728 SIVAL(pdata,8,0); /* ??? */
4729 SIVAL(pdata,12,0); /* ??? */
4730 data_size = 16;
4731 break;
4733 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4734 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4735 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4736 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4737 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4738 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4739 SOFF_T(pdata,32,allocation_size);
4740 SOFF_T(pdata,40,file_size);
4741 SIVAL(pdata,48,mode);
4742 SIVAL(pdata,52,0); /* ??? */
4743 data_size = 56;
4744 break;
4746 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4747 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4748 SIVAL(pdata,0,mode);
4749 SIVAL(pdata,4,0);
4750 data_size = 8;
4751 break;
4754 * CIFS UNIX Extensions.
4757 case SMB_QUERY_FILE_UNIX_BASIC:
4759 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4760 data_size = PTR_DIFF(pdata,(*ppdata));
4762 DEBUG(4,("smbd_do_qfilepathinfo: "
4763 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4764 dump_data(4, (uint8_t *)(*ppdata), data_size);
4766 break;
4768 case SMB_QUERY_FILE_UNIX_INFO2:
4770 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4771 data_size = PTR_DIFF(pdata,(*ppdata));
4774 int i;
4775 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4777 for (i=0; i<100; i++)
4778 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4779 DEBUG(4,("\n"));
4782 break;
4784 case SMB_QUERY_FILE_UNIX_LINK:
4786 int len;
4787 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4789 if (!buffer) {
4790 return NT_STATUS_NO_MEMORY;
4793 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4794 #ifdef S_ISLNK
4795 if(!S_ISLNK(psbuf->st_ex_mode)) {
4796 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4798 #else
4799 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4800 #endif
4801 len = SMB_VFS_READLINK(conn,
4802 smb_fname->base_name,
4803 buffer, PATH_MAX);
4804 if (len == -1) {
4805 return map_nt_error_from_unix(errno);
4807 buffer[len] = 0;
4808 len = srvstr_push(dstart, flags2,
4809 pdata, buffer,
4810 PTR_DIFF(dend, pdata),
4811 STR_TERMINATE);
4812 pdata += len;
4813 data_size = PTR_DIFF(pdata,(*ppdata));
4815 break;
4818 #if defined(HAVE_POSIX_ACLS)
4819 case SMB_QUERY_POSIX_ACL:
4821 SMB_ACL_T file_acl = NULL;
4822 SMB_ACL_T def_acl = NULL;
4823 uint16 num_file_acls = 0;
4824 uint16 num_def_acls = 0;
4826 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4827 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4828 } else {
4829 file_acl =
4830 SMB_VFS_SYS_ACL_GET_FILE(conn,
4831 smb_fname->base_name,
4832 SMB_ACL_TYPE_ACCESS);
4835 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4836 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4837 "not implemented on "
4838 "filesystem containing %s\n",
4839 smb_fname->base_name));
4840 return NT_STATUS_NOT_IMPLEMENTED;
4843 if (S_ISDIR(psbuf->st_ex_mode)) {
4844 if (fsp && fsp->is_directory) {
4845 def_acl =
4846 SMB_VFS_SYS_ACL_GET_FILE(
4847 conn,
4848 fsp->fsp_name->base_name,
4849 SMB_ACL_TYPE_DEFAULT);
4850 } else {
4851 def_acl =
4852 SMB_VFS_SYS_ACL_GET_FILE(
4853 conn,
4854 smb_fname->base_name,
4855 SMB_ACL_TYPE_DEFAULT);
4857 def_acl = free_empty_sys_acl(conn, def_acl);
4860 num_file_acls = count_acl_entries(conn, file_acl);
4861 num_def_acls = count_acl_entries(conn, def_acl);
4863 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4864 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4865 data_size,
4866 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4867 SMB_POSIX_ACL_HEADER_SIZE) ));
4868 if (file_acl) {
4869 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4871 if (def_acl) {
4872 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4874 return NT_STATUS_BUFFER_TOO_SMALL;
4877 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4878 SSVAL(pdata,2,num_file_acls);
4879 SSVAL(pdata,4,num_def_acls);
4880 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4881 if (file_acl) {
4882 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4884 if (def_acl) {
4885 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4887 return NT_STATUS_INTERNAL_ERROR;
4889 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4890 if (file_acl) {
4891 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4893 if (def_acl) {
4894 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4896 return NT_STATUS_INTERNAL_ERROR;
4899 if (file_acl) {
4900 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4902 if (def_acl) {
4903 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4905 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4906 break;
4908 #endif
4911 case SMB_QUERY_POSIX_LOCK:
4913 uint64_t count;
4914 uint64_t offset;
4915 uint64_t smblctx;
4916 enum brl_type lock_type;
4918 /* We need an open file with a real fd for this. */
4919 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4920 return NT_STATUS_INVALID_LEVEL;
4923 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4924 return NT_STATUS_INVALID_PARAMETER;
4927 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4928 case POSIX_LOCK_TYPE_READ:
4929 lock_type = READ_LOCK;
4930 break;
4931 case POSIX_LOCK_TYPE_WRITE:
4932 lock_type = WRITE_LOCK;
4933 break;
4934 case POSIX_LOCK_TYPE_UNLOCK:
4935 default:
4936 /* There's no point in asking for an unlock... */
4937 return NT_STATUS_INVALID_PARAMETER;
4940 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4941 #if defined(HAVE_LONGLONG)
4942 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4943 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4944 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4945 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4946 #else /* HAVE_LONGLONG */
4947 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4948 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4949 #endif /* HAVE_LONGLONG */
4951 status = query_lock(fsp,
4952 &smblctx,
4953 &count,
4954 &offset,
4955 &lock_type,
4956 POSIX_LOCK);
4958 if (ERROR_WAS_LOCK_DENIED(status)) {
4959 /* Here we need to report who has it locked... */
4960 data_size = POSIX_LOCK_DATA_SIZE;
4962 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4963 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4964 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4965 #if defined(HAVE_LONGLONG)
4966 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4967 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4968 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4969 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4970 #else /* HAVE_LONGLONG */
4971 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4972 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4973 #endif /* HAVE_LONGLONG */
4975 } else if (NT_STATUS_IS_OK(status)) {
4976 /* For success we just return a copy of what we sent
4977 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4978 data_size = POSIX_LOCK_DATA_SIZE;
4979 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4980 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4981 } else {
4982 return status;
4984 break;
4987 default:
4988 return NT_STATUS_INVALID_LEVEL;
4991 *pdata_size = data_size;
4992 return NT_STATUS_OK;
4995 /****************************************************************************
4996 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4997 file name or file id).
4998 ****************************************************************************/
5000 static void call_trans2qfilepathinfo(connection_struct *conn,
5001 struct smb_request *req,
5002 unsigned int tran_call,
5003 char **pparams, int total_params,
5004 char **ppdata, int total_data,
5005 unsigned int max_data_bytes)
5007 char *params = *pparams;
5008 char *pdata = *ppdata;
5009 uint16 info_level;
5010 unsigned int data_size = 0;
5011 unsigned int param_size = 2;
5012 struct smb_filename *smb_fname = NULL;
5013 bool delete_pending = False;
5014 struct timespec write_time_ts;
5015 files_struct *fsp = NULL;
5016 struct file_id fileid;
5017 struct ea_list *ea_list = NULL;
5018 int lock_data_count = 0;
5019 char *lock_data = NULL;
5020 NTSTATUS status = NT_STATUS_OK;
5022 if (!params) {
5023 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5024 return;
5027 ZERO_STRUCT(write_time_ts);
5029 if (tran_call == TRANSACT2_QFILEINFO) {
5030 if (total_params < 4) {
5031 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5032 return;
5035 if (IS_IPC(conn)) {
5036 call_trans2qpipeinfo(conn, req, tran_call,
5037 pparams, total_params,
5038 ppdata, total_data,
5039 max_data_bytes);
5040 return;
5043 fsp = file_fsp(req, SVAL(params,0));
5044 info_level = SVAL(params,2);
5046 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5048 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5049 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5050 return;
5053 /* Initial check for valid fsp ptr. */
5054 if (!check_fsp_open(conn, req, fsp)) {
5055 return;
5058 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5059 &smb_fname);
5060 if (!NT_STATUS_IS_OK(status)) {
5061 reply_nterror(req, status);
5062 return;
5065 if(fsp->fake_file_handle) {
5067 * This is actually for the QUOTA_FAKE_FILE --metze
5070 /* We know this name is ok, it's already passed the checks. */
5072 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5074 * This is actually a QFILEINFO on a directory
5075 * handle (returned from an NT SMB). NT5.0 seems
5076 * to do this call. JRA.
5079 if (INFO_LEVEL_IS_UNIX(info_level)) {
5080 /* Always do lstat for UNIX calls. */
5081 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5082 DEBUG(3,("call_trans2qfilepathinfo: "
5083 "SMB_VFS_LSTAT of %s failed "
5084 "(%s)\n",
5085 smb_fname_str_dbg(smb_fname),
5086 strerror(errno)));
5087 reply_nterror(req,
5088 map_nt_error_from_unix(errno));
5089 return;
5091 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5092 DEBUG(3,("call_trans2qfilepathinfo: "
5093 "SMB_VFS_STAT of %s failed (%s)\n",
5094 smb_fname_str_dbg(smb_fname),
5095 strerror(errno)));
5096 reply_nterror(req,
5097 map_nt_error_from_unix(errno));
5098 return;
5101 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5102 get_file_infos(fileid, &delete_pending, &write_time_ts);
5103 } else {
5105 * Original code - this is an open file.
5107 if (!check_fsp(conn, req, fsp)) {
5108 return;
5111 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5112 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5113 fsp->fnum, strerror(errno)));
5114 reply_nterror(req,
5115 map_nt_error_from_unix(errno));
5116 return;
5118 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5119 get_file_infos(fileid, &delete_pending, &write_time_ts);
5122 } else {
5123 char *fname = NULL;
5125 /* qpathinfo */
5126 if (total_params < 7) {
5127 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5128 return;
5131 info_level = SVAL(params,0);
5133 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5135 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5136 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5137 return;
5140 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5141 total_params - 6,
5142 STR_TERMINATE, &status);
5143 if (!NT_STATUS_IS_OK(status)) {
5144 reply_nterror(req, status);
5145 return;
5148 status = filename_convert(req,
5149 conn,
5150 req->flags2 & FLAGS2_DFS_PATHNAMES,
5151 fname,
5153 NULL,
5154 &smb_fname);
5155 if (!NT_STATUS_IS_OK(status)) {
5156 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5157 reply_botherror(req,
5158 NT_STATUS_PATH_NOT_COVERED,
5159 ERRSRV, ERRbadpath);
5160 return;
5162 reply_nterror(req, status);
5163 return;
5166 /* If this is a stream, check if there is a delete_pending. */
5167 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5168 && is_ntfs_stream_smb_fname(smb_fname)) {
5169 struct smb_filename *smb_fname_base = NULL;
5171 /* Create an smb_filename with stream_name == NULL. */
5172 status =
5173 create_synthetic_smb_fname(talloc_tos(),
5174 smb_fname->base_name,
5175 NULL, NULL,
5176 &smb_fname_base);
5177 if (!NT_STATUS_IS_OK(status)) {
5178 reply_nterror(req, status);
5179 return;
5182 if (INFO_LEVEL_IS_UNIX(info_level)) {
5183 /* Always do lstat for UNIX calls. */
5184 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5185 DEBUG(3,("call_trans2qfilepathinfo: "
5186 "SMB_VFS_LSTAT of %s failed "
5187 "(%s)\n",
5188 smb_fname_str_dbg(smb_fname_base),
5189 strerror(errno)));
5190 TALLOC_FREE(smb_fname_base);
5191 reply_nterror(req,
5192 map_nt_error_from_unix(errno));
5193 return;
5195 } else {
5196 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5197 DEBUG(3,("call_trans2qfilepathinfo: "
5198 "fileinfo of %s failed "
5199 "(%s)\n",
5200 smb_fname_str_dbg(smb_fname_base),
5201 strerror(errno)));
5202 TALLOC_FREE(smb_fname_base);
5203 reply_nterror(req,
5204 map_nt_error_from_unix(errno));
5205 return;
5209 fileid = vfs_file_id_from_sbuf(conn,
5210 &smb_fname_base->st);
5211 TALLOC_FREE(smb_fname_base);
5212 get_file_infos(fileid, &delete_pending, NULL);
5213 if (delete_pending) {
5214 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5215 return;
5219 if (INFO_LEVEL_IS_UNIX(info_level)) {
5220 /* Always do lstat for UNIX calls. */
5221 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5222 DEBUG(3,("call_trans2qfilepathinfo: "
5223 "SMB_VFS_LSTAT of %s failed (%s)\n",
5224 smb_fname_str_dbg(smb_fname),
5225 strerror(errno)));
5226 reply_nterror(req,
5227 map_nt_error_from_unix(errno));
5228 return;
5231 } else {
5232 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5233 DEBUG(3,("call_trans2qfilepathinfo: "
5234 "SMB_VFS_STAT 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;
5243 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5244 get_file_infos(fileid, &delete_pending, &write_time_ts);
5245 if (delete_pending) {
5246 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5247 return;
5251 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5252 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5253 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5255 /* Pull out any data sent here before we realloc. */
5256 switch (info_level) {
5257 case SMB_INFO_QUERY_EAS_FROM_LIST:
5259 /* Pull any EA list from the data portion. */
5260 uint32 ea_size;
5262 if (total_data < 4) {
5263 reply_nterror(
5264 req, NT_STATUS_INVALID_PARAMETER);
5265 return;
5267 ea_size = IVAL(pdata,0);
5269 if (total_data > 0 && ea_size != total_data) {
5270 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5271 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5272 reply_nterror(
5273 req, NT_STATUS_INVALID_PARAMETER);
5274 return;
5277 if (!lp_ea_support(SNUM(conn))) {
5278 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5279 return;
5282 /* Pull out the list of names. */
5283 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5284 if (!ea_list) {
5285 reply_nterror(
5286 req, NT_STATUS_INVALID_PARAMETER);
5287 return;
5289 break;
5292 case SMB_QUERY_POSIX_LOCK:
5294 if (fsp == NULL || fsp->fh->fd == -1) {
5295 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5296 return;
5299 if (total_data != POSIX_LOCK_DATA_SIZE) {
5300 reply_nterror(
5301 req, NT_STATUS_INVALID_PARAMETER);
5302 return;
5305 /* Copy the lock range data. */
5306 lock_data = (char *)TALLOC_MEMDUP(
5307 req, pdata, total_data);
5308 if (!lock_data) {
5309 reply_nterror(req, NT_STATUS_NO_MEMORY);
5310 return;
5312 lock_data_count = total_data;
5314 default:
5315 break;
5318 *pparams = (char *)SMB_REALLOC(*pparams,2);
5319 if (*pparams == NULL) {
5320 reply_nterror(req, NT_STATUS_NO_MEMORY);
5321 return;
5323 params = *pparams;
5324 SSVAL(params,0,0);
5327 * draft-leach-cifs-v1-spec-02.txt
5328 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5329 * says:
5331 * The requested information is placed in the Data portion of the
5332 * transaction response. For the information levels greater than 0x100,
5333 * the transaction response has 1 parameter word which should be
5334 * ignored by the client.
5336 * However Windows only follows this rule for the IS_NAME_VALID call.
5338 switch (info_level) {
5339 case SMB_INFO_IS_NAME_VALID:
5340 param_size = 0;
5341 break;
5344 if ((info_level & 0xFF00) == 0xFF00) {
5346 * We use levels that start with 0xFF00
5347 * internally to represent SMB2 specific levels
5349 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5350 return;
5353 status = smbd_do_qfilepathinfo(conn, req, info_level,
5354 fsp, smb_fname,
5355 delete_pending, write_time_ts,
5356 ea_list,
5357 lock_data_count, lock_data,
5358 req->flags2, max_data_bytes,
5359 ppdata, &data_size);
5360 if (!NT_STATUS_IS_OK(status)) {
5361 reply_nterror(req, status);
5362 return;
5365 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5366 max_data_bytes);
5368 return;
5371 /****************************************************************************
5372 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5373 code.
5374 ****************************************************************************/
5376 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5377 connection_struct *conn,
5378 struct smb_request *req,
5379 bool overwrite_if_exists,
5380 const struct smb_filename *smb_fname_old,
5381 struct smb_filename *smb_fname_new)
5383 NTSTATUS status = NT_STATUS_OK;
5385 /* source must already exist. */
5386 if (!VALID_STAT(smb_fname_old->st)) {
5387 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5390 if (VALID_STAT(smb_fname_new->st)) {
5391 if (overwrite_if_exists) {
5392 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5393 return NT_STATUS_FILE_IS_A_DIRECTORY;
5395 status = unlink_internals(conn,
5396 req,
5397 FILE_ATTRIBUTE_NORMAL,
5398 smb_fname_new,
5399 false);
5400 if (!NT_STATUS_IS_OK(status)) {
5401 return status;
5403 } else {
5404 /* Disallow if newname already exists. */
5405 return NT_STATUS_OBJECT_NAME_COLLISION;
5409 /* No links from a directory. */
5410 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5411 return NT_STATUS_FILE_IS_A_DIRECTORY;
5414 /* Setting a hardlink to/from a stream isn't currently supported. */
5415 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5416 is_ntfs_stream_smb_fname(smb_fname_new)) {
5417 return NT_STATUS_INVALID_PARAMETER;
5420 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5421 smb_fname_old->base_name, smb_fname_new->base_name));
5423 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5424 smb_fname_new->base_name) != 0) {
5425 status = map_nt_error_from_unix(errno);
5426 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5427 nt_errstr(status), smb_fname_old->base_name,
5428 smb_fname_new->base_name));
5430 return status;
5433 /****************************************************************************
5434 Deal with setting the time from any of the setfilepathinfo functions.
5435 ****************************************************************************/
5437 NTSTATUS smb_set_file_time(connection_struct *conn,
5438 files_struct *fsp,
5439 const struct smb_filename *smb_fname,
5440 struct smb_file_time *ft,
5441 bool setting_write_time)
5443 struct smb_filename smb_fname_base;
5444 uint32 action =
5445 FILE_NOTIFY_CHANGE_LAST_ACCESS
5446 |FILE_NOTIFY_CHANGE_LAST_WRITE
5447 |FILE_NOTIFY_CHANGE_CREATION;
5449 if (!VALID_STAT(smb_fname->st)) {
5450 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5453 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5454 return NT_STATUS_ACCESS_DENIED;
5457 /* get some defaults (no modifications) if any info is zero or -1. */
5458 if (null_timespec(ft->create_time)) {
5459 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5462 if (null_timespec(ft->atime)) {
5463 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5466 if (null_timespec(ft->mtime)) {
5467 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5470 if (!setting_write_time) {
5471 /* ft->mtime comes from change time, not write time. */
5472 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5475 /* Ensure the resolution is the correct for
5476 * what we can store on this filesystem. */
5478 round_timespec(conn->ts_res, &ft->create_time);
5479 round_timespec(conn->ts_res, &ft->ctime);
5480 round_timespec(conn->ts_res, &ft->atime);
5481 round_timespec(conn->ts_res, &ft->mtime);
5483 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5484 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5485 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5486 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5487 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5488 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5489 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5490 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5492 if (setting_write_time) {
5494 * This was a Windows setfileinfo on an open file.
5495 * NT does this a lot. We also need to
5496 * set the time here, as it can be read by
5497 * FindFirst/FindNext and with the patch for bug #2045
5498 * in smbd/fileio.c it ensures that this timestamp is
5499 * kept sticky even after a write. We save the request
5500 * away and will set it on file close and after a write. JRA.
5503 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5504 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5506 if (fsp != NULL) {
5507 if (fsp->base_fsp) {
5508 set_sticky_write_time_fsp(fsp->base_fsp,
5509 ft->mtime);
5510 } else {
5511 set_sticky_write_time_fsp(fsp, ft->mtime);
5513 } else {
5514 set_sticky_write_time_path(
5515 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5516 ft->mtime);
5520 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5522 /* Always call ntimes on the base, even if a stream was passed in. */
5523 smb_fname_base = *smb_fname;
5524 smb_fname_base.stream_name = NULL;
5526 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5527 return map_nt_error_from_unix(errno);
5530 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5531 smb_fname->base_name);
5532 return NT_STATUS_OK;
5535 /****************************************************************************
5536 Deal with setting the dosmode from any of the setfilepathinfo functions.
5537 ****************************************************************************/
5539 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5540 const struct smb_filename *smb_fname,
5541 uint32 dosmode)
5543 struct smb_filename *smb_fname_base = NULL;
5544 NTSTATUS status;
5546 if (!VALID_STAT(smb_fname->st)) {
5547 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5550 /* Always operate on the base_name, even if a stream was passed in. */
5551 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5552 NULL, &smb_fname->st,
5553 &smb_fname_base);
5554 if (!NT_STATUS_IS_OK(status)) {
5555 return status;
5558 if (dosmode) {
5559 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5560 dosmode |= aDIR;
5561 } else {
5562 dosmode &= ~aDIR;
5566 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5568 /* check the mode isn't different, before changing it */
5569 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5570 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5571 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5572 (unsigned int)dosmode));
5574 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5575 false)) {
5576 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5577 "%s failed (%s)\n",
5578 smb_fname_str_dbg(smb_fname_base),
5579 strerror(errno)));
5580 status = map_nt_error_from_unix(errno);
5581 goto out;
5584 status = NT_STATUS_OK;
5585 out:
5586 TALLOC_FREE(smb_fname_base);
5587 return status;
5590 /****************************************************************************
5591 Deal with setting the size from any of the setfilepathinfo functions.
5592 ****************************************************************************/
5594 static NTSTATUS smb_set_file_size(connection_struct *conn,
5595 struct smb_request *req,
5596 files_struct *fsp,
5597 const struct smb_filename *smb_fname,
5598 const SMB_STRUCT_STAT *psbuf,
5599 SMB_OFF_T size,
5600 bool fail_after_createfile)
5602 NTSTATUS status = NT_STATUS_OK;
5603 struct smb_filename *smb_fname_tmp = NULL;
5604 files_struct *new_fsp = NULL;
5606 if (!VALID_STAT(*psbuf)) {
5607 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5610 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5611 return NT_STATUS_ACCESS_DENIED;
5614 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5616 if (size == get_file_size_stat(psbuf)) {
5617 return NT_STATUS_OK;
5620 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5621 smb_fname_str_dbg(smb_fname), (double)size));
5623 if (fsp && fsp->fh->fd != -1) {
5624 /* Handle based call. */
5625 if (vfs_set_filelen(fsp, size) == -1) {
5626 return map_nt_error_from_unix(errno);
5628 trigger_write_time_update_immediate(fsp);
5629 return NT_STATUS_OK;
5632 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5633 if (!NT_STATUS_IS_OK(status)) {
5634 return status;
5637 smb_fname_tmp->st = *psbuf;
5639 status = SMB_VFS_CREATE_FILE(
5640 conn, /* conn */
5641 req, /* req */
5642 0, /* root_dir_fid */
5643 smb_fname_tmp, /* fname */
5644 FILE_WRITE_DATA, /* access_mask */
5645 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5646 FILE_SHARE_DELETE),
5647 FILE_OPEN, /* create_disposition*/
5648 0, /* create_options */
5649 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5650 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5651 0, /* allocation_size */
5652 0, /* private_flags */
5653 NULL, /* sd */
5654 NULL, /* ea_list */
5655 &new_fsp, /* result */
5656 NULL); /* pinfo */
5658 TALLOC_FREE(smb_fname_tmp);
5660 if (!NT_STATUS_IS_OK(status)) {
5661 /* NB. We check for open_was_deferred in the caller. */
5662 return status;
5665 /* See RAW-SFILEINFO-END-OF-FILE */
5666 if (fail_after_createfile) {
5667 close_file(req, new_fsp,NORMAL_CLOSE);
5668 return NT_STATUS_INVALID_LEVEL;
5671 if (vfs_set_filelen(new_fsp, size) == -1) {
5672 status = map_nt_error_from_unix(errno);
5673 close_file(req, new_fsp,NORMAL_CLOSE);
5674 return status;
5677 trigger_write_time_update_immediate(new_fsp);
5678 close_file(req, new_fsp,NORMAL_CLOSE);
5679 return NT_STATUS_OK;
5682 /****************************************************************************
5683 Deal with SMB_INFO_SET_EA.
5684 ****************************************************************************/
5686 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5687 const char *pdata,
5688 int total_data,
5689 files_struct *fsp,
5690 const struct smb_filename *smb_fname)
5692 struct ea_list *ea_list = NULL;
5693 TALLOC_CTX *ctx = NULL;
5694 NTSTATUS status = NT_STATUS_OK;
5696 if (total_data < 10) {
5698 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5699 length. They seem to have no effect. Bug #3212. JRA */
5701 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5702 /* We're done. We only get EA info in this call. */
5703 return NT_STATUS_OK;
5706 return NT_STATUS_INVALID_PARAMETER;
5709 if (IVAL(pdata,0) > total_data) {
5710 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5711 IVAL(pdata,0), (unsigned int)total_data));
5712 return NT_STATUS_INVALID_PARAMETER;
5715 ctx = talloc_tos();
5716 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5717 if (!ea_list) {
5718 return NT_STATUS_INVALID_PARAMETER;
5721 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5722 return NT_STATUS_ACCESS_DENIED;
5725 status = set_ea(conn, fsp, smb_fname, ea_list);
5727 return status;
5730 /****************************************************************************
5731 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5732 ****************************************************************************/
5734 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5735 const char *pdata,
5736 int total_data,
5737 files_struct *fsp)
5739 struct ea_list *ea_list = NULL;
5740 NTSTATUS status;
5742 if (!fsp) {
5743 return NT_STATUS_INVALID_HANDLE;
5746 if (!lp_ea_support(SNUM(conn))) {
5747 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5748 "EA's not supported.\n",
5749 (unsigned int)total_data));
5750 return NT_STATUS_EAS_NOT_SUPPORTED;
5753 if (total_data < 10) {
5754 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5755 "too small.\n",
5756 (unsigned int)total_data));
5757 return NT_STATUS_INVALID_PARAMETER;
5760 ea_list = read_nttrans_ea_list(talloc_tos(),
5761 pdata,
5762 total_data);
5764 if (!ea_list) {
5765 return NT_STATUS_INVALID_PARAMETER;
5768 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5769 return NT_STATUS_ACCESS_DENIED;
5772 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5774 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5775 smb_fname_str_dbg(fsp->fsp_name),
5776 nt_errstr(status) ));
5778 return status;
5782 /****************************************************************************
5783 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5784 ****************************************************************************/
5786 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5787 const char *pdata,
5788 int total_data,
5789 files_struct *fsp,
5790 struct smb_filename *smb_fname)
5792 NTSTATUS status = NT_STATUS_OK;
5793 bool delete_on_close;
5794 uint32 dosmode = 0;
5796 if (total_data < 1) {
5797 return NT_STATUS_INVALID_PARAMETER;
5800 if (fsp == NULL) {
5801 return NT_STATUS_INVALID_HANDLE;
5804 delete_on_close = (CVAL(pdata,0) ? True : False);
5805 dosmode = dos_mode(conn, smb_fname);
5807 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5808 "delete_on_close = %u\n",
5809 smb_fname_str_dbg(smb_fname),
5810 (unsigned int)dosmode,
5811 (unsigned int)delete_on_close ));
5813 if (delete_on_close) {
5814 status = can_set_delete_on_close(fsp, dosmode);
5815 if (!NT_STATUS_IS_OK(status)) {
5816 return status;
5820 /* The set is across all open files on this dev/inode pair. */
5821 if (!set_delete_on_close(fsp, delete_on_close,
5822 &conn->server_info->utok)) {
5823 return NT_STATUS_ACCESS_DENIED;
5825 return NT_STATUS_OK;
5828 /****************************************************************************
5829 Deal with SMB_FILE_POSITION_INFORMATION.
5830 ****************************************************************************/
5832 static NTSTATUS smb_file_position_information(connection_struct *conn,
5833 const char *pdata,
5834 int total_data,
5835 files_struct *fsp)
5837 uint64_t position_information;
5839 if (total_data < 8) {
5840 return NT_STATUS_INVALID_PARAMETER;
5843 if (fsp == NULL) {
5844 /* Ignore on pathname based set. */
5845 return NT_STATUS_OK;
5848 position_information = (uint64_t)IVAL(pdata,0);
5849 #ifdef LARGE_SMB_OFF_T
5850 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5851 #else /* LARGE_SMB_OFF_T */
5852 if (IVAL(pdata,4) != 0) {
5853 /* more than 32 bits? */
5854 return NT_STATUS_INVALID_PARAMETER;
5856 #endif /* LARGE_SMB_OFF_T */
5858 DEBUG(10,("smb_file_position_information: Set file position "
5859 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5860 (double)position_information));
5861 fsp->fh->position_information = position_information;
5862 return NT_STATUS_OK;
5865 /****************************************************************************
5866 Deal with SMB_FILE_MODE_INFORMATION.
5867 ****************************************************************************/
5869 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5870 const char *pdata,
5871 int total_data)
5873 uint32 mode;
5875 if (total_data < 4) {
5876 return NT_STATUS_INVALID_PARAMETER;
5878 mode = IVAL(pdata,0);
5879 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5880 return NT_STATUS_INVALID_PARAMETER;
5882 return NT_STATUS_OK;
5885 /****************************************************************************
5886 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5887 ****************************************************************************/
5889 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5890 struct smb_request *req,
5891 const char *pdata,
5892 int total_data,
5893 const struct smb_filename *smb_fname)
5895 char *link_target = NULL;
5896 const char *newname = smb_fname->base_name;
5897 TALLOC_CTX *ctx = talloc_tos();
5899 /* Set a symbolic link. */
5900 /* Don't allow this if follow links is false. */
5902 if (total_data == 0) {
5903 return NT_STATUS_INVALID_PARAMETER;
5906 if (!lp_symlinks(SNUM(conn))) {
5907 return NT_STATUS_ACCESS_DENIED;
5910 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5911 total_data, STR_TERMINATE);
5913 if (!link_target) {
5914 return NT_STATUS_INVALID_PARAMETER;
5917 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5918 newname, link_target ));
5920 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5921 return map_nt_error_from_unix(errno);
5924 return NT_STATUS_OK;
5927 /****************************************************************************
5928 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5929 ****************************************************************************/
5931 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5932 struct smb_request *req,
5933 const char *pdata, int total_data,
5934 struct smb_filename *smb_fname_new)
5936 char *oldname = NULL;
5937 struct smb_filename *smb_fname_old = NULL;
5938 TALLOC_CTX *ctx = talloc_tos();
5939 NTSTATUS status = NT_STATUS_OK;
5941 /* Set a hard link. */
5942 if (total_data == 0) {
5943 return NT_STATUS_INVALID_PARAMETER;
5946 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5947 total_data, STR_TERMINATE, &status);
5948 if (!NT_STATUS_IS_OK(status)) {
5949 return status;
5952 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5953 smb_fname_str_dbg(smb_fname_new), oldname));
5955 status = filename_convert(ctx,
5956 conn,
5957 req->flags2 & FLAGS2_DFS_PATHNAMES,
5958 oldname,
5960 NULL,
5961 &smb_fname_old);
5962 if (!NT_STATUS_IS_OK(status)) {
5963 return status;
5966 return hardlink_internals(ctx, conn, req, false,
5967 smb_fname_old, smb_fname_new);
5970 /****************************************************************************
5971 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5972 ****************************************************************************/
5974 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5975 struct smb_request *req,
5976 const char *pdata,
5977 int total_data,
5978 files_struct *fsp,
5979 struct smb_filename *smb_fname_src)
5981 bool overwrite;
5982 uint32_t len;
5983 char *newname = NULL;
5984 struct smb_filename *smb_fname_dst = NULL;
5985 NTSTATUS status = NT_STATUS_OK;
5986 TALLOC_CTX *ctx = talloc_tos();
5988 if (!fsp) {
5989 return NT_STATUS_INVALID_HANDLE;
5992 if (total_data < 20) {
5993 return NT_STATUS_INVALID_PARAMETER;
5996 overwrite = (CVAL(pdata,0) ? True : False);
5997 len = IVAL(pdata,16);
5999 if (len > (total_data - 20) || (len == 0)) {
6000 return NT_STATUS_INVALID_PARAMETER;
6003 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6004 &pdata[20], len, STR_TERMINATE,
6005 &status);
6006 if (!NT_STATUS_IS_OK(status)) {
6007 return status;
6010 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6011 newname));
6013 status = filename_convert(ctx,
6014 conn,
6015 req->flags2 & FLAGS2_DFS_PATHNAMES,
6016 newname,
6017 UCF_SAVE_LCOMP,
6018 NULL,
6019 &smb_fname_dst);
6020 if (!NT_STATUS_IS_OK(status)) {
6021 return status;
6024 if (fsp->base_fsp) {
6025 /* newname must be a stream name. */
6026 if (newname[0] != ':') {
6027 return NT_STATUS_NOT_SUPPORTED;
6030 /* Create an smb_fname to call rename_internals_fsp() with. */
6031 status = create_synthetic_smb_fname(talloc_tos(),
6032 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6033 &smb_fname_dst);
6034 if (!NT_STATUS_IS_OK(status)) {
6035 goto out;
6039 * Set the original last component, since
6040 * rename_internals_fsp() requires it.
6042 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6043 newname);
6044 if (smb_fname_dst->original_lcomp == NULL) {
6045 status = NT_STATUS_NO_MEMORY;
6046 goto out;
6051 DEBUG(10,("smb2_file_rename_information: "
6052 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6053 fsp->fnum, fsp_str_dbg(fsp),
6054 smb_fname_str_dbg(smb_fname_dst)));
6055 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6056 overwrite);
6058 out:
6059 TALLOC_FREE(smb_fname_dst);
6060 return status;
6063 static NTSTATUS smb_file_link_information(connection_struct *conn,
6064 struct smb_request *req,
6065 const char *pdata,
6066 int total_data,
6067 files_struct *fsp,
6068 struct smb_filename *smb_fname_src)
6070 bool overwrite;
6071 uint32_t len;
6072 char *newname = NULL;
6073 struct smb_filename *smb_fname_dst = NULL;
6074 NTSTATUS status = NT_STATUS_OK;
6075 TALLOC_CTX *ctx = talloc_tos();
6077 if (!fsp) {
6078 return NT_STATUS_INVALID_HANDLE;
6081 if (total_data < 20) {
6082 return NT_STATUS_INVALID_PARAMETER;
6085 overwrite = (CVAL(pdata,0) ? true : false);
6086 len = IVAL(pdata,16);
6088 if (len > (total_data - 20) || (len == 0)) {
6089 return NT_STATUS_INVALID_PARAMETER;
6092 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6093 &pdata[20], len, STR_TERMINATE,
6094 &status);
6095 if (!NT_STATUS_IS_OK(status)) {
6096 return status;
6099 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6100 newname));
6102 status = filename_convert(ctx,
6103 conn,
6104 req->flags2 & FLAGS2_DFS_PATHNAMES,
6105 newname,
6106 UCF_SAVE_LCOMP,
6107 NULL,
6108 &smb_fname_dst);
6109 if (!NT_STATUS_IS_OK(status)) {
6110 return status;
6113 if (fsp->base_fsp) {
6114 /* No stream names. */
6115 return NT_STATUS_NOT_SUPPORTED;
6118 DEBUG(10,("smb_file_link_information: "
6119 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6120 fsp->fnum, fsp_str_dbg(fsp),
6121 smb_fname_str_dbg(smb_fname_dst)));
6122 status = hardlink_internals(ctx,
6123 conn,
6124 req,
6125 overwrite,
6126 fsp->fsp_name,
6127 smb_fname_dst);
6129 TALLOC_FREE(smb_fname_dst);
6130 return status;
6133 /****************************************************************************
6134 Deal with SMB_FILE_RENAME_INFORMATION.
6135 ****************************************************************************/
6137 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6138 struct smb_request *req,
6139 const char *pdata,
6140 int total_data,
6141 files_struct *fsp,
6142 struct smb_filename *smb_fname_src)
6144 bool overwrite;
6145 uint32 root_fid;
6146 uint32 len;
6147 char *newname = NULL;
6148 struct smb_filename *smb_fname_dst = NULL;
6149 bool dest_has_wcard = False;
6150 NTSTATUS status = NT_STATUS_OK;
6151 char *p;
6152 TALLOC_CTX *ctx = talloc_tos();
6154 if (total_data < 13) {
6155 return NT_STATUS_INVALID_PARAMETER;
6158 overwrite = (CVAL(pdata,0) ? True : False);
6159 root_fid = IVAL(pdata,4);
6160 len = IVAL(pdata,8);
6162 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6163 return NT_STATUS_INVALID_PARAMETER;
6166 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6167 len, 0, &status,
6168 &dest_has_wcard);
6169 if (!NT_STATUS_IS_OK(status)) {
6170 return status;
6173 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6174 newname));
6176 status = resolve_dfspath_wcard(ctx, conn,
6177 req->flags2 & FLAGS2_DFS_PATHNAMES,
6178 newname,
6179 true,
6180 &newname,
6181 &dest_has_wcard);
6182 if (!NT_STATUS_IS_OK(status)) {
6183 return status;
6186 /* Check the new name has no '/' characters. */
6187 if (strchr_m(newname, '/')) {
6188 return NT_STATUS_NOT_SUPPORTED;
6191 if (fsp && fsp->base_fsp) {
6192 /* newname must be a stream name. */
6193 if (newname[0] != ':') {
6194 return NT_STATUS_NOT_SUPPORTED;
6197 /* Create an smb_fname to call rename_internals_fsp() with. */
6198 status = create_synthetic_smb_fname(talloc_tos(),
6199 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6200 &smb_fname_dst);
6201 if (!NT_STATUS_IS_OK(status)) {
6202 goto out;
6206 * Set the original last component, since
6207 * rename_internals_fsp() requires it.
6209 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6210 newname);
6211 if (smb_fname_dst->original_lcomp == NULL) {
6212 status = NT_STATUS_NO_MEMORY;
6213 goto out;
6216 } else {
6218 * Build up an smb_fname_dst based on the filename passed in.
6219 * We basically just strip off the last component, and put on
6220 * the newname instead.
6222 char *base_name = NULL;
6224 /* newname must *not* be a stream name. */
6225 if (newname[0] == ':') {
6226 return NT_STATUS_NOT_SUPPORTED;
6230 * Strip off the last component (filename) of the path passed
6231 * in.
6233 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6234 if (!base_name) {
6235 return NT_STATUS_NO_MEMORY;
6237 p = strrchr_m(base_name, '/');
6238 if (p) {
6239 p[1] = '\0';
6240 } else {
6241 base_name = talloc_strdup(ctx, "./");
6242 if (!base_name) {
6243 return NT_STATUS_NO_MEMORY;
6246 /* Append the new name. */
6247 base_name = talloc_asprintf_append(base_name,
6248 "%s",
6249 newname);
6250 if (!base_name) {
6251 return NT_STATUS_NO_MEMORY;
6254 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6255 (UCF_SAVE_LCOMP |
6256 (dest_has_wcard ?
6257 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6258 0)));
6260 /* If an error we expect this to be
6261 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6263 if (!NT_STATUS_IS_OK(status)) {
6264 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6265 status)) {
6266 goto out;
6268 /* Create an smb_fname to call rename_internals_fsp() */
6269 status = create_synthetic_smb_fname(ctx,
6270 base_name, NULL,
6271 NULL,
6272 &smb_fname_dst);
6273 if (!NT_STATUS_IS_OK(status)) {
6274 goto out;
6279 if (fsp) {
6280 DEBUG(10,("smb_file_rename_information: "
6281 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6282 fsp->fnum, fsp_str_dbg(fsp),
6283 smb_fname_str_dbg(smb_fname_dst)));
6284 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6285 overwrite);
6286 } else {
6287 DEBUG(10,("smb_file_rename_information: "
6288 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6289 smb_fname_str_dbg(smb_fname_src),
6290 smb_fname_str_dbg(smb_fname_dst)));
6291 status = rename_internals(ctx, conn, req, smb_fname_src,
6292 smb_fname_dst, 0, overwrite, false,
6293 dest_has_wcard,
6294 FILE_WRITE_ATTRIBUTES);
6296 out:
6297 TALLOC_FREE(smb_fname_dst);
6298 return status;
6301 /****************************************************************************
6302 Deal with SMB_SET_POSIX_ACL.
6303 ****************************************************************************/
6305 #if defined(HAVE_POSIX_ACLS)
6306 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6307 const char *pdata,
6308 int total_data,
6309 files_struct *fsp,
6310 const struct smb_filename *smb_fname)
6312 uint16 posix_acl_version;
6313 uint16 num_file_acls;
6314 uint16 num_def_acls;
6315 bool valid_file_acls = True;
6316 bool valid_def_acls = True;
6318 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6319 return NT_STATUS_INVALID_PARAMETER;
6321 posix_acl_version = SVAL(pdata,0);
6322 num_file_acls = SVAL(pdata,2);
6323 num_def_acls = SVAL(pdata,4);
6325 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6326 valid_file_acls = False;
6327 num_file_acls = 0;
6330 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6331 valid_def_acls = False;
6332 num_def_acls = 0;
6335 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6336 return NT_STATUS_INVALID_PARAMETER;
6339 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6340 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6341 return NT_STATUS_INVALID_PARAMETER;
6344 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6345 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6346 (unsigned int)num_file_acls,
6347 (unsigned int)num_def_acls));
6349 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6350 smb_fname->base_name, num_file_acls,
6351 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6352 return map_nt_error_from_unix(errno);
6355 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6356 smb_fname->base_name, &smb_fname->st, num_def_acls,
6357 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6358 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6359 return map_nt_error_from_unix(errno);
6361 return NT_STATUS_OK;
6363 #endif
6365 /****************************************************************************
6366 Deal with SMB_SET_POSIX_LOCK.
6367 ****************************************************************************/
6369 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6370 struct smb_request *req,
6371 const char *pdata,
6372 int total_data,
6373 files_struct *fsp)
6375 uint64_t count;
6376 uint64_t offset;
6377 uint64_t smblctx;
6378 bool blocking_lock = False;
6379 enum brl_type lock_type;
6381 NTSTATUS status = NT_STATUS_OK;
6383 if (fsp == NULL || fsp->fh->fd == -1) {
6384 return NT_STATUS_INVALID_HANDLE;
6387 if (total_data != POSIX_LOCK_DATA_SIZE) {
6388 return NT_STATUS_INVALID_PARAMETER;
6391 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6392 case POSIX_LOCK_TYPE_READ:
6393 lock_type = READ_LOCK;
6394 break;
6395 case POSIX_LOCK_TYPE_WRITE:
6396 /* Return the right POSIX-mappable error code for files opened read-only. */
6397 if (!fsp->can_write) {
6398 return NT_STATUS_INVALID_HANDLE;
6400 lock_type = WRITE_LOCK;
6401 break;
6402 case POSIX_LOCK_TYPE_UNLOCK:
6403 lock_type = UNLOCK_LOCK;
6404 break;
6405 default:
6406 return NT_STATUS_INVALID_PARAMETER;
6409 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6410 blocking_lock = False;
6411 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6412 blocking_lock = True;
6413 } else {
6414 return NT_STATUS_INVALID_PARAMETER;
6417 if (!lp_blocking_locks(SNUM(conn))) {
6418 blocking_lock = False;
6421 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6422 #if defined(HAVE_LONGLONG)
6423 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6424 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6425 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6426 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6427 #else /* HAVE_LONGLONG */
6428 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6429 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6430 #endif /* HAVE_LONGLONG */
6432 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6433 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6434 fsp_str_dbg(fsp),
6435 (unsigned int)lock_type,
6436 (unsigned long long)smblctx,
6437 (double)count,
6438 (double)offset ));
6440 if (lock_type == UNLOCK_LOCK) {
6441 status = do_unlock(req->sconn->msg_ctx,
6442 fsp,
6443 smblctx,
6444 count,
6445 offset,
6446 POSIX_LOCK);
6447 } else {
6448 uint64_t block_smblctx;
6450 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6451 fsp,
6452 smblctx,
6453 count,
6454 offset,
6455 lock_type,
6456 POSIX_LOCK,
6457 blocking_lock,
6458 &status,
6459 &block_smblctx,
6460 NULL);
6462 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6464 * A blocking lock was requested. Package up
6465 * this smb into a queued request and push it
6466 * onto the blocking lock queue.
6468 if(push_blocking_lock_request(br_lck,
6469 req,
6470 fsp,
6471 -1, /* infinite timeout. */
6473 smblctx,
6474 lock_type,
6475 POSIX_LOCK,
6476 offset,
6477 count,
6478 block_smblctx)) {
6479 TALLOC_FREE(br_lck);
6480 return status;
6483 TALLOC_FREE(br_lck);
6486 return status;
6489 /****************************************************************************
6490 Deal with SMB_SET_FILE_BASIC_INFO.
6491 ****************************************************************************/
6493 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6494 const char *pdata,
6495 int total_data,
6496 files_struct *fsp,
6497 const struct smb_filename *smb_fname)
6499 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6500 struct smb_file_time ft;
6501 uint32 dosmode = 0;
6502 NTSTATUS status = NT_STATUS_OK;
6504 ZERO_STRUCT(ft);
6506 if (total_data < 36) {
6507 return NT_STATUS_INVALID_PARAMETER;
6510 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6511 return NT_STATUS_ACCESS_DENIED;
6514 /* Set the attributes */
6515 dosmode = IVAL(pdata,32);
6516 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6517 if (!NT_STATUS_IS_OK(status)) {
6518 return status;
6521 /* create time */
6522 ft.create_time = interpret_long_date(pdata);
6524 /* access time */
6525 ft.atime = interpret_long_date(pdata+8);
6527 /* write time. */
6528 ft.mtime = interpret_long_date(pdata+16);
6530 /* change time. */
6531 ft.ctime = interpret_long_date(pdata+24);
6533 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6534 smb_fname_str_dbg(smb_fname)));
6536 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6537 true);
6540 /****************************************************************************
6541 Deal with SMB_INFO_STANDARD.
6542 ****************************************************************************/
6544 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6545 const char *pdata,
6546 int total_data,
6547 files_struct *fsp,
6548 const struct smb_filename *smb_fname)
6550 struct smb_file_time ft;
6552 ZERO_STRUCT(ft);
6554 if (total_data < 12) {
6555 return NT_STATUS_INVALID_PARAMETER;
6558 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6559 return NT_STATUS_ACCESS_DENIED;
6562 /* create time */
6563 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6564 /* access time */
6565 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6566 /* write time */
6567 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6569 DEBUG(10,("smb_set_info_standard: file %s\n",
6570 smb_fname_str_dbg(smb_fname)));
6572 return smb_set_file_time(conn,
6573 fsp,
6574 smb_fname,
6575 &ft,
6576 true);
6579 /****************************************************************************
6580 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6581 ****************************************************************************/
6583 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6584 struct smb_request *req,
6585 const char *pdata,
6586 int total_data,
6587 files_struct *fsp,
6588 struct smb_filename *smb_fname)
6590 uint64_t allocation_size = 0;
6591 NTSTATUS status = NT_STATUS_OK;
6592 files_struct *new_fsp = NULL;
6594 if (!VALID_STAT(smb_fname->st)) {
6595 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6598 if (total_data < 8) {
6599 return NT_STATUS_INVALID_PARAMETER;
6602 allocation_size = (uint64_t)IVAL(pdata,0);
6603 #ifdef LARGE_SMB_OFF_T
6604 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6605 #else /* LARGE_SMB_OFF_T */
6606 if (IVAL(pdata,4) != 0) {
6607 /* more than 32 bits? */
6608 return NT_STATUS_INVALID_PARAMETER;
6610 #endif /* LARGE_SMB_OFF_T */
6612 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6613 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6614 (double)allocation_size));
6616 if (allocation_size) {
6617 allocation_size = smb_roundup(conn, allocation_size);
6620 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6621 return NT_STATUS_ACCESS_DENIED;
6624 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6625 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6626 (double)allocation_size));
6628 if (fsp && fsp->fh->fd != -1) {
6629 /* Open file handle. */
6630 /* Only change if needed. */
6631 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6632 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6633 return map_nt_error_from_unix(errno);
6636 /* But always update the time. */
6638 * This is equivalent to a write. Ensure it's seen immediately
6639 * if there are no pending writes.
6641 trigger_write_time_update_immediate(fsp);
6642 return NT_STATUS_OK;
6645 /* Pathname or stat or directory file. */
6646 status = SMB_VFS_CREATE_FILE(
6647 conn, /* conn */
6648 req, /* req */
6649 0, /* root_dir_fid */
6650 smb_fname, /* fname */
6651 FILE_WRITE_DATA, /* access_mask */
6652 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6653 FILE_SHARE_DELETE),
6654 FILE_OPEN, /* create_disposition*/
6655 0, /* create_options */
6656 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6657 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6658 0, /* allocation_size */
6659 0, /* private_flags */
6660 NULL, /* sd */
6661 NULL, /* ea_list */
6662 &new_fsp, /* result */
6663 NULL); /* pinfo */
6665 if (!NT_STATUS_IS_OK(status)) {
6666 /* NB. We check for open_was_deferred in the caller. */
6667 return status;
6670 /* Only change if needed. */
6671 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6672 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6673 status = map_nt_error_from_unix(errno);
6674 close_file(req, new_fsp, NORMAL_CLOSE);
6675 return status;
6679 /* Changing the allocation size should set the last mod time. */
6681 * This is equivalent to a write. Ensure it's seen immediately
6682 * if there are no pending writes.
6684 trigger_write_time_update_immediate(new_fsp);
6686 close_file(req, new_fsp, NORMAL_CLOSE);
6687 return NT_STATUS_OK;
6690 /****************************************************************************
6691 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6692 ****************************************************************************/
6694 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6695 struct smb_request *req,
6696 const char *pdata,
6697 int total_data,
6698 files_struct *fsp,
6699 const struct smb_filename *smb_fname,
6700 bool fail_after_createfile)
6702 SMB_OFF_T size;
6704 if (total_data < 8) {
6705 return NT_STATUS_INVALID_PARAMETER;
6708 size = IVAL(pdata,0);
6709 #ifdef LARGE_SMB_OFF_T
6710 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6711 #else /* LARGE_SMB_OFF_T */
6712 if (IVAL(pdata,4) != 0) {
6713 /* more than 32 bits? */
6714 return NT_STATUS_INVALID_PARAMETER;
6716 #endif /* LARGE_SMB_OFF_T */
6717 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6718 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6719 (double)size));
6721 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6722 return NT_STATUS_ACCESS_DENIED;
6725 return smb_set_file_size(conn, req,
6726 fsp,
6727 smb_fname,
6728 &smb_fname->st,
6729 size,
6730 fail_after_createfile);
6733 /****************************************************************************
6734 Allow a UNIX info mknod.
6735 ****************************************************************************/
6737 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6738 const char *pdata,
6739 int total_data,
6740 const struct smb_filename *smb_fname)
6742 uint32 file_type = IVAL(pdata,56);
6743 #if defined(HAVE_MAKEDEV)
6744 uint32 dev_major = IVAL(pdata,60);
6745 uint32 dev_minor = IVAL(pdata,68);
6746 #endif
6747 SMB_DEV_T dev = (SMB_DEV_T)0;
6748 uint32 raw_unixmode = IVAL(pdata,84);
6749 NTSTATUS status;
6750 mode_t unixmode;
6752 if (total_data < 100) {
6753 return NT_STATUS_INVALID_PARAMETER;
6756 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6757 PERM_NEW_FILE, &unixmode);
6758 if (!NT_STATUS_IS_OK(status)) {
6759 return status;
6762 #if defined(HAVE_MAKEDEV)
6763 dev = makedev(dev_major, dev_minor);
6764 #endif
6766 switch (file_type) {
6767 #if defined(S_IFIFO)
6768 case UNIX_TYPE_FIFO:
6769 unixmode |= S_IFIFO;
6770 break;
6771 #endif
6772 #if defined(S_IFSOCK)
6773 case UNIX_TYPE_SOCKET:
6774 unixmode |= S_IFSOCK;
6775 break;
6776 #endif
6777 #if defined(S_IFCHR)
6778 case UNIX_TYPE_CHARDEV:
6779 unixmode |= S_IFCHR;
6780 break;
6781 #endif
6782 #if defined(S_IFBLK)
6783 case UNIX_TYPE_BLKDEV:
6784 unixmode |= S_IFBLK;
6785 break;
6786 #endif
6787 default:
6788 return NT_STATUS_INVALID_PARAMETER;
6791 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6792 "%.0f mode 0%o for file %s\n", (double)dev,
6793 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6795 /* Ok - do the mknod. */
6796 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6797 return map_nt_error_from_unix(errno);
6800 /* If any of the other "set" calls fail we
6801 * don't want to end up with a half-constructed mknod.
6804 if (lp_inherit_perms(SNUM(conn))) {
6805 char *parent;
6806 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6807 &parent, NULL)) {
6808 return NT_STATUS_NO_MEMORY;
6810 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6811 unixmode);
6812 TALLOC_FREE(parent);
6815 return NT_STATUS_OK;
6818 /****************************************************************************
6819 Deal with SMB_SET_FILE_UNIX_BASIC.
6820 ****************************************************************************/
6822 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6823 struct smb_request *req,
6824 const char *pdata,
6825 int total_data,
6826 files_struct *fsp,
6827 const struct smb_filename *smb_fname)
6829 struct smb_file_time ft;
6830 uint32 raw_unixmode;
6831 mode_t unixmode;
6832 SMB_OFF_T size = 0;
6833 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6834 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6835 NTSTATUS status = NT_STATUS_OK;
6836 bool delete_on_fail = False;
6837 enum perm_type ptype;
6838 files_struct *all_fsps = NULL;
6839 bool modify_mtime = true;
6840 struct file_id id;
6841 struct smb_filename *smb_fname_tmp = NULL;
6842 SMB_STRUCT_STAT sbuf;
6844 ZERO_STRUCT(ft);
6846 if (total_data < 100) {
6847 return NT_STATUS_INVALID_PARAMETER;
6850 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6851 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6852 size=IVAL(pdata,0); /* first 8 Bytes are size */
6853 #ifdef LARGE_SMB_OFF_T
6854 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6855 #else /* LARGE_SMB_OFF_T */
6856 if (IVAL(pdata,4) != 0) {
6857 /* more than 32 bits? */
6858 return NT_STATUS_INVALID_PARAMETER;
6860 #endif /* LARGE_SMB_OFF_T */
6863 ft.atime = interpret_long_date(pdata+24); /* access_time */
6864 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6865 set_owner = (uid_t)IVAL(pdata,40);
6866 set_grp = (gid_t)IVAL(pdata,48);
6867 raw_unixmode = IVAL(pdata,84);
6869 if (VALID_STAT(smb_fname->st)) {
6870 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6871 ptype = PERM_EXISTING_DIR;
6872 } else {
6873 ptype = PERM_EXISTING_FILE;
6875 } else {
6876 ptype = PERM_NEW_FILE;
6879 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6880 ptype, &unixmode);
6881 if (!NT_STATUS_IS_OK(status)) {
6882 return status;
6885 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6886 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6887 smb_fname_str_dbg(smb_fname), (double)size,
6888 (unsigned int)set_owner, (unsigned int)set_grp,
6889 (int)raw_unixmode));
6891 sbuf = smb_fname->st;
6893 if (!VALID_STAT(sbuf)) {
6895 * The only valid use of this is to create character and block
6896 * devices, and named pipes. This is deprecated (IMHO) and
6897 * a new info level should be used for mknod. JRA.
6900 status = smb_unix_mknod(conn,
6901 pdata,
6902 total_data,
6903 smb_fname);
6904 if (!NT_STATUS_IS_OK(status)) {
6905 return status;
6908 status = copy_smb_filename(talloc_tos(), smb_fname,
6909 &smb_fname_tmp);
6910 if (!NT_STATUS_IS_OK(status)) {
6911 return status;
6914 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6915 status = map_nt_error_from_unix(errno);
6916 TALLOC_FREE(smb_fname_tmp);
6917 SMB_VFS_UNLINK(conn, smb_fname);
6918 return status;
6921 sbuf = smb_fname_tmp->st;
6922 smb_fname = smb_fname_tmp;
6924 /* Ensure we don't try and change anything else. */
6925 raw_unixmode = SMB_MODE_NO_CHANGE;
6926 size = get_file_size_stat(&sbuf);
6927 ft.atime = sbuf.st_ex_atime;
6928 ft.mtime = sbuf.st_ex_mtime;
6930 * We continue here as we might want to change the
6931 * owner uid/gid.
6933 delete_on_fail = True;
6936 #if 1
6937 /* Horrible backwards compatibility hack as an old server bug
6938 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6939 * */
6941 if (!size) {
6942 size = get_file_size_stat(&sbuf);
6944 #endif
6947 * Deal with the UNIX specific mode set.
6950 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6951 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6952 "setting mode 0%o for file %s\n",
6953 (unsigned int)unixmode,
6954 smb_fname_str_dbg(smb_fname)));
6955 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6956 return map_nt_error_from_unix(errno);
6961 * Deal with the UNIX specific uid set.
6964 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6965 (sbuf.st_ex_uid != set_owner)) {
6966 int ret;
6968 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6969 "changing owner %u for path %s\n",
6970 (unsigned int)set_owner,
6971 smb_fname_str_dbg(smb_fname)));
6973 if (S_ISLNK(sbuf.st_ex_mode)) {
6974 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6975 set_owner, (gid_t)-1);
6976 } else {
6977 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6978 set_owner, (gid_t)-1);
6981 if (ret != 0) {
6982 status = map_nt_error_from_unix(errno);
6983 if (delete_on_fail) {
6984 SMB_VFS_UNLINK(conn, smb_fname);
6986 return status;
6991 * Deal with the UNIX specific gid set.
6994 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6995 (sbuf.st_ex_gid != set_grp)) {
6996 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6997 "changing group %u for file %s\n",
6998 (unsigned int)set_owner,
6999 smb_fname_str_dbg(smb_fname)));
7000 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7001 set_grp) != 0) {
7002 status = map_nt_error_from_unix(errno);
7003 if (delete_on_fail) {
7004 SMB_VFS_UNLINK(conn, smb_fname);
7006 return status;
7010 /* Deal with any size changes. */
7012 status = smb_set_file_size(conn, req,
7013 fsp,
7014 smb_fname,
7015 &sbuf,
7016 size,
7017 false);
7018 if (!NT_STATUS_IS_OK(status)) {
7019 return status;
7022 /* Deal with any time changes. */
7023 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7024 /* No change, don't cancel anything. */
7025 return status;
7028 id = vfs_file_id_from_sbuf(conn, &sbuf);
7029 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7030 all_fsps = file_find_di_next(all_fsps)) {
7032 * We're setting the time explicitly for UNIX.
7033 * Cancel any pending changes over all handles.
7035 all_fsps->update_write_time_on_close = false;
7036 TALLOC_FREE(all_fsps->update_write_time_event);
7040 * Override the "setting_write_time"
7041 * parameter here as it almost does what
7042 * we need. Just remember if we modified
7043 * mtime and send the notify ourselves.
7045 if (null_timespec(ft.mtime)) {
7046 modify_mtime = false;
7049 status = smb_set_file_time(conn,
7050 fsp,
7051 smb_fname,
7052 &ft,
7053 false);
7054 if (modify_mtime) {
7055 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7056 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7058 return status;
7061 /****************************************************************************
7062 Deal with SMB_SET_FILE_UNIX_INFO2.
7063 ****************************************************************************/
7065 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7066 struct smb_request *req,
7067 const char *pdata,
7068 int total_data,
7069 files_struct *fsp,
7070 const struct smb_filename *smb_fname)
7072 NTSTATUS status;
7073 uint32 smb_fflags;
7074 uint32 smb_fmask;
7076 if (total_data < 116) {
7077 return NT_STATUS_INVALID_PARAMETER;
7080 /* Start by setting all the fields that are common between UNIX_BASIC
7081 * and UNIX_INFO2.
7083 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7084 fsp, smb_fname);
7085 if (!NT_STATUS_IS_OK(status)) {
7086 return status;
7089 smb_fflags = IVAL(pdata, 108);
7090 smb_fmask = IVAL(pdata, 112);
7092 /* NB: We should only attempt to alter the file flags if the client
7093 * sends a non-zero mask.
7095 if (smb_fmask != 0) {
7096 int stat_fflags = 0;
7098 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7099 smb_fmask, &stat_fflags)) {
7100 /* Client asked to alter a flag we don't understand. */
7101 return NT_STATUS_INVALID_PARAMETER;
7104 if (fsp && fsp->fh->fd != -1) {
7105 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7106 return NT_STATUS_NOT_SUPPORTED;
7107 } else {
7108 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7109 stat_fflags) != 0) {
7110 return map_nt_error_from_unix(errno);
7115 /* XXX: need to add support for changing the create_time here. You
7116 * can do this for paths on Darwin with setattrlist(2). The right way
7117 * to hook this up is probably by extending the VFS utimes interface.
7120 return NT_STATUS_OK;
7123 /****************************************************************************
7124 Create a directory with POSIX semantics.
7125 ****************************************************************************/
7127 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7128 struct smb_request *req,
7129 char **ppdata,
7130 int total_data,
7131 struct smb_filename *smb_fname,
7132 int *pdata_return_size)
7134 NTSTATUS status = NT_STATUS_OK;
7135 uint32 raw_unixmode = 0;
7136 uint32 mod_unixmode = 0;
7137 mode_t unixmode = (mode_t)0;
7138 files_struct *fsp = NULL;
7139 uint16 info_level_return = 0;
7140 int info;
7141 char *pdata = *ppdata;
7143 if (total_data < 18) {
7144 return NT_STATUS_INVALID_PARAMETER;
7147 raw_unixmode = IVAL(pdata,8);
7148 /* Next 4 bytes are not yet defined. */
7150 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7151 PERM_NEW_DIR, &unixmode);
7152 if (!NT_STATUS_IS_OK(status)) {
7153 return status;
7156 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7158 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7159 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7161 status = SMB_VFS_CREATE_FILE(
7162 conn, /* conn */
7163 req, /* req */
7164 0, /* root_dir_fid */
7165 smb_fname, /* fname */
7166 FILE_READ_ATTRIBUTES, /* access_mask */
7167 FILE_SHARE_NONE, /* share_access */
7168 FILE_CREATE, /* create_disposition*/
7169 FILE_DIRECTORY_FILE, /* create_options */
7170 mod_unixmode, /* file_attributes */
7171 0, /* oplock_request */
7172 0, /* allocation_size */
7173 0, /* private_flags */
7174 NULL, /* sd */
7175 NULL, /* ea_list */
7176 &fsp, /* result */
7177 &info); /* pinfo */
7179 if (NT_STATUS_IS_OK(status)) {
7180 close_file(req, fsp, NORMAL_CLOSE);
7183 info_level_return = SVAL(pdata,16);
7185 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7186 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7187 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7188 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7189 } else {
7190 *pdata_return_size = 12;
7193 /* Realloc the data size */
7194 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7195 if (*ppdata == NULL) {
7196 *pdata_return_size = 0;
7197 return NT_STATUS_NO_MEMORY;
7199 pdata = *ppdata;
7201 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7202 SSVAL(pdata,2,0); /* No fnum. */
7203 SIVAL(pdata,4,info); /* Was directory created. */
7205 switch (info_level_return) {
7206 case SMB_QUERY_FILE_UNIX_BASIC:
7207 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7208 SSVAL(pdata,10,0); /* Padding. */
7209 store_file_unix_basic(conn, pdata + 12, fsp,
7210 &smb_fname->st);
7211 break;
7212 case SMB_QUERY_FILE_UNIX_INFO2:
7213 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7214 SSVAL(pdata,10,0); /* Padding. */
7215 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7216 &smb_fname->st);
7217 break;
7218 default:
7219 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7220 SSVAL(pdata,10,0); /* Padding. */
7221 break;
7224 return status;
7227 /****************************************************************************
7228 Open/Create a file with POSIX semantics.
7229 ****************************************************************************/
7231 static NTSTATUS smb_posix_open(connection_struct *conn,
7232 struct smb_request *req,
7233 char **ppdata,
7234 int total_data,
7235 struct smb_filename *smb_fname,
7236 int *pdata_return_size)
7238 bool extended_oplock_granted = False;
7239 char *pdata = *ppdata;
7240 uint32 flags = 0;
7241 uint32 wire_open_mode = 0;
7242 uint32 raw_unixmode = 0;
7243 uint32 mod_unixmode = 0;
7244 uint32 create_disp = 0;
7245 uint32 access_mask = 0;
7246 uint32 create_options = 0;
7247 NTSTATUS status = NT_STATUS_OK;
7248 mode_t unixmode = (mode_t)0;
7249 files_struct *fsp = NULL;
7250 int oplock_request = 0;
7251 int info = 0;
7252 uint16 info_level_return = 0;
7254 if (total_data < 18) {
7255 return NT_STATUS_INVALID_PARAMETER;
7258 flags = IVAL(pdata,0);
7259 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7260 if (oplock_request) {
7261 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7264 wire_open_mode = IVAL(pdata,4);
7266 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7267 return smb_posix_mkdir(conn, req,
7268 ppdata,
7269 total_data,
7270 smb_fname,
7271 pdata_return_size);
7274 switch (wire_open_mode & SMB_ACCMODE) {
7275 case SMB_O_RDONLY:
7276 access_mask = FILE_READ_DATA;
7277 break;
7278 case SMB_O_WRONLY:
7279 access_mask = FILE_WRITE_DATA;
7280 break;
7281 case SMB_O_RDWR:
7282 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7283 break;
7284 default:
7285 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7286 (unsigned int)wire_open_mode ));
7287 return NT_STATUS_INVALID_PARAMETER;
7290 wire_open_mode &= ~SMB_ACCMODE;
7292 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7293 create_disp = FILE_CREATE;
7294 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7295 create_disp = FILE_OVERWRITE_IF;
7296 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7297 create_disp = FILE_OPEN_IF;
7298 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7299 create_disp = FILE_OPEN;
7300 } else {
7301 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7302 (unsigned int)wire_open_mode ));
7303 return NT_STATUS_INVALID_PARAMETER;
7306 raw_unixmode = IVAL(pdata,8);
7307 /* Next 4 bytes are not yet defined. */
7309 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7310 (VALID_STAT(smb_fname->st) ?
7311 PERM_EXISTING_FILE : PERM_NEW_FILE),
7312 &unixmode);
7314 if (!NT_STATUS_IS_OK(status)) {
7315 return status;
7318 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7320 if (wire_open_mode & SMB_O_SYNC) {
7321 create_options |= FILE_WRITE_THROUGH;
7323 if (wire_open_mode & SMB_O_APPEND) {
7324 access_mask |= FILE_APPEND_DATA;
7326 if (wire_open_mode & SMB_O_DIRECT) {
7327 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7330 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7331 smb_fname_str_dbg(smb_fname),
7332 (unsigned int)wire_open_mode,
7333 (unsigned int)unixmode ));
7335 status = SMB_VFS_CREATE_FILE(
7336 conn, /* conn */
7337 req, /* req */
7338 0, /* root_dir_fid */
7339 smb_fname, /* fname */
7340 access_mask, /* access_mask */
7341 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7342 FILE_SHARE_DELETE),
7343 create_disp, /* create_disposition*/
7344 FILE_NON_DIRECTORY_FILE, /* create_options */
7345 mod_unixmode, /* file_attributes */
7346 oplock_request, /* oplock_request */
7347 0, /* allocation_size */
7348 0, /* private_flags */
7349 NULL, /* sd */
7350 NULL, /* ea_list */
7351 &fsp, /* result */
7352 &info); /* pinfo */
7354 if (!NT_STATUS_IS_OK(status)) {
7355 return status;
7358 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7359 extended_oplock_granted = True;
7362 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7363 extended_oplock_granted = True;
7366 info_level_return = SVAL(pdata,16);
7368 /* Allocate the correct return size. */
7370 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7371 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7372 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7373 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7374 } else {
7375 *pdata_return_size = 12;
7378 /* Realloc the data size */
7379 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7380 if (*ppdata == NULL) {
7381 close_file(req, fsp, ERROR_CLOSE);
7382 *pdata_return_size = 0;
7383 return NT_STATUS_NO_MEMORY;
7385 pdata = *ppdata;
7387 if (extended_oplock_granted) {
7388 if (flags & REQUEST_BATCH_OPLOCK) {
7389 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7390 } else {
7391 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7393 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7394 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7395 } else {
7396 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7399 SSVAL(pdata,2,fsp->fnum);
7400 SIVAL(pdata,4,info); /* Was file created etc. */
7402 switch (info_level_return) {
7403 case SMB_QUERY_FILE_UNIX_BASIC:
7404 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7405 SSVAL(pdata,10,0); /* padding. */
7406 store_file_unix_basic(conn, pdata + 12, fsp,
7407 &smb_fname->st);
7408 break;
7409 case SMB_QUERY_FILE_UNIX_INFO2:
7410 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7411 SSVAL(pdata,10,0); /* padding. */
7412 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7413 &smb_fname->st);
7414 break;
7415 default:
7416 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7417 SSVAL(pdata,10,0); /* padding. */
7418 break;
7420 return NT_STATUS_OK;
7423 /****************************************************************************
7424 Delete a file with POSIX semantics.
7425 ****************************************************************************/
7427 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7428 struct smb_request *req,
7429 const char *pdata,
7430 int total_data,
7431 struct smb_filename *smb_fname)
7433 NTSTATUS status = NT_STATUS_OK;
7434 files_struct *fsp = NULL;
7435 uint16 flags = 0;
7436 char del = 1;
7437 int info = 0;
7438 int create_options = 0;
7439 int i;
7440 struct share_mode_lock *lck = NULL;
7442 if (total_data < 2) {
7443 return NT_STATUS_INVALID_PARAMETER;
7446 flags = SVAL(pdata,0);
7448 if (!VALID_STAT(smb_fname->st)) {
7449 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7452 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7453 !VALID_STAT_OF_DIR(smb_fname->st)) {
7454 return NT_STATUS_NOT_A_DIRECTORY;
7457 DEBUG(10,("smb_posix_unlink: %s %s\n",
7458 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7459 smb_fname_str_dbg(smb_fname)));
7461 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7462 create_options |= FILE_DIRECTORY_FILE;
7465 status = SMB_VFS_CREATE_FILE(
7466 conn, /* conn */
7467 req, /* req */
7468 0, /* root_dir_fid */
7469 smb_fname, /* fname */
7470 DELETE_ACCESS, /* access_mask */
7471 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7472 FILE_SHARE_DELETE),
7473 FILE_OPEN, /* create_disposition*/
7474 create_options, /* create_options */
7475 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7476 0, /* oplock_request */
7477 0, /* allocation_size */
7478 0, /* private_flags */
7479 NULL, /* sd */
7480 NULL, /* ea_list */
7481 &fsp, /* result */
7482 &info); /* pinfo */
7484 if (!NT_STATUS_IS_OK(status)) {
7485 return status;
7489 * Don't lie to client. If we can't really delete due to
7490 * non-POSIX opens return SHARING_VIOLATION.
7493 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7494 NULL);
7495 if (lck == NULL) {
7496 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7497 "lock for file %s\n", fsp_str_dbg(fsp)));
7498 close_file(req, fsp, NORMAL_CLOSE);
7499 return NT_STATUS_INVALID_PARAMETER;
7503 * See if others still have the file open. If this is the case, then
7504 * don't delete. If all opens are POSIX delete we can set the delete
7505 * on close disposition.
7507 for (i=0; i<lck->num_share_modes; i++) {
7508 struct share_mode_entry *e = &lck->share_modes[i];
7509 if (is_valid_share_mode_entry(e)) {
7510 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7511 continue;
7513 /* Fail with sharing violation. */
7514 close_file(req, fsp, NORMAL_CLOSE);
7515 TALLOC_FREE(lck);
7516 return NT_STATUS_SHARING_VIOLATION;
7521 * Set the delete on close.
7523 status = smb_set_file_disposition_info(conn,
7524 &del,
7526 fsp,
7527 smb_fname);
7529 if (!NT_STATUS_IS_OK(status)) {
7530 close_file(req, fsp, NORMAL_CLOSE);
7531 TALLOC_FREE(lck);
7532 return status;
7534 TALLOC_FREE(lck);
7535 return close_file(req, fsp, NORMAL_CLOSE);
7538 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7539 struct smb_request *req,
7540 TALLOC_CTX *mem_ctx,
7541 uint16_t info_level,
7542 files_struct *fsp,
7543 struct smb_filename *smb_fname,
7544 char **ppdata, int total_data,
7545 int *ret_data_size)
7547 char *pdata = *ppdata;
7548 NTSTATUS status = NT_STATUS_OK;
7549 int data_return_size = 0;
7551 *ret_data_size = 0;
7553 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7554 return NT_STATUS_INVALID_LEVEL;
7557 if (!CAN_WRITE(conn)) {
7558 /* Allow POSIX opens. The open path will deny
7559 * any non-readonly opens. */
7560 if (info_level != SMB_POSIX_PATH_OPEN) {
7561 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7565 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7566 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7567 fsp ? fsp->fnum : -1, info_level, total_data));
7569 switch (info_level) {
7571 case SMB_INFO_STANDARD:
7573 status = smb_set_info_standard(conn,
7574 pdata,
7575 total_data,
7576 fsp,
7577 smb_fname);
7578 break;
7581 case SMB_INFO_SET_EA:
7583 status = smb_info_set_ea(conn,
7584 pdata,
7585 total_data,
7586 fsp,
7587 smb_fname);
7588 break;
7591 case SMB_SET_FILE_BASIC_INFO:
7592 case SMB_FILE_BASIC_INFORMATION:
7594 status = smb_set_file_basic_info(conn,
7595 pdata,
7596 total_data,
7597 fsp,
7598 smb_fname);
7599 break;
7602 case SMB_FILE_ALLOCATION_INFORMATION:
7603 case SMB_SET_FILE_ALLOCATION_INFO:
7605 status = smb_set_file_allocation_info(conn, req,
7606 pdata,
7607 total_data,
7608 fsp,
7609 smb_fname);
7610 break;
7613 case SMB_FILE_END_OF_FILE_INFORMATION:
7614 case SMB_SET_FILE_END_OF_FILE_INFO:
7617 * XP/Win7 both fail after the createfile with
7618 * SMB_SET_FILE_END_OF_FILE_INFO but not
7619 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7620 * The level is known here, so pass it down
7621 * appropriately.
7623 bool should_fail =
7624 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7626 status = smb_set_file_end_of_file_info(conn, req,
7627 pdata,
7628 total_data,
7629 fsp,
7630 smb_fname,
7631 should_fail);
7632 break;
7635 case SMB_FILE_DISPOSITION_INFORMATION:
7636 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7638 #if 0
7639 /* JRA - We used to just ignore this on a path ?
7640 * Shouldn't this be invalid level on a pathname
7641 * based call ?
7643 if (tran_call != TRANSACT2_SETFILEINFO) {
7644 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7646 #endif
7647 status = smb_set_file_disposition_info(conn,
7648 pdata,
7649 total_data,
7650 fsp,
7651 smb_fname);
7652 break;
7655 case SMB_FILE_POSITION_INFORMATION:
7657 status = smb_file_position_information(conn,
7658 pdata,
7659 total_data,
7660 fsp);
7661 break;
7664 case SMB_FILE_FULL_EA_INFORMATION:
7666 status = smb_set_file_full_ea_info(conn,
7667 pdata,
7668 total_data,
7669 fsp);
7670 break;
7673 /* From tridge Samba4 :
7674 * MODE_INFORMATION in setfileinfo (I have no
7675 * idea what "mode information" on a file is - it takes a value of 0,
7676 * 2, 4 or 6. What could it be?).
7679 case SMB_FILE_MODE_INFORMATION:
7681 status = smb_file_mode_information(conn,
7682 pdata,
7683 total_data);
7684 break;
7688 * CIFS UNIX extensions.
7691 case SMB_SET_FILE_UNIX_BASIC:
7693 status = smb_set_file_unix_basic(conn, req,
7694 pdata,
7695 total_data,
7696 fsp,
7697 smb_fname);
7698 break;
7701 case SMB_SET_FILE_UNIX_INFO2:
7703 status = smb_set_file_unix_info2(conn, req,
7704 pdata,
7705 total_data,
7706 fsp,
7707 smb_fname);
7708 break;
7711 case SMB_SET_FILE_UNIX_LINK:
7713 if (fsp) {
7714 /* We must have a pathname for this. */
7715 return NT_STATUS_INVALID_LEVEL;
7717 status = smb_set_file_unix_link(conn, req, pdata,
7718 total_data, smb_fname);
7719 break;
7722 case SMB_SET_FILE_UNIX_HLINK:
7724 if (fsp) {
7725 /* We must have a pathname for this. */
7726 return NT_STATUS_INVALID_LEVEL;
7728 status = smb_set_file_unix_hlink(conn, req,
7729 pdata, total_data,
7730 smb_fname);
7731 break;
7734 case SMB_FILE_RENAME_INFORMATION:
7736 status = smb_file_rename_information(conn, req,
7737 pdata, total_data,
7738 fsp, smb_fname);
7739 break;
7742 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7744 /* SMB2 rename information. */
7745 status = smb2_file_rename_information(conn, req,
7746 pdata, total_data,
7747 fsp, smb_fname);
7748 break;
7751 case SMB_FILE_LINK_INFORMATION:
7753 status = smb_file_link_information(conn, req,
7754 pdata, total_data,
7755 fsp, smb_fname);
7756 break;
7759 #if defined(HAVE_POSIX_ACLS)
7760 case SMB_SET_POSIX_ACL:
7762 status = smb_set_posix_acl(conn,
7763 pdata,
7764 total_data,
7765 fsp,
7766 smb_fname);
7767 break;
7769 #endif
7771 case SMB_SET_POSIX_LOCK:
7773 if (!fsp) {
7774 return NT_STATUS_INVALID_LEVEL;
7776 status = smb_set_posix_lock(conn, req,
7777 pdata, total_data, fsp);
7778 break;
7781 case SMB_POSIX_PATH_OPEN:
7783 if (fsp) {
7784 /* We must have a pathname for this. */
7785 return NT_STATUS_INVALID_LEVEL;
7788 status = smb_posix_open(conn, req,
7789 ppdata,
7790 total_data,
7791 smb_fname,
7792 &data_return_size);
7793 break;
7796 case SMB_POSIX_PATH_UNLINK:
7798 if (fsp) {
7799 /* We must have a pathname for this. */
7800 return NT_STATUS_INVALID_LEVEL;
7803 status = smb_posix_unlink(conn, req,
7804 pdata,
7805 total_data,
7806 smb_fname);
7807 break;
7810 default:
7811 return NT_STATUS_INVALID_LEVEL;
7814 if (!NT_STATUS_IS_OK(status)) {
7815 return status;
7818 *ret_data_size = data_return_size;
7819 return NT_STATUS_OK;
7822 /****************************************************************************
7823 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7824 ****************************************************************************/
7826 static void call_trans2setfilepathinfo(connection_struct *conn,
7827 struct smb_request *req,
7828 unsigned int tran_call,
7829 char **pparams, int total_params,
7830 char **ppdata, int total_data,
7831 unsigned int max_data_bytes)
7833 char *params = *pparams;
7834 char *pdata = *ppdata;
7835 uint16 info_level;
7836 struct smb_filename *smb_fname = NULL;
7837 files_struct *fsp = NULL;
7838 NTSTATUS status = NT_STATUS_OK;
7839 int data_return_size = 0;
7841 if (!params) {
7842 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7843 return;
7846 if (tran_call == TRANSACT2_SETFILEINFO) {
7847 if (total_params < 4) {
7848 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7849 return;
7852 fsp = file_fsp(req, SVAL(params,0));
7853 /* Basic check for non-null fsp. */
7854 if (!check_fsp_open(conn, req, fsp)) {
7855 return;
7857 info_level = SVAL(params,2);
7859 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7860 &smb_fname);
7861 if (!NT_STATUS_IS_OK(status)) {
7862 reply_nterror(req, status);
7863 return;
7866 if(fsp->is_directory || fsp->fh->fd == -1) {
7868 * This is actually a SETFILEINFO on a directory
7869 * handle (returned from an NT SMB). NT5.0 seems
7870 * to do this call. JRA.
7872 if (INFO_LEVEL_IS_UNIX(info_level)) {
7873 /* Always do lstat for UNIX calls. */
7874 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7875 DEBUG(3,("call_trans2setfilepathinfo: "
7876 "SMB_VFS_LSTAT of %s failed "
7877 "(%s)\n",
7878 smb_fname_str_dbg(smb_fname),
7879 strerror(errno)));
7880 reply_nterror(req, map_nt_error_from_unix(errno));
7881 return;
7883 } else {
7884 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7885 DEBUG(3,("call_trans2setfilepathinfo: "
7886 "fileinfo of %s failed (%s)\n",
7887 smb_fname_str_dbg(smb_fname),
7888 strerror(errno)));
7889 reply_nterror(req, map_nt_error_from_unix(errno));
7890 return;
7893 } else if (fsp->print_file) {
7895 * Doing a DELETE_ON_CLOSE should cancel a print job.
7897 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7898 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7900 DEBUG(3,("call_trans2setfilepathinfo: "
7901 "Cancelling print job (%s)\n",
7902 fsp_str_dbg(fsp)));
7904 SSVAL(params,0,0);
7905 send_trans2_replies(conn, req, params, 2,
7906 *ppdata, 0,
7907 max_data_bytes);
7908 return;
7909 } else {
7910 reply_nterror(req,
7911 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7912 return;
7914 } else {
7916 * Original code - this is an open file.
7918 if (!check_fsp(conn, req, fsp)) {
7919 return;
7922 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7923 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7924 "of fnum %d failed (%s)\n", fsp->fnum,
7925 strerror(errno)));
7926 reply_nterror(req, map_nt_error_from_unix(errno));
7927 return;
7930 } else {
7931 char *fname = NULL;
7933 /* set path info */
7934 if (total_params < 7) {
7935 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7936 return;
7939 info_level = SVAL(params,0);
7940 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7941 total_params - 6, STR_TERMINATE,
7942 &status);
7943 if (!NT_STATUS_IS_OK(status)) {
7944 reply_nterror(req, status);
7945 return;
7948 status = filename_convert(req, conn,
7949 req->flags2 & FLAGS2_DFS_PATHNAMES,
7950 fname,
7952 NULL,
7953 &smb_fname);
7954 if (!NT_STATUS_IS_OK(status)) {
7955 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7956 reply_botherror(req,
7957 NT_STATUS_PATH_NOT_COVERED,
7958 ERRSRV, ERRbadpath);
7959 return;
7961 reply_nterror(req, status);
7962 return;
7965 if (INFO_LEVEL_IS_UNIX(info_level)) {
7967 * For CIFS UNIX extensions the target name may not exist.
7970 /* Always do lstat for UNIX calls. */
7971 SMB_VFS_LSTAT(conn, smb_fname);
7973 } else if (!VALID_STAT(smb_fname->st) &&
7974 SMB_VFS_STAT(conn, smb_fname)) {
7975 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7976 "%s failed (%s)\n",
7977 smb_fname_str_dbg(smb_fname),
7978 strerror(errno)));
7979 reply_nterror(req, map_nt_error_from_unix(errno));
7980 return;
7984 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7985 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7986 fsp ? fsp->fnum : -1, info_level,total_data));
7988 /* Realloc the parameter size */
7989 *pparams = (char *)SMB_REALLOC(*pparams,2);
7990 if (*pparams == NULL) {
7991 reply_nterror(req, NT_STATUS_NO_MEMORY);
7992 return;
7994 params = *pparams;
7996 SSVAL(params,0,0);
7998 status = smbd_do_setfilepathinfo(conn, req, req,
7999 info_level,
8000 fsp,
8001 smb_fname,
8002 ppdata, total_data,
8003 &data_return_size);
8004 if (!NT_STATUS_IS_OK(status)) {
8005 if (open_was_deferred(req->mid)) {
8006 /* We have re-scheduled this call. */
8007 return;
8009 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8010 /* We have re-scheduled this call. */
8011 return;
8013 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8014 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8015 ERRSRV, ERRbadpath);
8016 return;
8018 if (info_level == SMB_POSIX_PATH_OPEN) {
8019 reply_openerror(req, status);
8020 return;
8023 reply_nterror(req, status);
8024 return;
8027 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8028 max_data_bytes);
8030 return;
8033 /****************************************************************************
8034 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8035 ****************************************************************************/
8037 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8038 char **pparams, int total_params,
8039 char **ppdata, int total_data,
8040 unsigned int max_data_bytes)
8042 struct smb_filename *smb_dname = NULL;
8043 char *params = *pparams;
8044 char *pdata = *ppdata;
8045 char *directory = NULL;
8046 NTSTATUS status = NT_STATUS_OK;
8047 struct ea_list *ea_list = NULL;
8048 TALLOC_CTX *ctx = talloc_tos();
8050 if (!CAN_WRITE(conn)) {
8051 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8052 return;
8055 if (total_params < 5) {
8056 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8057 return;
8060 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8061 total_params - 4, STR_TERMINATE,
8062 &status);
8063 if (!NT_STATUS_IS_OK(status)) {
8064 reply_nterror(req, status);
8065 return;
8068 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8070 status = filename_convert(ctx,
8071 conn,
8072 req->flags2 & FLAGS2_DFS_PATHNAMES,
8073 directory,
8075 NULL,
8076 &smb_dname);
8078 if (!NT_STATUS_IS_OK(status)) {
8079 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8080 reply_botherror(req,
8081 NT_STATUS_PATH_NOT_COVERED,
8082 ERRSRV, ERRbadpath);
8083 return;
8085 reply_nterror(req, status);
8086 return;
8090 * OS/2 workplace shell seems to send SET_EA requests of "null"
8091 * length (4 bytes containing IVAL 4).
8092 * They seem to have no effect. Bug #3212. JRA.
8095 if (total_data && (total_data != 4)) {
8096 /* Any data in this call is an EA list. */
8097 if (total_data < 10) {
8098 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8099 goto out;
8102 if (IVAL(pdata,0) > total_data) {
8103 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8104 IVAL(pdata,0), (unsigned int)total_data));
8105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8106 goto out;
8109 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8110 total_data - 4);
8111 if (!ea_list) {
8112 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8113 goto out;
8116 if (!lp_ea_support(SNUM(conn))) {
8117 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8118 goto out;
8121 /* If total_data == 4 Windows doesn't care what values
8122 * are placed in that field, it just ignores them.
8123 * The System i QNTC IBM SMB client puts bad values here,
8124 * so ignore them. */
8126 status = create_directory(conn, req, smb_dname);
8128 if (!NT_STATUS_IS_OK(status)) {
8129 reply_nterror(req, status);
8130 goto out;
8133 /* Try and set any given EA. */
8134 if (ea_list) {
8135 status = set_ea(conn, NULL, smb_dname, ea_list);
8136 if (!NT_STATUS_IS_OK(status)) {
8137 reply_nterror(req, status);
8138 goto out;
8142 /* Realloc the parameter and data sizes */
8143 *pparams = (char *)SMB_REALLOC(*pparams,2);
8144 if(*pparams == NULL) {
8145 reply_nterror(req, NT_STATUS_NO_MEMORY);
8146 goto out;
8148 params = *pparams;
8150 SSVAL(params,0,0);
8152 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8154 out:
8155 TALLOC_FREE(smb_dname);
8156 return;
8159 /****************************************************************************
8160 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8161 We don't actually do this - we just send a null response.
8162 ****************************************************************************/
8164 static void call_trans2findnotifyfirst(connection_struct *conn,
8165 struct smb_request *req,
8166 char **pparams, int total_params,
8167 char **ppdata, int total_data,
8168 unsigned int max_data_bytes)
8170 char *params = *pparams;
8171 uint16 info_level;
8173 if (total_params < 6) {
8174 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8175 return;
8178 info_level = SVAL(params,4);
8179 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8181 switch (info_level) {
8182 case 1:
8183 case 2:
8184 break;
8185 default:
8186 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8187 return;
8190 /* Realloc the parameter and data sizes */
8191 *pparams = (char *)SMB_REALLOC(*pparams,6);
8192 if (*pparams == NULL) {
8193 reply_nterror(req, NT_STATUS_NO_MEMORY);
8194 return;
8196 params = *pparams;
8198 SSVAL(params,0,fnf_handle);
8199 SSVAL(params,2,0); /* No changes */
8200 SSVAL(params,4,0); /* No EA errors */
8202 fnf_handle++;
8204 if(fnf_handle == 0)
8205 fnf_handle = 257;
8207 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8209 return;
8212 /****************************************************************************
8213 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8214 changes). Currently this does nothing.
8215 ****************************************************************************/
8217 static void call_trans2findnotifynext(connection_struct *conn,
8218 struct smb_request *req,
8219 char **pparams, int total_params,
8220 char **ppdata, int total_data,
8221 unsigned int max_data_bytes)
8223 char *params = *pparams;
8225 DEBUG(3,("call_trans2findnotifynext\n"));
8227 /* Realloc the parameter and data sizes */
8228 *pparams = (char *)SMB_REALLOC(*pparams,4);
8229 if (*pparams == NULL) {
8230 reply_nterror(req, NT_STATUS_NO_MEMORY);
8231 return;
8233 params = *pparams;
8235 SSVAL(params,0,0); /* No changes */
8236 SSVAL(params,2,0); /* No EA errors */
8238 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8240 return;
8243 /****************************************************************************
8244 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8245 ****************************************************************************/
8247 static void call_trans2getdfsreferral(connection_struct *conn,
8248 struct smb_request *req,
8249 char **pparams, int total_params,
8250 char **ppdata, int total_data,
8251 unsigned int max_data_bytes)
8253 char *params = *pparams;
8254 char *pathname = NULL;
8255 int reply_size = 0;
8256 int max_referral_level;
8257 NTSTATUS status = NT_STATUS_OK;
8258 TALLOC_CTX *ctx = talloc_tos();
8260 DEBUG(10,("call_trans2getdfsreferral\n"));
8262 if (total_params < 3) {
8263 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8264 return;
8267 max_referral_level = SVAL(params,0);
8269 if(!lp_host_msdfs()) {
8270 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8271 return;
8274 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8275 total_params - 2, STR_TERMINATE);
8276 if (!pathname) {
8277 reply_nterror(req, NT_STATUS_NOT_FOUND);
8278 return;
8280 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8281 ppdata,&status)) < 0) {
8282 reply_nterror(req, status);
8283 return;
8286 SSVAL(req->inbuf, smb_flg2,
8287 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8288 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8290 return;
8293 #define LMCAT_SPL 0x53
8294 #define LMFUNC_GETJOBID 0x60
8296 /****************************************************************************
8297 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8298 ****************************************************************************/
8300 static void call_trans2ioctl(connection_struct *conn,
8301 struct smb_request *req,
8302 char **pparams, int total_params,
8303 char **ppdata, int total_data,
8304 unsigned int max_data_bytes)
8306 char *pdata = *ppdata;
8307 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8309 /* check for an invalid fid before proceeding */
8311 if (!fsp) {
8312 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8313 return;
8316 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8317 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8318 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8319 if (*ppdata == NULL) {
8320 reply_nterror(req, NT_STATUS_NO_MEMORY);
8321 return;
8323 pdata = *ppdata;
8325 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8326 CAN ACCEPT THIS IN UNICODE. JRA. */
8328 /* Job number */
8329 if (fsp->print_file) {
8330 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8331 } else {
8332 SSVAL(pdata, 0, 0);
8334 srvstr_push(pdata, req->flags2, pdata + 2,
8335 global_myname(), 15,
8336 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8337 srvstr_push(pdata, req->flags2, pdata+18,
8338 lp_servicename(SNUM(conn)), 13,
8339 STR_ASCII|STR_TERMINATE); /* Service name */
8340 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8341 max_data_bytes);
8342 return;
8345 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8346 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8349 /****************************************************************************
8350 Reply to a SMBfindclose (stop trans2 directory search).
8351 ****************************************************************************/
8353 void reply_findclose(struct smb_request *req)
8355 int dptr_num;
8356 struct smbd_server_connection *sconn = req->sconn;
8358 START_PROFILE(SMBfindclose);
8360 if (req->wct < 1) {
8361 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8362 END_PROFILE(SMBfindclose);
8363 return;
8366 dptr_num = SVALS(req->vwv+0, 0);
8368 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8370 dptr_close(sconn, &dptr_num);
8372 reply_outbuf(req, 0, 0);
8374 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8376 END_PROFILE(SMBfindclose);
8377 return;
8380 /****************************************************************************
8381 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8382 ****************************************************************************/
8384 void reply_findnclose(struct smb_request *req)
8386 int dptr_num;
8388 START_PROFILE(SMBfindnclose);
8390 if (req->wct < 1) {
8391 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8392 END_PROFILE(SMBfindnclose);
8393 return;
8396 dptr_num = SVAL(req->vwv+0, 0);
8398 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8400 /* We never give out valid handles for a
8401 findnotifyfirst - so any dptr_num is ok here.
8402 Just ignore it. */
8404 reply_outbuf(req, 0, 0);
8406 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8408 END_PROFILE(SMBfindnclose);
8409 return;
8412 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8413 struct trans_state *state)
8415 if (get_Protocol() >= PROTOCOL_NT1) {
8416 req->flags2 |= 0x40; /* IS_LONG_NAME */
8417 SSVAL(req->inbuf,smb_flg2,req->flags2);
8420 if (conn->encrypt_level == Required && !req->encrypted) {
8421 if (state->call != TRANSACT2_QFSINFO &&
8422 state->call != TRANSACT2_SETFSINFO) {
8423 DEBUG(0,("handle_trans2: encryption required "
8424 "with call 0x%x\n",
8425 (unsigned int)state->call));
8426 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8427 return;
8431 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8433 /* Now we must call the relevant TRANS2 function */
8434 switch(state->call) {
8435 case TRANSACT2_OPEN:
8437 START_PROFILE(Trans2_open);
8438 call_trans2open(conn, req,
8439 &state->param, state->total_param,
8440 &state->data, state->total_data,
8441 state->max_data_return);
8442 END_PROFILE(Trans2_open);
8443 break;
8446 case TRANSACT2_FINDFIRST:
8448 START_PROFILE(Trans2_findfirst);
8449 call_trans2findfirst(conn, req,
8450 &state->param, state->total_param,
8451 &state->data, state->total_data,
8452 state->max_data_return);
8453 END_PROFILE(Trans2_findfirst);
8454 break;
8457 case TRANSACT2_FINDNEXT:
8459 START_PROFILE(Trans2_findnext);
8460 call_trans2findnext(conn, req,
8461 &state->param, state->total_param,
8462 &state->data, state->total_data,
8463 state->max_data_return);
8464 END_PROFILE(Trans2_findnext);
8465 break;
8468 case TRANSACT2_QFSINFO:
8470 START_PROFILE(Trans2_qfsinfo);
8471 call_trans2qfsinfo(conn, req,
8472 &state->param, state->total_param,
8473 &state->data, state->total_data,
8474 state->max_data_return);
8475 END_PROFILE(Trans2_qfsinfo);
8476 break;
8479 case TRANSACT2_SETFSINFO:
8481 START_PROFILE(Trans2_setfsinfo);
8482 call_trans2setfsinfo(conn, req,
8483 &state->param, state->total_param,
8484 &state->data, state->total_data,
8485 state->max_data_return);
8486 END_PROFILE(Trans2_setfsinfo);
8487 break;
8490 case TRANSACT2_QPATHINFO:
8491 case TRANSACT2_QFILEINFO:
8493 START_PROFILE(Trans2_qpathinfo);
8494 call_trans2qfilepathinfo(conn, req, state->call,
8495 &state->param, state->total_param,
8496 &state->data, state->total_data,
8497 state->max_data_return);
8498 END_PROFILE(Trans2_qpathinfo);
8499 break;
8502 case TRANSACT2_SETPATHINFO:
8503 case TRANSACT2_SETFILEINFO:
8505 START_PROFILE(Trans2_setpathinfo);
8506 call_trans2setfilepathinfo(conn, req, state->call,
8507 &state->param, state->total_param,
8508 &state->data, state->total_data,
8509 state->max_data_return);
8510 END_PROFILE(Trans2_setpathinfo);
8511 break;
8514 case TRANSACT2_FINDNOTIFYFIRST:
8516 START_PROFILE(Trans2_findnotifyfirst);
8517 call_trans2findnotifyfirst(conn, req,
8518 &state->param, state->total_param,
8519 &state->data, state->total_data,
8520 state->max_data_return);
8521 END_PROFILE(Trans2_findnotifyfirst);
8522 break;
8525 case TRANSACT2_FINDNOTIFYNEXT:
8527 START_PROFILE(Trans2_findnotifynext);
8528 call_trans2findnotifynext(conn, req,
8529 &state->param, state->total_param,
8530 &state->data, state->total_data,
8531 state->max_data_return);
8532 END_PROFILE(Trans2_findnotifynext);
8533 break;
8536 case TRANSACT2_MKDIR:
8538 START_PROFILE(Trans2_mkdir);
8539 call_trans2mkdir(conn, req,
8540 &state->param, state->total_param,
8541 &state->data, state->total_data,
8542 state->max_data_return);
8543 END_PROFILE(Trans2_mkdir);
8544 break;
8547 case TRANSACT2_GET_DFS_REFERRAL:
8549 START_PROFILE(Trans2_get_dfs_referral);
8550 call_trans2getdfsreferral(conn, req,
8551 &state->param, state->total_param,
8552 &state->data, state->total_data,
8553 state->max_data_return);
8554 END_PROFILE(Trans2_get_dfs_referral);
8555 break;
8558 case TRANSACT2_IOCTL:
8560 START_PROFILE(Trans2_ioctl);
8561 call_trans2ioctl(conn, req,
8562 &state->param, state->total_param,
8563 &state->data, state->total_data,
8564 state->max_data_return);
8565 END_PROFILE(Trans2_ioctl);
8566 break;
8569 default:
8570 /* Error in request */
8571 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8572 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8576 /****************************************************************************
8577 Reply to a SMBtrans2.
8578 ****************************************************************************/
8580 void reply_trans2(struct smb_request *req)
8582 connection_struct *conn = req->conn;
8583 unsigned int dsoff;
8584 unsigned int dscnt;
8585 unsigned int psoff;
8586 unsigned int pscnt;
8587 unsigned int tran_call;
8588 struct trans_state *state;
8589 NTSTATUS result;
8591 START_PROFILE(SMBtrans2);
8593 if (req->wct < 14) {
8594 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8595 END_PROFILE(SMBtrans2);
8596 return;
8599 dsoff = SVAL(req->vwv+12, 0);
8600 dscnt = SVAL(req->vwv+11, 0);
8601 psoff = SVAL(req->vwv+10, 0);
8602 pscnt = SVAL(req->vwv+9, 0);
8603 tran_call = SVAL(req->vwv+14, 0);
8605 result = allow_new_trans(conn->pending_trans, req->mid);
8606 if (!NT_STATUS_IS_OK(result)) {
8607 DEBUG(2, ("Got invalid trans2 request: %s\n",
8608 nt_errstr(result)));
8609 reply_nterror(req, result);
8610 END_PROFILE(SMBtrans2);
8611 return;
8614 if (IS_IPC(conn)) {
8615 switch (tran_call) {
8616 /* List the allowed trans2 calls on IPC$ */
8617 case TRANSACT2_OPEN:
8618 case TRANSACT2_GET_DFS_REFERRAL:
8619 case TRANSACT2_QFILEINFO:
8620 case TRANSACT2_QFSINFO:
8621 case TRANSACT2_SETFSINFO:
8622 break;
8623 default:
8624 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8625 END_PROFILE(SMBtrans2);
8626 return;
8630 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8631 DEBUG(0, ("talloc failed\n"));
8632 reply_nterror(req, NT_STATUS_NO_MEMORY);
8633 END_PROFILE(SMBtrans2);
8634 return;
8637 state->cmd = SMBtrans2;
8639 state->mid = req->mid;
8640 state->vuid = req->vuid;
8641 state->setup_count = SVAL(req->vwv+13, 0);
8642 state->setup = NULL;
8643 state->total_param = SVAL(req->vwv+0, 0);
8644 state->param = NULL;
8645 state->total_data = SVAL(req->vwv+1, 0);
8646 state->data = NULL;
8647 state->max_param_return = SVAL(req->vwv+2, 0);
8648 state->max_data_return = SVAL(req->vwv+3, 0);
8649 state->max_setup_return = SVAL(req->vwv+4, 0);
8650 state->close_on_completion = BITSETW(req->vwv+5, 0);
8651 state->one_way = BITSETW(req->vwv+5, 1);
8653 state->call = tran_call;
8655 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8656 is so as a sanity check */
8657 if (state->setup_count != 1) {
8659 * Need to have rc=0 for ioctl to get job id for OS/2.
8660 * Network printing will fail if function is not successful.
8661 * Similar function in reply.c will be used if protocol
8662 * is LANMAN1.0 instead of LM1.2X002.
8663 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8664 * outbuf doesn't have to be set(only job id is used).
8666 if ( (state->setup_count == 4)
8667 && (tran_call == TRANSACT2_IOCTL)
8668 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8669 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8670 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8671 } else {
8672 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8673 DEBUG(2,("Transaction is %d\n",tran_call));
8674 TALLOC_FREE(state);
8675 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8676 END_PROFILE(SMBtrans2);
8677 return;
8681 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8682 goto bad_param;
8684 if (state->total_data) {
8686 if (trans_oob(state->total_data, 0, dscnt)
8687 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8688 goto bad_param;
8691 /* Can't use talloc here, the core routines do realloc on the
8692 * params and data. */
8693 state->data = (char *)SMB_MALLOC(state->total_data);
8694 if (state->data == NULL) {
8695 DEBUG(0,("reply_trans2: data malloc fail for %u "
8696 "bytes !\n", (unsigned int)state->total_data));
8697 TALLOC_FREE(state);
8698 reply_nterror(req, NT_STATUS_NO_MEMORY);
8699 END_PROFILE(SMBtrans2);
8700 return;
8703 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8706 if (state->total_param) {
8708 if (trans_oob(state->total_param, 0, pscnt)
8709 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8710 goto bad_param;
8713 /* Can't use talloc here, the core routines do realloc on the
8714 * params and data. */
8715 state->param = (char *)SMB_MALLOC(state->total_param);
8716 if (state->param == NULL) {
8717 DEBUG(0,("reply_trans: param malloc fail for %u "
8718 "bytes !\n", (unsigned int)state->total_param));
8719 SAFE_FREE(state->data);
8720 TALLOC_FREE(state);
8721 reply_nterror(req, NT_STATUS_NO_MEMORY);
8722 END_PROFILE(SMBtrans2);
8723 return;
8726 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8729 state->received_data = dscnt;
8730 state->received_param = pscnt;
8732 if ((state->received_param == state->total_param) &&
8733 (state->received_data == state->total_data)) {
8735 handle_trans2(conn, req, state);
8737 SAFE_FREE(state->data);
8738 SAFE_FREE(state->param);
8739 TALLOC_FREE(state);
8740 END_PROFILE(SMBtrans2);
8741 return;
8744 DLIST_ADD(conn->pending_trans, state);
8746 /* We need to send an interim response then receive the rest
8747 of the parameter/data bytes */
8748 reply_outbuf(req, 0, 0);
8749 show_msg((char *)req->outbuf);
8750 END_PROFILE(SMBtrans2);
8751 return;
8753 bad_param:
8755 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8756 SAFE_FREE(state->data);
8757 SAFE_FREE(state->param);
8758 TALLOC_FREE(state);
8759 END_PROFILE(SMBtrans2);
8760 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8764 /****************************************************************************
8765 Reply to a SMBtranss2
8766 ****************************************************************************/
8768 void reply_transs2(struct smb_request *req)
8770 connection_struct *conn = req->conn;
8771 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8772 struct trans_state *state;
8774 START_PROFILE(SMBtranss2);
8776 show_msg((char *)req->inbuf);
8778 if (req->wct < 8) {
8779 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8780 END_PROFILE(SMBtranss2);
8781 return;
8784 for (state = conn->pending_trans; state != NULL;
8785 state = state->next) {
8786 if (state->mid == req->mid) {
8787 break;
8791 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8792 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8793 END_PROFILE(SMBtranss2);
8794 return;
8797 /* Revise state->total_param and state->total_data in case they have
8798 changed downwards */
8800 if (SVAL(req->vwv+0, 0) < state->total_param)
8801 state->total_param = SVAL(req->vwv+0, 0);
8802 if (SVAL(req->vwv+1, 0) < state->total_data)
8803 state->total_data = SVAL(req->vwv+1, 0);
8805 pcnt = SVAL(req->vwv+2, 0);
8806 poff = SVAL(req->vwv+3, 0);
8807 pdisp = SVAL(req->vwv+4, 0);
8809 dcnt = SVAL(req->vwv+5, 0);
8810 doff = SVAL(req->vwv+6, 0);
8811 ddisp = SVAL(req->vwv+7, 0);
8813 state->received_param += pcnt;
8814 state->received_data += dcnt;
8816 if ((state->received_data > state->total_data) ||
8817 (state->received_param > state->total_param))
8818 goto bad_param;
8820 if (pcnt) {
8821 if (trans_oob(state->total_param, pdisp, pcnt)
8822 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8823 goto bad_param;
8825 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8828 if (dcnt) {
8829 if (trans_oob(state->total_data, ddisp, dcnt)
8830 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8831 goto bad_param;
8833 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8836 if ((state->received_param < state->total_param) ||
8837 (state->received_data < state->total_data)) {
8838 END_PROFILE(SMBtranss2);
8839 return;
8842 handle_trans2(conn, req, state);
8844 DLIST_REMOVE(conn->pending_trans, state);
8845 SAFE_FREE(state->data);
8846 SAFE_FREE(state->param);
8847 TALLOC_FREE(state);
8849 END_PROFILE(SMBtranss2);
8850 return;
8852 bad_param:
8854 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8855 DLIST_REMOVE(conn->pending_trans, state);
8856 SAFE_FREE(state->data);
8857 SAFE_FREE(state->param);
8858 TALLOC_FREE(state);
8859 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8860 END_PROFILE(SMBtranss2);
8861 return;