Fix a bunch of "unused variable" warnings.
[Samba/vl.git] / source3 / smbd / trans2.c
blob336e76e481afb687cafdf3bdd5ee2323d0ba0044
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 "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
36 #include "trans2.h"
37 #include "auth.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
41 #define DIR_ENTRY_SAFETY_MARGIN 4096
43 static char *store_file_unix_basic(connection_struct *conn,
44 char *pdata,
45 files_struct *fsp,
46 const SMB_STRUCT_STAT *psbuf);
48 static char *store_file_unix_basic_info2(connection_struct *conn,
49 char *pdata,
50 files_struct *fsp,
51 const SMB_STRUCT_STAT *psbuf);
53 /********************************************************************
54 The canonical "check access" based on object handle or path function.
55 ********************************************************************/
57 NTSTATUS check_access(connection_struct *conn,
58 files_struct *fsp,
59 const struct smb_filename *smb_fname,
60 uint32_t access_mask)
62 if (fsp) {
63 if (!(fsp->access_mask & access_mask)) {
64 return NT_STATUS_ACCESS_DENIED;
66 } else {
67 NTSTATUS status = smbd_check_access_rights(conn,
68 smb_fname,
69 access_mask);
70 if (!NT_STATUS_IS_OK(status)) {
71 return status;
74 return NT_STATUS_OK;
77 /********************************************************************
78 Roundup a value to the nearest allocation roundup size boundary.
79 Only do this for Windows clients.
80 ********************************************************************/
82 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
84 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
86 /* Only roundup for Windows clients. */
87 enum remote_arch_types ra_type = get_remote_arch();
88 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
89 val = SMB_ROUNDUP(val,rval);
91 return val;
94 /********************************************************************
95 Create a 64 bit FileIndex. If the file is on the same device as
96 the root of the share, just return the 64-bit inode. If it isn't,
97 mangle as we used to do.
98 ********************************************************************/
100 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
102 uint64_t file_index;
103 if (conn->base_share_dev == psbuf->st_ex_dev) {
104 return (uint64_t)psbuf->st_ex_ino;
106 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
107 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
108 return file_index;
111 /****************************************************************************
112 Utility functions for dealing with extended attributes.
113 ****************************************************************************/
115 /****************************************************************************
116 Refuse to allow clients to overwrite our private xattrs.
117 ****************************************************************************/
119 static bool samba_private_attr_name(const char *unix_ea_name)
121 static const char * const prohibited_ea_names[] = {
122 SAMBA_POSIX_INHERITANCE_EA_NAME,
123 SAMBA_XATTR_DOS_ATTRIB,
124 SAMBA_XATTR_MARKER,
125 XATTR_NTACL_NAME,
126 NULL
129 int i;
131 for (i = 0; prohibited_ea_names[i]; i++) {
132 if (strequal( prohibited_ea_names[i], unix_ea_name))
133 return true;
135 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
136 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
137 return true;
139 return false;
142 /****************************************************************************
143 Get one EA value. Fill in a struct ea_struct.
144 ****************************************************************************/
146 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
147 files_struct *fsp, const char *fname,
148 const char *ea_name, struct ea_struct *pea)
150 /* Get the value of this xattr. Max size is 64k. */
151 size_t attr_size = 256;
152 char *val = NULL;
153 ssize_t sizeret;
155 again:
157 val = talloc_realloc(mem_ctx, val, char, attr_size);
158 if (!val) {
159 return NT_STATUS_NO_MEMORY;
162 if (fsp && fsp->fh->fd != -1) {
163 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
164 } else {
165 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
168 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
169 attr_size = 65536;
170 goto again;
173 if (sizeret == -1) {
174 return map_nt_error_from_unix(errno);
177 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
178 dump_data(10, (uint8 *)val, sizeret);
180 pea->flags = 0;
181 if (strnequal(ea_name, "user.", 5)) {
182 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
183 } else {
184 pea->name = talloc_strdup(mem_ctx, ea_name);
186 if (pea->name == NULL) {
187 TALLOC_FREE(val);
188 return NT_STATUS_NO_MEMORY;
190 pea->value.data = (unsigned char *)val;
191 pea->value.length = (size_t)sizeret;
192 return NT_STATUS_OK;
195 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
196 files_struct *fsp, const char *fname,
197 char ***pnames, size_t *pnum_names)
199 /* Get a list of all xattrs. Max namesize is 64k. */
200 size_t ea_namelist_size = 1024;
201 char *ea_namelist = NULL;
203 char *p;
204 char **names, **tmp;
205 size_t num_names;
206 ssize_t sizeret = -1;
208 if (!lp_ea_support(SNUM(conn))) {
209 if (pnames) {
210 *pnames = NULL;
212 *pnum_names = 0;
213 return NT_STATUS_OK;
217 * TALLOC the result early to get the talloc hierarchy right.
220 names = talloc_array(mem_ctx, char *, 1);
221 if (names == NULL) {
222 DEBUG(0, ("talloc failed\n"));
223 return NT_STATUS_NO_MEMORY;
226 while (ea_namelist_size <= 65536) {
228 ea_namelist = talloc_realloc(
229 names, ea_namelist, char, ea_namelist_size);
230 if (ea_namelist == NULL) {
231 DEBUG(0, ("talloc failed\n"));
232 TALLOC_FREE(names);
233 return NT_STATUS_NO_MEMORY;
236 if (fsp && fsp->fh->fd != -1) {
237 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
238 ea_namelist_size);
239 } else {
240 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
241 ea_namelist_size);
244 if ((sizeret == -1) && (errno == ERANGE)) {
245 ea_namelist_size *= 2;
247 else {
248 break;
252 if (sizeret == -1) {
253 TALLOC_FREE(names);
254 return map_nt_error_from_unix(errno);
257 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
258 (unsigned int)sizeret));
260 if (sizeret == 0) {
261 TALLOC_FREE(names);
262 if (pnames) {
263 *pnames = NULL;
265 *pnum_names = 0;
266 return NT_STATUS_OK;
270 * Ensure the result is 0-terminated
273 if (ea_namelist[sizeret-1] != '\0') {
274 TALLOC_FREE(names);
275 return NT_STATUS_INTERNAL_ERROR;
279 * count the names
281 num_names = 0;
283 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
284 num_names += 1;
287 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
288 if (tmp == NULL) {
289 DEBUG(0, ("talloc failed\n"));
290 TALLOC_FREE(names);
291 return NT_STATUS_NO_MEMORY;
294 names = tmp;
295 num_names = 0;
297 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
298 names[num_names++] = p;
301 if (pnames) {
302 *pnames = names;
303 } else {
304 TALLOC_FREE(names);
306 *pnum_names = num_names;
307 return NT_STATUS_OK;
310 /****************************************************************************
311 Return a linked list of the total EA's. Plus the total size
312 ****************************************************************************/
314 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
315 const char *fname, size_t *pea_total_len)
317 /* Get a list of all xattrs. Max namesize is 64k. */
318 size_t i, num_names;
319 char **names;
320 struct ea_list *ea_list_head = NULL;
321 NTSTATUS status;
323 *pea_total_len = 0;
325 if (!lp_ea_support(SNUM(conn))) {
326 return NULL;
329 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
330 &names, &num_names);
332 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
333 return NULL;
336 for (i=0; i<num_names; i++) {
337 struct ea_list *listp;
338 fstring dos_ea_name;
340 if (strnequal(names[i], "system.", 7)
341 || samba_private_attr_name(names[i]))
342 continue;
344 listp = talloc(mem_ctx, struct ea_list);
345 if (listp == NULL) {
346 return NULL;
349 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
350 fname, names[i],
351 &listp->ea))) {
352 return NULL;
355 push_ascii_fstring(dos_ea_name, listp->ea.name);
357 *pea_total_len +=
358 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
360 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
361 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
362 (unsigned int)listp->ea.value.length));
364 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
368 /* Add on 4 for total length. */
369 if (*pea_total_len) {
370 *pea_total_len += 4;
373 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
374 (unsigned int)*pea_total_len));
376 return ea_list_head;
379 /****************************************************************************
380 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
381 that was filled.
382 ****************************************************************************/
384 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
385 connection_struct *conn, struct ea_list *ea_list)
387 unsigned int ret_data_size = 4;
388 char *p = pdata;
390 SMB_ASSERT(total_data_size >= 4);
392 if (!lp_ea_support(SNUM(conn))) {
393 SIVAL(pdata,4,0);
394 return 4;
397 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
398 size_t dos_namelen;
399 fstring dos_ea_name;
400 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
401 dos_namelen = strlen(dos_ea_name);
402 if (dos_namelen > 255 || dos_namelen == 0) {
403 break;
405 if (ea_list->ea.value.length > 65535) {
406 break;
408 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
409 break;
412 /* We know we have room. */
413 SCVAL(p,0,ea_list->ea.flags);
414 SCVAL(p,1,dos_namelen);
415 SSVAL(p,2,ea_list->ea.value.length);
416 strlcpy(p+4, dos_ea_name, dos_namelen+1);
417 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
419 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
420 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
423 ret_data_size = PTR_DIFF(p, pdata);
424 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
425 SIVAL(pdata,0,ret_data_size);
426 return ret_data_size;
429 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
430 char *pdata,
431 unsigned int total_data_size,
432 unsigned int *ret_data_size,
433 connection_struct *conn,
434 struct ea_list *ea_list)
436 uint8_t *p = (uint8_t *)pdata;
437 uint8_t *last_start = NULL;
439 *ret_data_size = 0;
441 if (!lp_ea_support(SNUM(conn))) {
442 return NT_STATUS_NO_EAS_ON_FILE;
445 for (; ea_list; ea_list = ea_list->next) {
446 size_t dos_namelen;
447 fstring dos_ea_name;
448 size_t this_size;
450 if (last_start) {
451 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
453 last_start = p;
455 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
456 dos_namelen = strlen(dos_ea_name);
457 if (dos_namelen > 255 || dos_namelen == 0) {
458 return NT_STATUS_INTERNAL_ERROR;
460 if (ea_list->ea.value.length > 65535) {
461 return NT_STATUS_INTERNAL_ERROR;
464 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
466 if (ea_list->next) {
467 size_t pad = 4 - (this_size % 4);
468 this_size += pad;
471 if (this_size > total_data_size) {
472 return NT_STATUS_INFO_LENGTH_MISMATCH;
475 /* We know we have room. */
476 SIVAL(p, 0x00, 0); /* next offset */
477 SCVAL(p, 0x04, ea_list->ea.flags);
478 SCVAL(p, 0x05, dos_namelen);
479 SSVAL(p, 0x06, ea_list->ea.value.length);
480 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
481 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
483 total_data_size -= this_size;
484 p += this_size;
487 *ret_data_size = PTR_DIFF(p, pdata);
488 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
489 return NT_STATUS_OK;
492 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
494 size_t total_ea_len = 0;
495 TALLOC_CTX *mem_ctx = NULL;
497 if (!lp_ea_support(SNUM(conn))) {
498 return 0;
500 mem_ctx = talloc_tos();
501 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
502 return total_ea_len;
505 /****************************************************************************
506 Ensure the EA name is case insensitive by matching any existing EA name.
507 ****************************************************************************/
509 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
511 size_t total_ea_len;
512 TALLOC_CTX *mem_ctx = talloc_tos();
513 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
515 for (; ea_list; ea_list = ea_list->next) {
516 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
517 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
518 &unix_ea_name[5], ea_list->ea.name));
519 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
520 break;
525 /****************************************************************************
526 Set or delete an extended attribute.
527 ****************************************************************************/
529 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
530 const struct smb_filename *smb_fname, struct ea_list *ea_list)
532 NTSTATUS status;
533 char *fname = NULL;
535 if (!lp_ea_support(SNUM(conn))) {
536 return NT_STATUS_EAS_NOT_SUPPORTED;
539 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
540 if (!NT_STATUS_IS_OK(status)) {
541 return status;
544 /* For now setting EAs on streams isn't supported. */
545 fname = smb_fname->base_name;
547 for (;ea_list; ea_list = ea_list->next) {
548 int ret;
549 fstring unix_ea_name;
551 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
552 fstrcat(unix_ea_name, ea_list->ea.name);
554 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
556 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
558 if (samba_private_attr_name(unix_ea_name)) {
559 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
560 return NT_STATUS_ACCESS_DENIED;
563 if (ea_list->ea.value.length == 0) {
564 /* Remove the attribute. */
565 if (fsp && (fsp->fh->fd != -1)) {
566 DEBUG(10,("set_ea: deleting ea name %s on "
567 "file %s by file descriptor.\n",
568 unix_ea_name, fsp_str_dbg(fsp)));
569 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
570 } else {
571 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
572 unix_ea_name, fname));
573 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
575 #ifdef ENOATTR
576 /* Removing a non existent attribute always succeeds. */
577 if (ret == -1 && errno == ENOATTR) {
578 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
579 unix_ea_name));
580 ret = 0;
582 #endif
583 } else {
584 if (fsp && (fsp->fh->fd != -1)) {
585 DEBUG(10,("set_ea: setting ea name %s on file "
586 "%s by file descriptor.\n",
587 unix_ea_name, fsp_str_dbg(fsp)));
588 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
589 ea_list->ea.value.data, ea_list->ea.value.length, 0);
590 } else {
591 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
592 unix_ea_name, fname));
593 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
594 ea_list->ea.value.data, ea_list->ea.value.length, 0);
598 if (ret == -1) {
599 #ifdef ENOTSUP
600 if (errno == ENOTSUP) {
601 return NT_STATUS_EAS_NOT_SUPPORTED;
603 #endif
604 return map_nt_error_from_unix(errno);
608 return NT_STATUS_OK;
610 /****************************************************************************
611 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
612 ****************************************************************************/
614 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
616 struct ea_list *ea_list_head = NULL;
617 size_t converted_size, offset = 0;
619 while (offset + 2 < data_size) {
620 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
621 unsigned int namelen = CVAL(pdata,offset);
623 offset++; /* Go past the namelen byte. */
625 /* integer wrap paranioa. */
626 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
627 (offset > data_size) || (namelen > data_size) ||
628 (offset + namelen >= data_size)) {
629 break;
631 /* Ensure the name is null terminated. */
632 if (pdata[offset + namelen] != '\0') {
633 return NULL;
635 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
636 &converted_size)) {
637 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
638 "failed: %s", strerror(errno)));
640 if (!eal->ea.name) {
641 return NULL;
644 offset += (namelen + 1); /* Go past the name + terminating zero. */
645 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
646 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
649 return ea_list_head;
652 /****************************************************************************
653 Read one EA list entry from the buffer.
654 ****************************************************************************/
656 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
658 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
659 uint16 val_len;
660 unsigned int namelen;
661 size_t converted_size;
663 if (!eal) {
664 return NULL;
667 if (data_size < 6) {
668 return NULL;
671 eal->ea.flags = CVAL(pdata,0);
672 namelen = CVAL(pdata,1);
673 val_len = SVAL(pdata,2);
675 if (4 + namelen + 1 + val_len > data_size) {
676 return NULL;
679 /* Ensure the name is null terminated. */
680 if (pdata[namelen + 4] != '\0') {
681 return NULL;
683 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
684 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
685 strerror(errno)));
687 if (!eal->ea.name) {
688 return NULL;
691 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
692 if (!eal->ea.value.data) {
693 return NULL;
696 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
698 /* Ensure we're null terminated just in case we print the value. */
699 eal->ea.value.data[val_len] = '\0';
700 /* But don't count the null. */
701 eal->ea.value.length--;
703 if (pbytes_used) {
704 *pbytes_used = 4 + namelen + 1 + val_len;
707 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
708 dump_data(10, eal->ea.value.data, eal->ea.value.length);
710 return eal;
713 /****************************************************************************
714 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
715 ****************************************************************************/
717 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
719 struct ea_list *ea_list_head = NULL;
720 size_t offset = 0;
721 size_t bytes_used = 0;
723 while (offset < data_size) {
724 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
726 if (!eal) {
727 return NULL;
730 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
731 offset += bytes_used;
734 return ea_list_head;
737 /****************************************************************************
738 Count the total EA size needed.
739 ****************************************************************************/
741 static size_t ea_list_size(struct ea_list *ealist)
743 fstring dos_ea_name;
744 struct ea_list *listp;
745 size_t ret = 0;
747 for (listp = ealist; listp; listp = listp->next) {
748 push_ascii_fstring(dos_ea_name, listp->ea.name);
749 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
751 /* Add on 4 for total length. */
752 if (ret) {
753 ret += 4;
756 return ret;
759 /****************************************************************************
760 Return a union of EA's from a file list and a list of names.
761 The TALLOC context for the two lists *MUST* be identical as we steal
762 memory from one list to add to another. JRA.
763 ****************************************************************************/
765 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
767 struct ea_list *nlistp, *flistp;
769 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
770 for (flistp = file_list; flistp; flistp = flistp->next) {
771 if (strequal(nlistp->ea.name, flistp->ea.name)) {
772 break;
776 if (flistp) {
777 /* Copy the data from this entry. */
778 nlistp->ea.flags = flistp->ea.flags;
779 nlistp->ea.value = flistp->ea.value;
780 } else {
781 /* Null entry. */
782 nlistp->ea.flags = 0;
783 ZERO_STRUCT(nlistp->ea.value);
787 *total_ea_len = ea_list_size(name_list);
788 return name_list;
791 /****************************************************************************
792 Send the required number of replies back.
793 We assume all fields other than the data fields are
794 set correctly for the type of call.
795 HACK ! Always assumes smb_setup field is zero.
796 ****************************************************************************/
798 void send_trans2_replies(connection_struct *conn,
799 struct smb_request *req,
800 const char *params,
801 int paramsize,
802 const char *pdata,
803 int datasize,
804 int max_data_bytes)
806 /* As we are using a protocol > LANMAN1 then the max_send
807 variable must have been set in the sessetupX call.
808 This takes precedence over the max_xmit field in the
809 global struct. These different max_xmit variables should
810 be merged as this is now too confusing */
812 int data_to_send = datasize;
813 int params_to_send = paramsize;
814 int useable_space;
815 const char *pp = params;
816 const char *pd = pdata;
817 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
818 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
819 int data_alignment_offset = 0;
820 bool overflow = False;
821 struct smbd_server_connection *sconn = req->sconn;
822 int max_send = sconn->smb1.sessions.max_send;
824 /* Modify the data_to_send and datasize and set the error if
825 we're trying to send more than max_data_bytes. We still send
826 the part of the packet(s) that fit. Strange, but needed
827 for OS/2. */
829 if (max_data_bytes > 0 && datasize > max_data_bytes) {
830 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
831 max_data_bytes, datasize ));
832 datasize = data_to_send = max_data_bytes;
833 overflow = True;
836 /* If there genuinely are no parameters or data to send just send the empty packet */
838 if(params_to_send == 0 && data_to_send == 0) {
839 reply_outbuf(req, 10, 0);
840 show_msg((char *)req->outbuf);
841 if (!srv_send_smb(sconn,
842 (char *)req->outbuf,
843 true, req->seqnum+1,
844 IS_CONN_ENCRYPTED(conn),
845 &req->pcd)) {
846 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
848 TALLOC_FREE(req->outbuf);
849 return;
852 /* When sending params and data ensure that both are nicely aligned */
853 /* Only do this alignment when there is also data to send - else
854 can cause NT redirector problems. */
856 if (((params_to_send % 4) != 0) && (data_to_send != 0))
857 data_alignment_offset = 4 - (params_to_send % 4);
859 /* Space is bufsize minus Netbios over TCP header minus SMB header */
860 /* The alignment_offset is to align the param bytes on an even byte
861 boundary. NT 4.0 Beta needs this to work correctly. */
863 useable_space = max_send - (smb_size
864 + 2 * 10 /* wct */
865 + alignment_offset
866 + data_alignment_offset);
868 if (useable_space < 0) {
869 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
870 "= %d!!!", useable_space));
871 exit_server_cleanly("send_trans2_replies: Not enough space");
874 while (params_to_send || data_to_send) {
875 /* Calculate whether we will totally or partially fill this packet */
877 total_sent_thistime = params_to_send + data_to_send;
879 /* We can never send more than useable_space */
881 * Note that 'useable_space' does not include the alignment offsets,
882 * but we must include the alignment offsets in the calculation of
883 * the length of the data we send over the wire, as the alignment offsets
884 * are sent here. Fix from Marc_Jacobsen@hp.com.
887 total_sent_thistime = MIN(total_sent_thistime, useable_space);
889 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
890 + data_alignment_offset);
893 * We might have SMBtrans2s in req which was transferred to
894 * the outbuf, fix that.
896 SCVAL(req->outbuf, smb_com, SMBtrans2);
898 /* Set total params and data to be sent */
899 SSVAL(req->outbuf,smb_tprcnt,paramsize);
900 SSVAL(req->outbuf,smb_tdrcnt,datasize);
902 /* Calculate how many parameters and data we can fit into
903 * this packet. Parameters get precedence
906 params_sent_thistime = MIN(params_to_send,useable_space);
907 data_sent_thistime = useable_space - params_sent_thistime;
908 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
910 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
912 /* smb_proff is the offset from the start of the SMB header to the
913 parameter bytes, however the first 4 bytes of outbuf are
914 the Netbios over TCP header. Thus use smb_base() to subtract
915 them from the calculation */
917 SSVAL(req->outbuf,smb_proff,
918 ((smb_buf(req->outbuf)+alignment_offset)
919 - smb_base(req->outbuf)));
921 if(params_sent_thistime == 0)
922 SSVAL(req->outbuf,smb_prdisp,0);
923 else
924 /* Absolute displacement of param bytes sent in this packet */
925 SSVAL(req->outbuf,smb_prdisp,pp - params);
927 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
928 if(data_sent_thistime == 0) {
929 SSVAL(req->outbuf,smb_droff,0);
930 SSVAL(req->outbuf,smb_drdisp, 0);
931 } else {
932 /* The offset of the data bytes is the offset of the
933 parameter bytes plus the number of parameters being sent this time */
934 SSVAL(req->outbuf, smb_droff,
935 ((smb_buf(req->outbuf)+alignment_offset)
936 - smb_base(req->outbuf))
937 + params_sent_thistime + data_alignment_offset);
938 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
941 /* Initialize the padding for alignment */
943 if (alignment_offset != 0) {
944 memset(smb_buf(req->outbuf), 0, alignment_offset);
947 /* Copy the param bytes into the packet */
949 if(params_sent_thistime) {
950 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
951 params_sent_thistime);
954 /* Copy in the data bytes */
955 if(data_sent_thistime) {
956 if (data_alignment_offset != 0) {
957 memset((smb_buf(req->outbuf)+alignment_offset+
958 params_sent_thistime), 0,
959 data_alignment_offset);
961 memcpy(smb_buf(req->outbuf)+alignment_offset
962 +params_sent_thistime+data_alignment_offset,
963 pd,data_sent_thistime);
966 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
967 params_sent_thistime, data_sent_thistime, useable_space));
968 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
969 params_to_send, data_to_send, paramsize, datasize));
971 if (overflow) {
972 error_packet_set((char *)req->outbuf,
973 ERRDOS,ERRbufferoverflow,
974 STATUS_BUFFER_OVERFLOW,
975 __LINE__,__FILE__);
978 /* Send the packet */
979 show_msg((char *)req->outbuf);
980 if (!srv_send_smb(sconn,
981 (char *)req->outbuf,
982 true, req->seqnum+1,
983 IS_CONN_ENCRYPTED(conn),
984 &req->pcd))
985 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
987 TALLOC_FREE(req->outbuf);
989 pp += params_sent_thistime;
990 pd += data_sent_thistime;
992 params_to_send -= params_sent_thistime;
993 data_to_send -= data_sent_thistime;
995 /* Sanity check */
996 if(params_to_send < 0 || data_to_send < 0) {
997 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
998 params_to_send, data_to_send));
999 return;
1003 return;
1006 /****************************************************************************
1007 Reply to a TRANSACT2_OPEN.
1008 ****************************************************************************/
1010 static void call_trans2open(connection_struct *conn,
1011 struct smb_request *req,
1012 char **pparams, int total_params,
1013 char **ppdata, int total_data,
1014 unsigned int max_data_bytes)
1016 struct smb_filename *smb_fname = NULL;
1017 char *params = *pparams;
1018 char *pdata = *ppdata;
1019 int deny_mode;
1020 int32 open_attr;
1021 bool oplock_request;
1022 #if 0
1023 bool return_additional_info;
1024 int16 open_sattr;
1025 time_t open_time;
1026 #endif
1027 int open_ofun;
1028 uint32 open_size;
1029 char *pname;
1030 char *fname = NULL;
1031 SMB_OFF_T size=0;
1032 int fattr=0,mtime=0;
1033 SMB_INO_T inode = 0;
1034 int smb_action = 0;
1035 files_struct *fsp;
1036 struct ea_list *ea_list = NULL;
1037 uint16 flags = 0;
1038 NTSTATUS status;
1039 uint32 access_mask;
1040 uint32 share_mode;
1041 uint32 create_disposition;
1042 uint32 create_options = 0;
1043 uint32_t private_flags = 0;
1044 TALLOC_CTX *ctx = talloc_tos();
1047 * Ensure we have enough parameters to perform the operation.
1050 if (total_params < 29) {
1051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1052 goto out;
1055 flags = SVAL(params, 0);
1056 deny_mode = SVAL(params, 2);
1057 open_attr = SVAL(params,6);
1058 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1059 if (oplock_request) {
1060 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1063 #if 0
1064 return_additional_info = BITSETW(params,0);
1065 open_sattr = SVAL(params, 4);
1066 open_time = make_unix_date3(params+8);
1067 #endif
1068 open_ofun = SVAL(params,12);
1069 open_size = IVAL(params,14);
1070 pname = &params[28];
1072 if (IS_IPC(conn)) {
1073 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1074 goto out;
1077 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1078 total_params - 28, STR_TERMINATE,
1079 &status);
1080 if (!NT_STATUS_IS_OK(status)) {
1081 reply_nterror(req, status);
1082 goto out;
1085 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1086 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1087 (unsigned int)open_ofun, open_size));
1089 status = filename_convert(ctx,
1090 conn,
1091 req->flags2 & FLAGS2_DFS_PATHNAMES,
1092 fname,
1094 NULL,
1095 &smb_fname);
1096 if (!NT_STATUS_IS_OK(status)) {
1097 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1098 reply_botherror(req,
1099 NT_STATUS_PATH_NOT_COVERED,
1100 ERRSRV, ERRbadpath);
1101 goto out;
1103 reply_nterror(req, status);
1104 goto out;
1107 if (open_ofun == 0) {
1108 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1109 goto out;
1112 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1113 open_ofun,
1114 &access_mask, &share_mode,
1115 &create_disposition,
1116 &create_options,
1117 &private_flags)) {
1118 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1119 goto out;
1122 /* Any data in this call is an EA list. */
1123 if (total_data && (total_data != 4)) {
1124 if (total_data < 10) {
1125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1126 goto out;
1129 if (IVAL(pdata,0) > total_data) {
1130 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1131 IVAL(pdata,0), (unsigned int)total_data));
1132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1133 goto out;
1136 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1137 total_data - 4);
1138 if (!ea_list) {
1139 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1140 goto out;
1143 if (!lp_ea_support(SNUM(conn))) {
1144 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1145 goto out;
1149 status = SMB_VFS_CREATE_FILE(
1150 conn, /* conn */
1151 req, /* req */
1152 0, /* root_dir_fid */
1153 smb_fname, /* fname */
1154 access_mask, /* access_mask */
1155 share_mode, /* share_access */
1156 create_disposition, /* create_disposition*/
1157 create_options, /* create_options */
1158 open_attr, /* file_attributes */
1159 oplock_request, /* oplock_request */
1160 open_size, /* allocation_size */
1161 private_flags,
1162 NULL, /* sd */
1163 ea_list, /* ea_list */
1164 &fsp, /* result */
1165 &smb_action); /* psbuf */
1167 if (!NT_STATUS_IS_OK(status)) {
1168 if (open_was_deferred(req->sconn, req->mid)) {
1169 /* We have re-scheduled this call. */
1170 goto out;
1172 reply_openerror(req, status);
1173 goto out;
1176 size = get_file_size_stat(&smb_fname->st);
1177 fattr = dos_mode(conn, smb_fname);
1178 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1179 inode = smb_fname->st.st_ex_ino;
1180 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1181 close_file(req, fsp, ERROR_CLOSE);
1182 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1183 goto out;
1186 /* Realloc the size of parameters and data we will return */
1187 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1188 if(*pparams == NULL ) {
1189 reply_nterror(req, NT_STATUS_NO_MEMORY);
1190 goto out;
1192 params = *pparams;
1194 SSVAL(params,0,fsp->fnum);
1195 SSVAL(params,2,fattr);
1196 srv_put_dos_date2(params,4, mtime);
1197 SIVAL(params,8, (uint32)size);
1198 SSVAL(params,12,deny_mode);
1199 SSVAL(params,14,0); /* open_type - file or directory. */
1200 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1202 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1203 smb_action |= EXTENDED_OPLOCK_GRANTED;
1206 SSVAL(params,18,smb_action);
1209 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1211 SIVAL(params,20,inode);
1212 SSVAL(params,24,0); /* Padding. */
1213 if (flags & 8) {
1214 uint32 ea_size = estimate_ea_size(conn, fsp,
1215 fsp->fsp_name->base_name);
1216 SIVAL(params, 26, ea_size);
1217 } else {
1218 SIVAL(params, 26, 0);
1221 /* Send the required number of replies */
1222 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1223 out:
1224 TALLOC_FREE(smb_fname);
1227 /*********************************************************
1228 Routine to check if a given string matches exactly.
1229 as a special case a mask of "." does NOT match. That
1230 is required for correct wildcard semantics
1231 Case can be significant or not.
1232 **********************************************************/
1234 static bool exact_match(bool has_wild,
1235 bool case_sensitive,
1236 const char *str,
1237 const char *mask)
1239 if (mask[0] == '.' && mask[1] == 0) {
1240 return false;
1243 if (has_wild) {
1244 return false;
1247 if (case_sensitive) {
1248 return strcmp(str,mask)==0;
1249 } else {
1250 return strcasecmp_m(str,mask) == 0;
1254 /****************************************************************************
1255 Return the filetype for UNIX extensions.
1256 ****************************************************************************/
1258 static uint32 unix_filetype(mode_t mode)
1260 if(S_ISREG(mode))
1261 return UNIX_TYPE_FILE;
1262 else if(S_ISDIR(mode))
1263 return UNIX_TYPE_DIR;
1264 #ifdef S_ISLNK
1265 else if(S_ISLNK(mode))
1266 return UNIX_TYPE_SYMLINK;
1267 #endif
1268 #ifdef S_ISCHR
1269 else if(S_ISCHR(mode))
1270 return UNIX_TYPE_CHARDEV;
1271 #endif
1272 #ifdef S_ISBLK
1273 else if(S_ISBLK(mode))
1274 return UNIX_TYPE_BLKDEV;
1275 #endif
1276 #ifdef S_ISFIFO
1277 else if(S_ISFIFO(mode))
1278 return UNIX_TYPE_FIFO;
1279 #endif
1280 #ifdef S_ISSOCK
1281 else if(S_ISSOCK(mode))
1282 return UNIX_TYPE_SOCKET;
1283 #endif
1285 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1286 return UNIX_TYPE_UNKNOWN;
1289 /****************************************************************************
1290 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1291 ****************************************************************************/
1293 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1295 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1296 const SMB_STRUCT_STAT *psbuf,
1297 uint32 perms,
1298 enum perm_type ptype,
1299 mode_t *ret_perms)
1301 mode_t ret = 0;
1303 if (perms == SMB_MODE_NO_CHANGE) {
1304 if (!VALID_STAT(*psbuf)) {
1305 return NT_STATUS_INVALID_PARAMETER;
1306 } else {
1307 *ret_perms = psbuf->st_ex_mode;
1308 return NT_STATUS_OK;
1312 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1313 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1314 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1315 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1316 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1317 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1318 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1319 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1320 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1321 #ifdef S_ISVTX
1322 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1323 #endif
1324 #ifdef S_ISGID
1325 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1326 #endif
1327 #ifdef S_ISUID
1328 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1329 #endif
1331 switch (ptype) {
1332 case PERM_NEW_FILE:
1333 /* Apply mode mask */
1334 ret &= lp_create_mask(SNUM(conn));
1335 /* Add in force bits */
1336 ret |= lp_force_create_mode(SNUM(conn));
1337 break;
1338 case PERM_NEW_DIR:
1339 ret &= lp_dir_mask(SNUM(conn));
1340 /* Add in force bits */
1341 ret |= lp_force_dir_mode(SNUM(conn));
1342 break;
1343 case PERM_EXISTING_FILE:
1344 /* Apply mode mask */
1345 ret &= lp_security_mask(SNUM(conn));
1346 /* Add in force bits */
1347 ret |= lp_force_security_mode(SNUM(conn));
1348 break;
1349 case PERM_EXISTING_DIR:
1350 /* Apply mode mask */
1351 ret &= lp_dir_security_mask(SNUM(conn));
1352 /* Add in force bits */
1353 ret |= lp_force_dir_security_mode(SNUM(conn));
1354 break;
1357 *ret_perms = ret;
1358 return NT_STATUS_OK;
1361 /****************************************************************************
1362 Needed to show the msdfs symlinks as directories. Modifies psbuf
1363 to be a directory if it's a msdfs link.
1364 ****************************************************************************/
1366 static bool check_msdfs_link(connection_struct *conn,
1367 const char *pathname,
1368 SMB_STRUCT_STAT *psbuf)
1370 int saved_errno = errno;
1371 if(lp_host_msdfs() &&
1372 lp_msdfs_root(SNUM(conn)) &&
1373 is_msdfs_link(conn, pathname, psbuf)) {
1375 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1376 "as a directory\n",
1377 pathname));
1378 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1379 errno = saved_errno;
1380 return true;
1382 errno = saved_errno;
1383 return false;
1387 /****************************************************************************
1388 Get a level dependent lanman2 dir entry.
1389 ****************************************************************************/
1391 struct smbd_dirptr_lanman2_state {
1392 connection_struct *conn;
1393 uint32_t info_level;
1394 bool check_mangled_names;
1395 bool has_wild;
1396 bool got_exact_match;
1399 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1400 void *private_data,
1401 const char *dname,
1402 const char *mask,
1403 char **_fname)
1405 struct smbd_dirptr_lanman2_state *state =
1406 (struct smbd_dirptr_lanman2_state *)private_data;
1407 bool ok;
1408 char mangled_name[13]; /* mangled 8.3 name. */
1409 bool got_match;
1410 const char *fname;
1412 /* Mangle fname if it's an illegal name. */
1413 if (mangle_must_mangle(dname, state->conn->params)) {
1414 ok = name_to_8_3(dname, mangled_name,
1415 true, state->conn->params);
1416 if (!ok) {
1417 return false;
1419 fname = mangled_name;
1420 } else {
1421 fname = dname;
1424 got_match = exact_match(state->has_wild,
1425 state->conn->case_sensitive,
1426 fname, mask);
1427 state->got_exact_match = got_match;
1428 if (!got_match) {
1429 got_match = mask_match(fname, mask,
1430 state->conn->case_sensitive);
1433 if(!got_match && state->check_mangled_names &&
1434 !mangle_is_8_3(fname, false, state->conn->params)) {
1436 * It turns out that NT matches wildcards against
1437 * both long *and* short names. This may explain some
1438 * of the wildcard wierdness from old DOS clients
1439 * that some people have been seeing.... JRA.
1441 /* Force the mangling into 8.3. */
1442 ok = name_to_8_3(fname, mangled_name,
1443 false, state->conn->params);
1444 if (!ok) {
1445 return false;
1448 got_match = exact_match(state->has_wild,
1449 state->conn->case_sensitive,
1450 mangled_name, mask);
1451 state->got_exact_match = got_match;
1452 if (!got_match) {
1453 got_match = mask_match(mangled_name, mask,
1454 state->conn->case_sensitive);
1458 if (!got_match) {
1459 return false;
1462 *_fname = talloc_strdup(ctx, fname);
1463 if (*_fname == NULL) {
1464 return false;
1467 return true;
1470 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1471 void *private_data,
1472 struct smb_filename *smb_fname,
1473 uint32_t *_mode)
1475 struct smbd_dirptr_lanman2_state *state =
1476 (struct smbd_dirptr_lanman2_state *)private_data;
1477 bool ms_dfs_link = false;
1478 uint32_t mode = 0;
1480 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1481 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1482 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1483 "Couldn't lstat [%s] (%s)\n",
1484 smb_fname_str_dbg(smb_fname),
1485 strerror(errno)));
1486 return false;
1488 } else if (!VALID_STAT(smb_fname->st) &&
1489 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1490 /* Needed to show the msdfs symlinks as
1491 * directories */
1493 ms_dfs_link = check_msdfs_link(state->conn,
1494 smb_fname->base_name,
1495 &smb_fname->st);
1496 if (!ms_dfs_link) {
1497 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1498 "Couldn't stat [%s] (%s)\n",
1499 smb_fname_str_dbg(smb_fname),
1500 strerror(errno)));
1501 return false;
1505 if (ms_dfs_link) {
1506 mode = dos_mode_msdfs(state->conn, smb_fname);
1507 } else {
1508 mode = dos_mode(state->conn, smb_fname);
1511 *_mode = mode;
1512 return true;
1515 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1516 connection_struct *conn,
1517 uint16_t flags2,
1518 uint32_t info_level,
1519 struct ea_list *name_list,
1520 bool check_mangled_names,
1521 bool requires_resume_key,
1522 uint32_t mode,
1523 const char *fname,
1524 const struct smb_filename *smb_fname,
1525 int space_remaining,
1526 uint8_t align,
1527 bool do_pad,
1528 char *base_data,
1529 char **ppdata,
1530 char *end_data,
1531 bool *out_of_space,
1532 uint64_t *last_entry_off)
1534 char *p, *q, *pdata = *ppdata;
1535 uint32_t reskey=0;
1536 uint64_t file_size = 0;
1537 uint64_t allocation_size = 0;
1538 uint64_t file_index = 0;
1539 uint32_t len;
1540 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1541 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1542 char *nameptr;
1543 char *last_entry_ptr;
1544 bool was_8_3;
1545 int off;
1546 int pad = 0;
1548 *out_of_space = false;
1550 ZERO_STRUCT(mdate_ts);
1551 ZERO_STRUCT(adate_ts);
1552 ZERO_STRUCT(create_date_ts);
1553 ZERO_STRUCT(cdate_ts);
1555 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1556 file_size = get_file_size_stat(&smb_fname->st);
1558 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1560 file_index = get_FileIndex(conn, &smb_fname->st);
1562 mdate_ts = smb_fname->st.st_ex_mtime;
1563 adate_ts = smb_fname->st.st_ex_atime;
1564 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1565 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1567 if (lp_dos_filetime_resolution(SNUM(conn))) {
1568 dos_filetime_timespec(&create_date_ts);
1569 dos_filetime_timespec(&mdate_ts);
1570 dos_filetime_timespec(&adate_ts);
1571 dos_filetime_timespec(&cdate_ts);
1574 create_date = convert_timespec_to_time_t(create_date_ts);
1575 mdate = convert_timespec_to_time_t(mdate_ts);
1576 adate = convert_timespec_to_time_t(adate_ts);
1578 /* align the record */
1579 SMB_ASSERT(align >= 1);
1581 off = (int)PTR_DIFF(pdata, base_data);
1582 pad = (off + (align-1)) & ~(align-1);
1583 pad -= off;
1585 if (pad && pad > space_remaining) {
1586 *out_of_space = true;
1587 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1588 "for padding (wanted %u, had %d)\n",
1589 (unsigned int)pad,
1590 space_remaining ));
1591 return false; /* Not finished - just out of space */
1594 off += pad;
1595 /* initialize padding to 0 */
1596 if (pad) {
1597 memset(pdata, 0, pad);
1599 space_remaining -= pad;
1601 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1602 space_remaining ));
1604 pdata += pad;
1605 p = pdata;
1606 last_entry_ptr = p;
1608 pad = 0;
1609 off = 0;
1611 switch (info_level) {
1612 case SMB_FIND_INFO_STANDARD:
1613 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1614 if(requires_resume_key) {
1615 SIVAL(p,0,reskey);
1616 p += 4;
1618 srv_put_dos_date2(p,0,create_date);
1619 srv_put_dos_date2(p,4,adate);
1620 srv_put_dos_date2(p,8,mdate);
1621 SIVAL(p,12,(uint32)file_size);
1622 SIVAL(p,16,(uint32)allocation_size);
1623 SSVAL(p,20,mode);
1624 p += 23;
1625 nameptr = p;
1626 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1627 p += ucs2_align(base_data, p, 0);
1629 len = srvstr_push(base_data, flags2, p,
1630 fname, PTR_DIFF(end_data, p),
1631 STR_TERMINATE);
1632 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1633 if (len > 2) {
1634 SCVAL(nameptr, -1, len - 2);
1635 } else {
1636 SCVAL(nameptr, -1, 0);
1638 } else {
1639 if (len > 1) {
1640 SCVAL(nameptr, -1, len - 1);
1641 } else {
1642 SCVAL(nameptr, -1, 0);
1645 p += len;
1646 break;
1648 case SMB_FIND_EA_SIZE:
1649 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1650 if (requires_resume_key) {
1651 SIVAL(p,0,reskey);
1652 p += 4;
1654 srv_put_dos_date2(p,0,create_date);
1655 srv_put_dos_date2(p,4,adate);
1656 srv_put_dos_date2(p,8,mdate);
1657 SIVAL(p,12,(uint32)file_size);
1658 SIVAL(p,16,(uint32)allocation_size);
1659 SSVAL(p,20,mode);
1661 unsigned int ea_size = estimate_ea_size(conn, NULL,
1662 smb_fname->base_name);
1663 SIVAL(p,22,ea_size); /* Extended attributes */
1665 p += 27;
1666 nameptr = p - 1;
1667 len = srvstr_push(base_data, flags2,
1668 p, fname, PTR_DIFF(end_data, p),
1669 STR_TERMINATE | STR_NOALIGN);
1670 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1671 if (len > 2) {
1672 len -= 2;
1673 } else {
1674 len = 0;
1676 } else {
1677 if (len > 1) {
1678 len -= 1;
1679 } else {
1680 len = 0;
1683 SCVAL(nameptr,0,len);
1684 p += len;
1685 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1686 break;
1688 case SMB_FIND_EA_LIST:
1690 struct ea_list *file_list = NULL;
1691 size_t ea_len = 0;
1693 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1694 if (!name_list) {
1695 return false;
1697 if (requires_resume_key) {
1698 SIVAL(p,0,reskey);
1699 p += 4;
1701 srv_put_dos_date2(p,0,create_date);
1702 srv_put_dos_date2(p,4,adate);
1703 srv_put_dos_date2(p,8,mdate);
1704 SIVAL(p,12,(uint32)file_size);
1705 SIVAL(p,16,(uint32)allocation_size);
1706 SSVAL(p,20,mode);
1707 p += 22; /* p now points to the EA area. */
1709 file_list = get_ea_list_from_file(ctx, conn, NULL,
1710 smb_fname->base_name,
1711 &ea_len);
1712 name_list = ea_list_union(name_list, file_list, &ea_len);
1714 /* We need to determine if this entry will fit in the space available. */
1715 /* Max string size is 255 bytes. */
1716 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1717 *out_of_space = true;
1718 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1719 "(wanted %u, had %d)\n",
1720 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1721 space_remaining ));
1722 return False; /* Not finished - just out of space */
1725 /* Push the ea_data followed by the name. */
1726 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1727 nameptr = p;
1728 len = srvstr_push(base_data, flags2,
1729 p + 1, fname, PTR_DIFF(end_data, p+1),
1730 STR_TERMINATE | STR_NOALIGN);
1731 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1732 if (len > 2) {
1733 len -= 2;
1734 } else {
1735 len = 0;
1737 } else {
1738 if (len > 1) {
1739 len -= 1;
1740 } else {
1741 len = 0;
1744 SCVAL(nameptr,0,len);
1745 p += len + 1;
1746 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1747 break;
1750 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1751 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1752 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1753 p += 4;
1754 SIVAL(p,0,reskey); p += 4;
1755 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1756 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1757 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1758 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1759 SOFF_T(p,0,file_size); p += 8;
1760 SOFF_T(p,0,allocation_size); p += 8;
1761 SIVAL(p,0,mode); p += 4;
1762 q = p; p += 4; /* q is placeholder for name length. */
1764 unsigned int ea_size = estimate_ea_size(conn, NULL,
1765 smb_fname->base_name);
1766 SIVAL(p,0,ea_size); /* Extended attributes */
1767 p += 4;
1769 /* Clear the short name buffer. This is
1770 * IMPORTANT as not doing so will trigger
1771 * a Win2k client bug. JRA.
1773 if (!was_8_3 && check_mangled_names) {
1774 char mangled_name[13]; /* mangled 8.3 name. */
1775 if (!name_to_8_3(fname,mangled_name,True,
1776 conn->params)) {
1777 /* Error - mangle failed ! */
1778 memset(mangled_name,'\0',12);
1780 mangled_name[12] = 0;
1781 len = srvstr_push(base_data, flags2,
1782 p+2, mangled_name, 24,
1783 STR_UPPER|STR_UNICODE);
1784 if (len < 24) {
1785 memset(p + 2 + len,'\0',24 - len);
1787 SSVAL(p, 0, len);
1788 } else {
1789 memset(p,'\0',26);
1791 p += 2 + 24;
1792 len = srvstr_push(base_data, flags2, p,
1793 fname, PTR_DIFF(end_data, p),
1794 STR_TERMINATE_ASCII);
1795 SIVAL(q,0,len);
1796 p += len;
1798 len = PTR_DIFF(p, pdata);
1799 pad = (len + (align-1)) & ~(align-1);
1801 * offset to the next entry, the caller
1802 * will overwrite it for the last entry
1803 * that's why we always include the padding
1805 SIVAL(pdata,0,pad);
1807 * set padding to zero
1809 if (do_pad) {
1810 memset(p, 0, pad - len);
1811 p = pdata + pad;
1812 } else {
1813 p = pdata + len;
1815 break;
1817 case SMB_FIND_FILE_DIRECTORY_INFO:
1818 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1819 p += 4;
1820 SIVAL(p,0,reskey); p += 4;
1821 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1822 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1823 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1824 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1825 SOFF_T(p,0,file_size); p += 8;
1826 SOFF_T(p,0,allocation_size); p += 8;
1827 SIVAL(p,0,mode); p += 4;
1828 len = srvstr_push(base_data, flags2,
1829 p + 4, fname, PTR_DIFF(end_data, p+4),
1830 STR_TERMINATE_ASCII);
1831 SIVAL(p,0,len);
1832 p += 4 + len;
1834 len = PTR_DIFF(p, pdata);
1835 pad = (len + (align-1)) & ~(align-1);
1837 * offset to the next entry, the caller
1838 * will overwrite it for the last entry
1839 * that's why we always include the padding
1841 SIVAL(pdata,0,pad);
1843 * set padding to zero
1845 if (do_pad) {
1846 memset(p, 0, pad - len);
1847 p = pdata + pad;
1848 } else {
1849 p = pdata + len;
1851 break;
1853 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1854 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1855 p += 4;
1856 SIVAL(p,0,reskey); p += 4;
1857 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1858 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1859 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1860 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1861 SOFF_T(p,0,file_size); p += 8;
1862 SOFF_T(p,0,allocation_size); p += 8;
1863 SIVAL(p,0,mode); p += 4;
1864 q = p; p += 4; /* q is placeholder for name length. */
1866 unsigned int ea_size = estimate_ea_size(conn, NULL,
1867 smb_fname->base_name);
1868 SIVAL(p,0,ea_size); /* Extended attributes */
1869 p +=4;
1871 len = srvstr_push(base_data, flags2, p,
1872 fname, PTR_DIFF(end_data, p),
1873 STR_TERMINATE_ASCII);
1874 SIVAL(q, 0, 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_FILE_NAMES_INFO:
1897 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1898 p += 4;
1899 SIVAL(p,0,reskey); p += 4;
1900 p += 4;
1901 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1902 acl on a dir (tridge) */
1903 len = srvstr_push(base_data, flags2, p,
1904 fname, PTR_DIFF(end_data, p),
1905 STR_TERMINATE_ASCII);
1906 SIVAL(p, -4, len);
1907 p += len;
1909 len = PTR_DIFF(p, pdata);
1910 pad = (len + (align-1)) & ~(align-1);
1912 * offset to the next entry, the caller
1913 * will overwrite it for the last entry
1914 * that's why we always include the padding
1916 SIVAL(pdata,0,pad);
1918 * set padding to zero
1920 if (do_pad) {
1921 memset(p, 0, pad - len);
1922 p = pdata + pad;
1923 } else {
1924 p = pdata + len;
1926 break;
1928 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1929 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1930 p += 4;
1931 SIVAL(p,0,reskey); p += 4;
1932 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1933 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1934 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1935 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1936 SOFF_T(p,0,file_size); p += 8;
1937 SOFF_T(p,0,allocation_size); p += 8;
1938 SIVAL(p,0,mode); p += 4;
1939 q = p; p += 4; /* q is placeholder for name length. */
1941 unsigned int ea_size = estimate_ea_size(conn, NULL,
1942 smb_fname->base_name);
1943 SIVAL(p,0,ea_size); /* Extended attributes */
1944 p +=4;
1946 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1947 SBVAL(p,0,file_index); p += 8;
1948 len = srvstr_push(base_data, flags2, p,
1949 fname, PTR_DIFF(end_data, p),
1950 STR_TERMINATE_ASCII);
1951 SIVAL(q, 0, len);
1952 p += len;
1954 len = PTR_DIFF(p, pdata);
1955 pad = (len + (align-1)) & ~(align-1);
1957 * offset to the next entry, the caller
1958 * will overwrite it for the last entry
1959 * that's why we always include the padding
1961 SIVAL(pdata,0,pad);
1963 * set padding to zero
1965 if (do_pad) {
1966 memset(p, 0, pad - len);
1967 p = pdata + pad;
1968 } else {
1969 p = pdata + len;
1971 break;
1973 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1974 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1975 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1976 p += 4;
1977 SIVAL(p,0,reskey); p += 4;
1978 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1979 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1980 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1981 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1982 SOFF_T(p,0,file_size); p += 8;
1983 SOFF_T(p,0,allocation_size); p += 8;
1984 SIVAL(p,0,mode); p += 4;
1985 q = p; p += 4; /* q is placeholder for name length */
1987 unsigned int ea_size = estimate_ea_size(conn, NULL,
1988 smb_fname->base_name);
1989 SIVAL(p,0,ea_size); /* Extended attributes */
1990 p +=4;
1992 /* Clear the short name buffer. This is
1993 * IMPORTANT as not doing so will trigger
1994 * a Win2k client bug. JRA.
1996 if (!was_8_3 && check_mangled_names) {
1997 char mangled_name[13]; /* mangled 8.3 name. */
1998 if (!name_to_8_3(fname,mangled_name,True,
1999 conn->params)) {
2000 /* Error - mangle failed ! */
2001 memset(mangled_name,'\0',12);
2003 mangled_name[12] = 0;
2004 len = srvstr_push(base_data, flags2,
2005 p+2, mangled_name, 24,
2006 STR_UPPER|STR_UNICODE);
2007 SSVAL(p, 0, len);
2008 if (len < 24) {
2009 memset(p + 2 + len,'\0',24 - len);
2011 SSVAL(p, 0, len);
2012 } else {
2013 memset(p,'\0',26);
2015 p += 26;
2016 SSVAL(p,0,0); p += 2; /* Reserved ? */
2017 SBVAL(p,0,file_index); p += 8;
2018 len = srvstr_push(base_data, flags2, p,
2019 fname, PTR_DIFF(end_data, p),
2020 STR_TERMINATE_ASCII);
2021 SIVAL(q,0,len);
2022 p += len;
2024 len = PTR_DIFF(p, pdata);
2025 pad = (len + (align-1)) & ~(align-1);
2027 * offset to the next entry, the caller
2028 * will overwrite it for the last entry
2029 * that's why we always include the padding
2031 SIVAL(pdata,0,pad);
2033 * set padding to zero
2035 if (do_pad) {
2036 memset(p, 0, pad - len);
2037 p = pdata + pad;
2038 } else {
2039 p = pdata + len;
2041 break;
2043 /* CIFS UNIX Extension. */
2045 case SMB_FIND_FILE_UNIX:
2046 case SMB_FIND_FILE_UNIX_INFO2:
2047 p+= 4;
2048 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2050 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2052 if (info_level == SMB_FIND_FILE_UNIX) {
2053 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2054 p = store_file_unix_basic(conn, p,
2055 NULL, &smb_fname->st);
2056 len = srvstr_push(base_data, flags2, p,
2057 fname, PTR_DIFF(end_data, p),
2058 STR_TERMINATE);
2059 } else {
2060 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2061 p = store_file_unix_basic_info2(conn, p,
2062 NULL, &smb_fname->st);
2063 nameptr = p;
2064 p += 4;
2065 len = srvstr_push(base_data, flags2, p, fname,
2066 PTR_DIFF(end_data, p), 0);
2067 SIVAL(nameptr, 0, len);
2070 p += len;
2072 len = PTR_DIFF(p, pdata);
2073 pad = (len + (align-1)) & ~(align-1);
2075 * offset to the next entry, the caller
2076 * will overwrite it for the last entry
2077 * that's why we always include the padding
2079 SIVAL(pdata,0,pad);
2081 * set padding to zero
2083 if (do_pad) {
2084 memset(p, 0, pad - len);
2085 p = pdata + pad;
2086 } else {
2087 p = pdata + len;
2089 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2091 break;
2093 default:
2094 return false;
2097 if (PTR_DIFF(p,pdata) > space_remaining) {
2098 *out_of_space = true;
2099 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2100 "(wanted %u, had %d)\n",
2101 (unsigned int)PTR_DIFF(p,pdata),
2102 space_remaining ));
2103 return false; /* Not finished - just out of space */
2106 /* Setup the last entry pointer, as an offset from base_data */
2107 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2108 /* Advance the data pointer to the next slot */
2109 *ppdata = p;
2111 return true;
2114 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2115 connection_struct *conn,
2116 struct dptr_struct *dirptr,
2117 uint16 flags2,
2118 const char *path_mask,
2119 uint32 dirtype,
2120 int info_level,
2121 int requires_resume_key,
2122 bool dont_descend,
2123 bool ask_sharemode,
2124 uint8_t align,
2125 bool do_pad,
2126 char **ppdata,
2127 char *base_data,
2128 char *end_data,
2129 int space_remaining,
2130 bool *out_of_space,
2131 bool *got_exact_match,
2132 int *_last_entry_off,
2133 struct ea_list *name_list)
2135 const char *p;
2136 const char *mask = NULL;
2137 long prev_dirpos = 0;
2138 uint32_t mode = 0;
2139 char *fname = NULL;
2140 struct smb_filename *smb_fname = NULL;
2141 struct smbd_dirptr_lanman2_state state;
2142 bool ok;
2143 uint64_t last_entry_off = 0;
2145 ZERO_STRUCT(state);
2146 state.conn = conn;
2147 state.info_level = info_level;
2148 state.check_mangled_names = lp_manglednames(conn->params);
2149 state.has_wild = dptr_has_wild(dirptr);
2150 state.got_exact_match = false;
2152 *out_of_space = false;
2153 *got_exact_match = false;
2155 p = strrchr_m(path_mask,'/');
2156 if(p != NULL) {
2157 if(p[1] == '\0') {
2158 mask = "*.*";
2159 } else {
2160 mask = p+1;
2162 } else {
2163 mask = path_mask;
2166 ok = smbd_dirptr_get_entry(ctx,
2167 dirptr,
2168 mask,
2169 dirtype,
2170 dont_descend,
2171 ask_sharemode,
2172 smbd_dirptr_lanman2_match_fn,
2173 smbd_dirptr_lanman2_mode_fn,
2174 &state,
2175 &fname,
2176 &smb_fname,
2177 &mode,
2178 &prev_dirpos);
2179 if (!ok) {
2180 return false;
2183 *got_exact_match = state.got_exact_match;
2185 ok = smbd_marshall_dir_entry(ctx,
2186 conn,
2187 flags2,
2188 info_level,
2189 name_list,
2190 state.check_mangled_names,
2191 requires_resume_key,
2192 mode,
2193 fname,
2194 smb_fname,
2195 space_remaining,
2196 align,
2197 do_pad,
2198 base_data,
2199 ppdata,
2200 end_data,
2201 out_of_space,
2202 &last_entry_off);
2203 TALLOC_FREE(fname);
2204 TALLOC_FREE(smb_fname);
2205 if (*out_of_space) {
2206 dptr_SeekDir(dirptr, prev_dirpos);
2207 return false;
2209 if (!ok) {
2210 return false;
2213 *_last_entry_off = last_entry_off;
2214 return true;
2217 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2218 connection_struct *conn,
2219 struct dptr_struct *dirptr,
2220 uint16 flags2,
2221 const char *path_mask,
2222 uint32 dirtype,
2223 int info_level,
2224 bool requires_resume_key,
2225 bool dont_descend,
2226 bool ask_sharemode,
2227 char **ppdata,
2228 char *base_data,
2229 char *end_data,
2230 int space_remaining,
2231 bool *out_of_space,
2232 bool *got_exact_match,
2233 int *last_entry_off,
2234 struct ea_list *name_list)
2236 uint8_t align = 4;
2237 const bool do_pad = true;
2239 if (info_level >= 1 && info_level <= 3) {
2240 /* No alignment on earlier info levels. */
2241 align = 1;
2244 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2245 path_mask, dirtype, info_level,
2246 requires_resume_key, dont_descend, ask_sharemode,
2247 align, do_pad,
2248 ppdata, base_data, end_data,
2249 space_remaining,
2250 out_of_space, got_exact_match,
2251 last_entry_off, name_list);
2254 /****************************************************************************
2255 Reply to a TRANS2_FINDFIRST.
2256 ****************************************************************************/
2258 static void call_trans2findfirst(connection_struct *conn,
2259 struct smb_request *req,
2260 char **pparams, int total_params,
2261 char **ppdata, int total_data,
2262 unsigned int max_data_bytes)
2264 /* We must be careful here that we don't return more than the
2265 allowed number of data bytes. If this means returning fewer than
2266 maxentries then so be it. We assume that the redirector has
2267 enough room for the fixed number of parameter bytes it has
2268 requested. */
2269 struct smb_filename *smb_dname = NULL;
2270 char *params = *pparams;
2271 char *pdata = *ppdata;
2272 char *data_end;
2273 uint32 dirtype;
2274 int maxentries;
2275 uint16 findfirst_flags;
2276 bool close_after_first;
2277 bool close_if_end;
2278 bool requires_resume_key;
2279 int info_level;
2280 char *directory = NULL;
2281 char *mask = NULL;
2282 char *p;
2283 int last_entry_off=0;
2284 int dptr_num = -1;
2285 int numentries = 0;
2286 int i;
2287 bool finished = False;
2288 bool dont_descend = False;
2289 bool out_of_space = False;
2290 int space_remaining;
2291 bool mask_contains_wcard = False;
2292 struct ea_list *ea_list = NULL;
2293 NTSTATUS ntstatus = NT_STATUS_OK;
2294 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2295 TALLOC_CTX *ctx = talloc_tos();
2296 struct dptr_struct *dirptr = NULL;
2297 struct smbd_server_connection *sconn = req->sconn;
2298 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2300 if (total_params < 13) {
2301 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2302 goto out;
2305 dirtype = SVAL(params,0);
2306 maxentries = SVAL(params,2);
2307 findfirst_flags = SVAL(params,4);
2308 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2309 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2310 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2311 info_level = SVAL(params,6);
2313 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2314 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2315 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2316 info_level, max_data_bytes));
2318 if (!maxentries) {
2319 /* W2K3 seems to treat zero as 1. */
2320 maxentries = 1;
2323 switch (info_level) {
2324 case SMB_FIND_INFO_STANDARD:
2325 case SMB_FIND_EA_SIZE:
2326 case SMB_FIND_EA_LIST:
2327 case SMB_FIND_FILE_DIRECTORY_INFO:
2328 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2329 case SMB_FIND_FILE_NAMES_INFO:
2330 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2331 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2332 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2333 break;
2334 case SMB_FIND_FILE_UNIX:
2335 case SMB_FIND_FILE_UNIX_INFO2:
2336 /* Always use filesystem for UNIX mtime query. */
2337 ask_sharemode = false;
2338 if (!lp_unix_extensions()) {
2339 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2340 goto out;
2342 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2343 break;
2344 default:
2345 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2346 goto out;
2349 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2350 params+12, total_params - 12,
2351 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2352 if (!NT_STATUS_IS_OK(ntstatus)) {
2353 reply_nterror(req, ntstatus);
2354 goto out;
2357 ntstatus = filename_convert(ctx, conn,
2358 req->flags2 & FLAGS2_DFS_PATHNAMES,
2359 directory,
2360 ucf_flags,
2361 &mask_contains_wcard,
2362 &smb_dname);
2363 if (!NT_STATUS_IS_OK(ntstatus)) {
2364 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2365 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2366 ERRSRV, ERRbadpath);
2367 goto out;
2369 reply_nterror(req, ntstatus);
2370 goto out;
2373 mask = smb_dname->original_lcomp;
2375 directory = smb_dname->base_name;
2377 p = strrchr_m(directory,'/');
2378 if(p == NULL) {
2379 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2380 if((directory[0] == '.') && (directory[1] == '\0')) {
2381 mask = talloc_strdup(ctx,"*");
2382 if (!mask) {
2383 reply_nterror(req, NT_STATUS_NO_MEMORY);
2384 goto out;
2386 mask_contains_wcard = True;
2388 } else {
2389 *p = 0;
2392 if (p == NULL || p == directory) {
2393 /* Ensure we don't have a directory name of "". */
2394 directory = talloc_strdup(talloc_tos(), ".");
2395 if (!directory) {
2396 reply_nterror(req, NT_STATUS_NO_MEMORY);
2397 goto out;
2401 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2403 if (info_level == SMB_FIND_EA_LIST) {
2404 uint32 ea_size;
2406 if (total_data < 4) {
2407 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2408 goto out;
2411 ea_size = IVAL(pdata,0);
2412 if (ea_size != total_data) {
2413 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2414 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2415 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2416 goto out;
2419 if (!lp_ea_support(SNUM(conn))) {
2420 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2421 goto out;
2424 /* Pull out the list of names. */
2425 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2426 if (!ea_list) {
2427 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2428 goto out;
2432 *ppdata = (char *)SMB_REALLOC(
2433 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2434 if(*ppdata == NULL ) {
2435 reply_nterror(req, NT_STATUS_NO_MEMORY);
2436 goto out;
2438 pdata = *ppdata;
2439 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2441 /* Realloc the params space */
2442 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2443 if (*pparams == NULL) {
2444 reply_nterror(req, NT_STATUS_NO_MEMORY);
2445 goto out;
2447 params = *pparams;
2449 /* Save the wildcard match and attribs we are using on this directory -
2450 needed as lanman2 assumes these are being saved between calls */
2452 ntstatus = dptr_create(conn,
2453 NULL, /* fsp */
2454 directory,
2455 False,
2456 True,
2457 req->smbpid,
2458 mask,
2459 mask_contains_wcard,
2460 dirtype,
2461 &dirptr);
2463 if (!NT_STATUS_IS_OK(ntstatus)) {
2464 reply_nterror(req, ntstatus);
2465 goto out;
2468 dptr_num = dptr_dnum(dirptr);
2469 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2471 /* Initialize per TRANS2_FIND_FIRST operation data */
2472 dptr_init_search_op(dirptr);
2474 /* We don't need to check for VOL here as this is returned by
2475 a different TRANS2 call. */
2477 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2478 directory,lp_dontdescend(SNUM(conn))));
2479 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2480 dont_descend = True;
2482 p = pdata;
2483 space_remaining = max_data_bytes;
2484 out_of_space = False;
2486 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2487 bool got_exact_match = False;
2489 /* this is a heuristic to avoid seeking the dirptr except when
2490 absolutely necessary. It allows for a filename of about 40 chars */
2491 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2492 out_of_space = True;
2493 finished = False;
2494 } else {
2495 finished = !get_lanman2_dir_entry(ctx,
2496 conn,
2497 dirptr,
2498 req->flags2,
2499 mask,dirtype,info_level,
2500 requires_resume_key,dont_descend,
2501 ask_sharemode,
2502 &p,pdata,data_end,
2503 space_remaining, &out_of_space,
2504 &got_exact_match,
2505 &last_entry_off, ea_list);
2508 if (finished && out_of_space)
2509 finished = False;
2511 if (!finished && !out_of_space)
2512 numentries++;
2515 * As an optimisation if we know we aren't looking
2516 * for a wildcard name (ie. the name matches the wildcard exactly)
2517 * then we can finish on any (first) match.
2518 * This speeds up large directory searches. JRA.
2521 if(got_exact_match)
2522 finished = True;
2524 /* Ensure space_remaining never goes -ve. */
2525 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2526 space_remaining = 0;
2527 out_of_space = true;
2528 } else {
2529 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2533 /* Check if we can close the dirptr */
2534 if(close_after_first || (finished && close_if_end)) {
2535 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2536 dptr_close(sconn, &dptr_num);
2540 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2541 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2542 * the protocol level is less than NT1. Tested with smbclient. JRA.
2543 * This should fix the OS/2 client bug #2335.
2546 if(numentries == 0) {
2547 dptr_close(sconn, &dptr_num);
2548 if (get_Protocol() < PROTOCOL_NT1) {
2549 reply_force_doserror(req, ERRDOS, ERRnofiles);
2550 goto out;
2551 } else {
2552 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2553 ERRDOS, ERRbadfile);
2554 goto out;
2558 /* At this point pdata points to numentries directory entries. */
2560 /* Set up the return parameter block */
2561 SSVAL(params,0,dptr_num);
2562 SSVAL(params,2,numentries);
2563 SSVAL(params,4,finished);
2564 SSVAL(params,6,0); /* Never an EA error */
2565 SSVAL(params,8,last_entry_off);
2567 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2568 max_data_bytes);
2570 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2571 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2572 if (!directory) {
2573 reply_nterror(req, NT_STATUS_NO_MEMORY);
2577 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2578 smb_fn_name(req->cmd),
2579 mask, directory, dirtype, numentries ) );
2582 * Force a name mangle here to ensure that the
2583 * mask as an 8.3 name is top of the mangled cache.
2584 * The reasons for this are subtle. Don't remove
2585 * this code unless you know what you are doing
2586 * (see PR#13758). JRA.
2589 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2590 char mangled_name[13];
2591 name_to_8_3(mask, mangled_name, True, conn->params);
2593 out:
2594 TALLOC_FREE(smb_dname);
2595 return;
2598 /****************************************************************************
2599 Reply to a TRANS2_FINDNEXT.
2600 ****************************************************************************/
2602 static void call_trans2findnext(connection_struct *conn,
2603 struct smb_request *req,
2604 char **pparams, int total_params,
2605 char **ppdata, int total_data,
2606 unsigned int max_data_bytes)
2608 /* We must be careful here that we don't return more than the
2609 allowed number of data bytes. If this means returning fewer than
2610 maxentries then so be it. We assume that the redirector has
2611 enough room for the fixed number of parameter bytes it has
2612 requested. */
2613 char *params = *pparams;
2614 char *pdata = *ppdata;
2615 char *data_end;
2616 int dptr_num;
2617 int maxentries;
2618 uint16 info_level;
2619 uint32 resume_key;
2620 uint16 findnext_flags;
2621 bool close_after_request;
2622 bool close_if_end;
2623 bool requires_resume_key;
2624 bool continue_bit;
2625 bool mask_contains_wcard = False;
2626 char *resume_name = NULL;
2627 const char *mask = NULL;
2628 const char *directory = NULL;
2629 char *p = NULL;
2630 uint16 dirtype;
2631 int numentries = 0;
2632 int i, last_entry_off=0;
2633 bool finished = False;
2634 bool dont_descend = False;
2635 bool out_of_space = False;
2636 int space_remaining;
2637 struct ea_list *ea_list = NULL;
2638 NTSTATUS ntstatus = NT_STATUS_OK;
2639 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2640 TALLOC_CTX *ctx = talloc_tos();
2641 struct dptr_struct *dirptr;
2642 struct smbd_server_connection *sconn = req->sconn;
2644 if (total_params < 13) {
2645 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2646 return;
2649 dptr_num = SVAL(params,0);
2650 maxentries = SVAL(params,2);
2651 info_level = SVAL(params,4);
2652 resume_key = IVAL(params,6);
2653 findnext_flags = SVAL(params,10);
2654 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2655 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2656 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2657 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2659 if (!continue_bit) {
2660 /* We only need resume_name if continue_bit is zero. */
2661 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2662 params+12,
2663 total_params - 12, STR_TERMINATE, &ntstatus,
2664 &mask_contains_wcard);
2665 if (!NT_STATUS_IS_OK(ntstatus)) {
2666 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2667 complain (it thinks we're asking for the directory above the shared
2668 path or an invalid name). Catch this as the resume name is only compared, never used in
2669 a file access. JRA. */
2670 srvstr_pull_talloc(ctx, params, req->flags2,
2671 &resume_name, params+12,
2672 total_params - 12,
2673 STR_TERMINATE);
2675 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2676 reply_nterror(req, ntstatus);
2677 return;
2682 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2683 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2684 resume_key = %d resume name = %s continue=%d level = %d\n",
2685 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2686 requires_resume_key, resume_key,
2687 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2689 if (!maxentries) {
2690 /* W2K3 seems to treat zero as 1. */
2691 maxentries = 1;
2694 switch (info_level) {
2695 case SMB_FIND_INFO_STANDARD:
2696 case SMB_FIND_EA_SIZE:
2697 case SMB_FIND_EA_LIST:
2698 case SMB_FIND_FILE_DIRECTORY_INFO:
2699 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2700 case SMB_FIND_FILE_NAMES_INFO:
2701 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2702 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2703 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2704 break;
2705 case SMB_FIND_FILE_UNIX:
2706 case SMB_FIND_FILE_UNIX_INFO2:
2707 /* Always use filesystem for UNIX mtime query. */
2708 ask_sharemode = false;
2709 if (!lp_unix_extensions()) {
2710 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2711 return;
2713 break;
2714 default:
2715 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2716 return;
2719 if (info_level == SMB_FIND_EA_LIST) {
2720 uint32 ea_size;
2722 if (total_data < 4) {
2723 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2724 return;
2727 ea_size = IVAL(pdata,0);
2728 if (ea_size != total_data) {
2729 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2730 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2731 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2732 return;
2735 if (!lp_ea_support(SNUM(conn))) {
2736 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2737 return;
2740 /* Pull out the list of names. */
2741 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2742 if (!ea_list) {
2743 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2744 return;
2748 *ppdata = (char *)SMB_REALLOC(
2749 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2750 if(*ppdata == NULL) {
2751 reply_nterror(req, NT_STATUS_NO_MEMORY);
2752 return;
2755 pdata = *ppdata;
2756 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2758 /* Realloc the params space */
2759 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2760 if(*pparams == NULL ) {
2761 reply_nterror(req, NT_STATUS_NO_MEMORY);
2762 return;
2765 params = *pparams;
2767 /* Check that the dptr is valid */
2768 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2769 reply_nterror(req, STATUS_NO_MORE_FILES);
2770 return;
2773 directory = dptr_path(sconn, dptr_num);
2775 /* Get the wildcard mask from the dptr */
2776 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2777 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2778 reply_nterror(req, STATUS_NO_MORE_FILES);
2779 return;
2782 mask = p;
2784 /* Get the attr mask from the dptr */
2785 dirtype = dptr_attr(sconn, dptr_num);
2787 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2788 dptr_num, mask, dirtype,
2789 (long)dirptr,
2790 dptr_TellDir(dirptr)));
2792 /* Initialize per TRANS2_FIND_NEXT operation data */
2793 dptr_init_search_op(dirptr);
2795 /* We don't need to check for VOL here as this is returned by
2796 a different TRANS2 call. */
2798 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2799 directory,lp_dontdescend(SNUM(conn))));
2800 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2801 dont_descend = True;
2803 p = pdata;
2804 space_remaining = max_data_bytes;
2805 out_of_space = False;
2808 * Seek to the correct position. We no longer use the resume key but
2809 * depend on the last file name instead.
2812 if(!continue_bit && resume_name && *resume_name) {
2813 SMB_STRUCT_STAT st;
2815 long current_pos = 0;
2817 * Remember, name_to_8_3 is called by
2818 * get_lanman2_dir_entry(), so the resume name
2819 * could be mangled. Ensure we check the unmangled name.
2822 if (mangle_is_mangled(resume_name, conn->params)) {
2823 char *new_resume_name = NULL;
2824 mangle_lookup_name_from_8_3(ctx,
2825 resume_name,
2826 &new_resume_name,
2827 conn->params);
2828 if (new_resume_name) {
2829 resume_name = new_resume_name;
2834 * Fix for NT redirector problem triggered by resume key indexes
2835 * changing between directory scans. We now return a resume key of 0
2836 * and instead look for the filename to continue from (also given
2837 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2838 * findfirst/findnext (as is usual) then the directory pointer
2839 * should already be at the correct place.
2842 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2843 } /* end if resume_name && !continue_bit */
2845 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2846 bool got_exact_match = False;
2848 /* this is a heuristic to avoid seeking the dirptr except when
2849 absolutely necessary. It allows for a filename of about 40 chars */
2850 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2851 out_of_space = True;
2852 finished = False;
2853 } else {
2854 finished = !get_lanman2_dir_entry(ctx,
2855 conn,
2856 dirptr,
2857 req->flags2,
2858 mask,dirtype,info_level,
2859 requires_resume_key,dont_descend,
2860 ask_sharemode,
2861 &p,pdata,data_end,
2862 space_remaining, &out_of_space,
2863 &got_exact_match,
2864 &last_entry_off, ea_list);
2867 if (finished && out_of_space)
2868 finished = False;
2870 if (!finished && !out_of_space)
2871 numentries++;
2874 * As an optimisation if we know we aren't looking
2875 * for a wildcard name (ie. the name matches the wildcard exactly)
2876 * then we can finish on any (first) match.
2877 * This speeds up large directory searches. JRA.
2880 if(got_exact_match)
2881 finished = True;
2883 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2886 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2887 smb_fn_name(req->cmd),
2888 mask, directory, dirtype, numentries ) );
2890 /* Check if we can close the dirptr */
2891 if(close_after_request || (finished && close_if_end)) {
2892 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2893 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2896 /* Set up the return parameter block */
2897 SSVAL(params,0,numentries);
2898 SSVAL(params,2,finished);
2899 SSVAL(params,4,0); /* Never an EA error */
2900 SSVAL(params,6,last_entry_off);
2902 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2903 max_data_bytes);
2905 return;
2908 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2910 E_md4hash(lp_servicename(SNUM(conn)),objid);
2911 return objid;
2914 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2916 SMB_ASSERT(extended_info != NULL);
2918 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2919 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2920 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2921 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2922 #ifdef SAMBA_VERSION_REVISION
2923 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2924 #endif
2925 extended_info->samba_subversion = 0;
2926 #ifdef SAMBA_VERSION_RC_RELEASE
2927 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2928 #else
2929 #ifdef SAMBA_VERSION_PRE_RELEASE
2930 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2931 #endif
2932 #endif
2933 #ifdef SAMBA_VERSION_VENDOR_PATCH
2934 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2935 #endif
2936 extended_info->samba_gitcommitdate = 0;
2937 #ifdef SAMBA_VERSION_COMMIT_TIME
2938 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2939 #endif
2941 memset(extended_info->samba_version_string, 0,
2942 sizeof(extended_info->samba_version_string));
2944 snprintf (extended_info->samba_version_string,
2945 sizeof(extended_info->samba_version_string),
2946 "%s", samba_version_string());
2949 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2950 TALLOC_CTX *mem_ctx,
2951 uint16_t info_level,
2952 uint16_t flags2,
2953 unsigned int max_data_bytes,
2954 char **ppdata,
2955 int *ret_data_len)
2957 char *pdata, *end_data;
2958 int data_len = 0, len;
2959 const char *vname = volume_label(SNUM(conn));
2960 int snum = SNUM(conn);
2961 char *fstype = lp_fstype(SNUM(conn));
2962 uint32 additional_flags = 0;
2963 struct smb_filename smb_fname_dot;
2964 SMB_STRUCT_STAT st;
2966 if (IS_IPC(conn)) {
2967 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2968 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2969 "info level (0x%x) on IPC$.\n",
2970 (unsigned int)info_level));
2971 return NT_STATUS_ACCESS_DENIED;
2975 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2977 ZERO_STRUCT(smb_fname_dot);
2978 smb_fname_dot.base_name = discard_const_p(char, ".");
2980 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2981 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2982 return map_nt_error_from_unix(errno);
2985 st = smb_fname_dot.st;
2987 *ppdata = (char *)SMB_REALLOC(
2988 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2989 if (*ppdata == NULL) {
2990 return NT_STATUS_NO_MEMORY;
2993 pdata = *ppdata;
2994 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2995 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2997 switch (info_level) {
2998 case SMB_INFO_ALLOCATION:
3000 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3001 data_len = 18;
3002 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3003 return map_nt_error_from_unix(errno);
3006 block_size = lp_block_size(snum);
3007 if (bsize < block_size) {
3008 uint64_t factor = block_size/bsize;
3009 bsize = block_size;
3010 dsize /= factor;
3011 dfree /= factor;
3013 if (bsize > block_size) {
3014 uint64_t factor = bsize/block_size;
3015 bsize = block_size;
3016 dsize *= factor;
3017 dfree *= factor;
3019 bytes_per_sector = 512;
3020 sectors_per_unit = bsize/bytes_per_sector;
3022 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3023 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3024 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3026 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3027 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3028 SIVAL(pdata,l1_cUnit,dsize);
3029 SIVAL(pdata,l1_cUnitAvail,dfree);
3030 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3031 break;
3034 case SMB_INFO_VOLUME:
3035 /* Return volume name */
3037 * Add volume serial number - hash of a combination of
3038 * the called hostname and the service name.
3040 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3042 * Win2k3 and previous mess this up by sending a name length
3043 * one byte short. I believe only older clients (OS/2 Win9x) use
3044 * this call so try fixing this by adding a terminating null to
3045 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3047 len = srvstr_push(
3048 pdata, flags2,
3049 pdata+l2_vol_szVolLabel, vname,
3050 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3051 STR_NOALIGN|STR_TERMINATE);
3052 SCVAL(pdata,l2_vol_cch,len);
3053 data_len = l2_vol_szVolLabel + len;
3054 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3055 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3056 len, vname));
3057 break;
3059 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3060 case SMB_FS_ATTRIBUTE_INFORMATION:
3062 additional_flags = 0;
3063 #if defined(HAVE_SYS_QUOTAS)
3064 additional_flags |= FILE_VOLUME_QUOTAS;
3065 #endif
3067 if(lp_nt_acl_support(SNUM(conn))) {
3068 additional_flags |= FILE_PERSISTENT_ACLS;
3071 /* Capabilities are filled in at connection time through STATVFS call */
3072 additional_flags |= conn->fs_capabilities;
3073 additional_flags |= lp_parm_int(conn->params->service,
3074 "share", "fake_fscaps",
3077 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3078 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3079 additional_flags); /* FS ATTRIBUTES */
3081 SIVAL(pdata,4,255); /* Max filename component length */
3082 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3083 and will think we can't do long filenames */
3084 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3085 PTR_DIFF(end_data, pdata+12),
3086 STR_UNICODE);
3087 SIVAL(pdata,8,len);
3088 data_len = 12 + len;
3089 break;
3091 case SMB_QUERY_FS_LABEL_INFO:
3092 case SMB_FS_LABEL_INFORMATION:
3093 len = srvstr_push(pdata, flags2, pdata+4, vname,
3094 PTR_DIFF(end_data, pdata+4), 0);
3095 data_len = 4 + len;
3096 SIVAL(pdata,0,len);
3097 break;
3099 case SMB_QUERY_FS_VOLUME_INFO:
3100 case SMB_FS_VOLUME_INFORMATION:
3103 * Add volume serial number - hash of a combination of
3104 * the called hostname and the service name.
3106 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3107 (str_checksum(get_local_machine_name())<<16));
3109 /* Max label len is 32 characters. */
3110 len = srvstr_push(pdata, flags2, pdata+18, vname,
3111 PTR_DIFF(end_data, pdata+18),
3112 STR_UNICODE);
3113 SIVAL(pdata,12,len);
3114 data_len = 18+len;
3116 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3117 (int)strlen(vname),vname, lp_servicename(snum)));
3118 break;
3120 case SMB_QUERY_FS_SIZE_INFO:
3121 case SMB_FS_SIZE_INFORMATION:
3123 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3124 data_len = 24;
3125 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3126 return map_nt_error_from_unix(errno);
3128 block_size = lp_block_size(snum);
3129 if (bsize < block_size) {
3130 uint64_t factor = block_size/bsize;
3131 bsize = block_size;
3132 dsize /= factor;
3133 dfree /= factor;
3135 if (bsize > block_size) {
3136 uint64_t factor = bsize/block_size;
3137 bsize = block_size;
3138 dsize *= factor;
3139 dfree *= factor;
3141 bytes_per_sector = 512;
3142 sectors_per_unit = bsize/bytes_per_sector;
3143 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3144 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3145 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3146 SBIG_UINT(pdata,0,dsize);
3147 SBIG_UINT(pdata,8,dfree);
3148 SIVAL(pdata,16,sectors_per_unit);
3149 SIVAL(pdata,20,bytes_per_sector);
3150 break;
3153 case SMB_FS_FULL_SIZE_INFORMATION:
3155 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3156 data_len = 32;
3157 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3158 return map_nt_error_from_unix(errno);
3160 block_size = lp_block_size(snum);
3161 if (bsize < block_size) {
3162 uint64_t factor = block_size/bsize;
3163 bsize = block_size;
3164 dsize /= factor;
3165 dfree /= factor;
3167 if (bsize > block_size) {
3168 uint64_t factor = bsize/block_size;
3169 bsize = block_size;
3170 dsize *= factor;
3171 dfree *= factor;
3173 bytes_per_sector = 512;
3174 sectors_per_unit = bsize/bytes_per_sector;
3175 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3176 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3177 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3178 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3179 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3180 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3181 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3182 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3183 break;
3186 case SMB_QUERY_FS_DEVICE_INFO:
3187 case SMB_FS_DEVICE_INFORMATION:
3189 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3191 if (!CAN_WRITE(conn)) {
3192 characteristics |= FILE_READ_ONLY_DEVICE;
3194 data_len = 8;
3195 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3196 SIVAL(pdata,4,characteristics);
3197 break;
3200 #ifdef HAVE_SYS_QUOTAS
3201 case SMB_FS_QUOTA_INFORMATION:
3203 * what we have to send --metze:
3205 * Unknown1: 24 NULL bytes
3206 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3207 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3208 * Quota Flags: 2 byte :
3209 * Unknown3: 6 NULL bytes
3211 * 48 bytes total
3213 * details for Quota Flags:
3215 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3216 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3217 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3218 * 0x0001 Enable Quotas: enable quota for this fs
3222 /* we need to fake up a fsp here,
3223 * because its not send in this call
3225 files_struct fsp;
3226 SMB_NTQUOTA_STRUCT quotas;
3228 ZERO_STRUCT(fsp);
3229 ZERO_STRUCT(quotas);
3231 fsp.conn = conn;
3232 fsp.fnum = -1;
3234 /* access check */
3235 if (get_current_uid(conn) != 0) {
3236 DEBUG(0,("set_user_quota: access_denied "
3237 "service [%s] user [%s]\n",
3238 lp_servicename(SNUM(conn)),
3239 conn->session_info->unix_info->unix_name));
3240 return NT_STATUS_ACCESS_DENIED;
3243 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3244 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3245 return map_nt_error_from_unix(errno);
3248 data_len = 48;
3250 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3251 lp_servicename(SNUM(conn))));
3253 /* Unknown1 24 NULL bytes*/
3254 SBIG_UINT(pdata,0,(uint64_t)0);
3255 SBIG_UINT(pdata,8,(uint64_t)0);
3256 SBIG_UINT(pdata,16,(uint64_t)0);
3258 /* Default Soft Quota 8 bytes */
3259 SBIG_UINT(pdata,24,quotas.softlim);
3261 /* Default Hard Quota 8 bytes */
3262 SBIG_UINT(pdata,32,quotas.hardlim);
3264 /* Quota flag 2 bytes */
3265 SSVAL(pdata,40,quotas.qflags);
3267 /* Unknown3 6 NULL bytes */
3268 SSVAL(pdata,42,0);
3269 SIVAL(pdata,44,0);
3271 break;
3273 #endif /* HAVE_SYS_QUOTAS */
3274 case SMB_FS_OBJECTID_INFORMATION:
3276 unsigned char objid[16];
3277 struct smb_extended_info extended_info;
3278 memcpy(pdata,create_volume_objectid(conn, objid),16);
3279 samba_extended_info_version (&extended_info);
3280 SIVAL(pdata,16,extended_info.samba_magic);
3281 SIVAL(pdata,20,extended_info.samba_version);
3282 SIVAL(pdata,24,extended_info.samba_subversion);
3283 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3284 memcpy(pdata+36,extended_info.samba_version_string,28);
3285 data_len = 64;
3286 break;
3290 * Query the version and capabilities of the CIFS UNIX extensions
3291 * in use.
3294 case SMB_QUERY_CIFS_UNIX_INFO:
3296 bool large_write = lp_min_receive_file_size() &&
3297 !srv_is_signing_active(conn->sconn);
3298 bool large_read = !srv_is_signing_active(conn->sconn);
3299 int encrypt_caps = 0;
3301 if (!lp_unix_extensions()) {
3302 return NT_STATUS_INVALID_LEVEL;
3305 switch (conn->encrypt_level) {
3306 case 0:
3307 encrypt_caps = 0;
3308 break;
3309 case 1:
3310 case Auto:
3311 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3312 break;
3313 case Required:
3314 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3315 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3316 large_write = false;
3317 large_read = false;
3318 break;
3321 data_len = 12;
3322 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3323 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3325 /* We have POSIX ACLs, pathname, encryption,
3326 * large read/write, and locking capability. */
3328 SBIG_UINT(pdata,4,((uint64_t)(
3329 CIFS_UNIX_POSIX_ACLS_CAP|
3330 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3331 CIFS_UNIX_FCNTL_LOCKS_CAP|
3332 CIFS_UNIX_EXTATTR_CAP|
3333 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3334 encrypt_caps|
3335 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3336 (large_write ?
3337 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3338 break;
3341 case SMB_QUERY_POSIX_FS_INFO:
3343 int rc;
3344 vfs_statvfs_struct svfs;
3346 if (!lp_unix_extensions()) {
3347 return NT_STATUS_INVALID_LEVEL;
3350 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3352 if (!rc) {
3353 data_len = 56;
3354 SIVAL(pdata,0,svfs.OptimalTransferSize);
3355 SIVAL(pdata,4,svfs.BlockSize);
3356 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3357 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3358 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3359 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3360 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3361 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3362 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3363 #ifdef EOPNOTSUPP
3364 } else if (rc == EOPNOTSUPP) {
3365 return NT_STATUS_INVALID_LEVEL;
3366 #endif /* EOPNOTSUPP */
3367 } else {
3368 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3369 return NT_STATUS_DOS(ERRSRV, ERRerror);
3371 break;
3374 case SMB_QUERY_POSIX_WHOAMI:
3376 uint32_t flags = 0;
3377 uint32_t sid_bytes;
3378 int i;
3380 if (!lp_unix_extensions()) {
3381 return NT_STATUS_INVALID_LEVEL;
3384 if (max_data_bytes < 40) {
3385 return NT_STATUS_BUFFER_TOO_SMALL;
3388 /* We ARE guest if global_sid_Builtin_Guests is
3389 * in our list of SIDs.
3391 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3392 conn->session_info->security_token)) {
3393 flags |= SMB_WHOAMI_GUEST;
3396 /* We are NOT guest if global_sid_Authenticated_Users
3397 * is in our list of SIDs.
3399 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3400 conn->session_info->security_token)) {
3401 flags &= ~SMB_WHOAMI_GUEST;
3404 /* NOTE: 8 bytes for UID/GID, irrespective of native
3405 * platform size. This matches
3406 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3408 data_len = 4 /* flags */
3409 + 4 /* flag mask */
3410 + 8 /* uid */
3411 + 8 /* gid */
3412 + 4 /* ngroups */
3413 + 4 /* num_sids */
3414 + 4 /* SID bytes */
3415 + 4 /* pad/reserved */
3416 + (conn->session_info->unix_token->ngroups * 8)
3417 /* groups list */
3418 + (conn->session_info->security_token->num_sids *
3419 SID_MAX_SIZE)
3420 /* SID list */;
3422 SIVAL(pdata, 0, flags);
3423 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3424 SBIG_UINT(pdata, 8,
3425 (uint64_t)conn->session_info->unix_token->uid);
3426 SBIG_UINT(pdata, 16,
3427 (uint64_t)conn->session_info->unix_token->gid);
3430 if (data_len >= max_data_bytes) {
3431 /* Potential overflow, skip the GIDs and SIDs. */
3433 SIVAL(pdata, 24, 0); /* num_groups */
3434 SIVAL(pdata, 28, 0); /* num_sids */
3435 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3436 SIVAL(pdata, 36, 0); /* reserved */
3438 data_len = 40;
3439 break;
3442 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3443 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3445 /* We walk the SID list twice, but this call is fairly
3446 * infrequent, and I don't expect that it's performance
3447 * sensitive -- jpeach
3449 for (i = 0, sid_bytes = 0;
3450 i < conn->session_info->security_token->num_sids; ++i) {
3451 sid_bytes += ndr_size_dom_sid(
3452 &conn->session_info->security_token->sids[i],
3456 /* SID list byte count */
3457 SIVAL(pdata, 32, sid_bytes);
3459 /* 4 bytes pad/reserved - must be zero */
3460 SIVAL(pdata, 36, 0);
3461 data_len = 40;
3463 /* GID list */
3464 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3465 SBIG_UINT(pdata, data_len,
3466 (uint64_t)conn->session_info->unix_token->groups[i]);
3467 data_len += 8;
3470 /* SID list */
3471 for (i = 0;
3472 i < conn->session_info->security_token->num_sids; ++i) {
3473 int sid_len = ndr_size_dom_sid(
3474 &conn->session_info->security_token->sids[i],
3477 sid_linearize(pdata + data_len, sid_len,
3478 &conn->session_info->security_token->sids[i]);
3479 data_len += sid_len;
3482 break;
3485 case SMB_MAC_QUERY_FS_INFO:
3487 * Thursby MAC extension... ONLY on NTFS filesystems
3488 * once we do streams then we don't need this
3490 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3491 data_len = 88;
3492 SIVAL(pdata,84,0x100); /* Don't support mac... */
3493 break;
3495 /* drop through */
3496 default:
3497 return NT_STATUS_INVALID_LEVEL;
3500 *ret_data_len = data_len;
3501 return NT_STATUS_OK;
3504 /****************************************************************************
3505 Reply to a TRANS2_QFSINFO (query filesystem info).
3506 ****************************************************************************/
3508 static void call_trans2qfsinfo(connection_struct *conn,
3509 struct smb_request *req,
3510 char **pparams, int total_params,
3511 char **ppdata, int total_data,
3512 unsigned int max_data_bytes)
3514 char *params = *pparams;
3515 uint16_t info_level;
3516 int data_len = 0;
3517 NTSTATUS status;
3519 if (total_params < 2) {
3520 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3521 return;
3524 info_level = SVAL(params,0);
3526 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3527 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3528 DEBUG(0,("call_trans2qfsinfo: encryption required "
3529 "and info level 0x%x sent.\n",
3530 (unsigned int)info_level));
3531 exit_server_cleanly("encryption required "
3532 "on connection");
3533 return;
3537 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3539 status = smbd_do_qfsinfo(conn, req,
3540 info_level,
3541 req->flags2,
3542 max_data_bytes,
3543 ppdata, &data_len);
3544 if (!NT_STATUS_IS_OK(status)) {
3545 reply_nterror(req, status);
3546 return;
3549 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3550 max_data_bytes);
3552 DEBUG( 4, ( "%s info_level = %d\n",
3553 smb_fn_name(req->cmd), info_level) );
3555 return;
3558 /****************************************************************************
3559 Reply to a TRANS2_SETFSINFO (set filesystem info).
3560 ****************************************************************************/
3562 static void call_trans2setfsinfo(connection_struct *conn,
3563 struct smb_request *req,
3564 char **pparams, int total_params,
3565 char **ppdata, int total_data,
3566 unsigned int max_data_bytes)
3568 struct smbd_server_connection *sconn = req->sconn;
3569 char *pdata = *ppdata;
3570 char *params = *pparams;
3571 uint16 info_level;
3573 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3575 /* */
3576 if (total_params < 4) {
3577 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3578 total_params));
3579 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3580 return;
3583 info_level = SVAL(params,2);
3585 if (IS_IPC(conn)) {
3586 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3587 info_level != SMB_SET_CIFS_UNIX_INFO) {
3588 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3589 "info level (0x%x) on IPC$.\n",
3590 (unsigned int)info_level));
3591 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3592 return;
3596 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3597 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3598 DEBUG(0,("call_trans2setfsinfo: encryption required "
3599 "and info level 0x%x sent.\n",
3600 (unsigned int)info_level));
3601 exit_server_cleanly("encryption required "
3602 "on connection");
3603 return;
3607 switch(info_level) {
3608 case SMB_SET_CIFS_UNIX_INFO:
3609 if (!lp_unix_extensions()) {
3610 reply_nterror(req,
3611 NT_STATUS_INVALID_LEVEL);
3612 return;
3615 /* There should be 12 bytes of capabilities set. */
3616 if (total_data < 8) {
3617 reply_nterror(
3618 req,
3619 NT_STATUS_INVALID_PARAMETER);
3620 return;
3622 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3623 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3624 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3625 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3626 /* Just print these values for now. */
3627 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3628 "major = %u, minor = %u cap_low = 0x%x, "
3629 "cap_high = 0x%xn",
3630 (unsigned int)sconn->
3631 smb1.unix_info.client_major,
3632 (unsigned int)sconn->
3633 smb1.unix_info.client_minor,
3634 (unsigned int)sconn->
3635 smb1.unix_info.client_cap_low,
3636 (unsigned int)sconn->
3637 smb1.unix_info.client_cap_high));
3639 /* Here is where we must switch to posix pathname processing... */
3640 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3641 lp_set_posix_pathnames();
3642 mangle_change_to_posix();
3645 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3646 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3647 /* Client that knows how to do posix locks,
3648 * but not posix open/mkdir operations. Set a
3649 * default type for read/write checks. */
3651 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3654 break;
3656 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3658 NTSTATUS status;
3659 size_t param_len = 0;
3660 size_t data_len = total_data;
3662 if (!lp_unix_extensions()) {
3663 reply_nterror(
3664 req,
3665 NT_STATUS_INVALID_LEVEL);
3666 return;
3669 if (lp_smb_encrypt(SNUM(conn)) == false) {
3670 reply_nterror(
3671 req,
3672 NT_STATUS_NOT_SUPPORTED);
3673 return;
3676 if (req->sconn->smb1.echo_handler.trusted_fde) {
3677 DEBUG( 2,("call_trans2setfsinfo: "
3678 "request transport encryption disabled"
3679 "with 'fork echo handler = yes'\n"));
3680 reply_nterror(
3681 req,
3682 NT_STATUS_NOT_SUPPORTED);
3683 return;
3686 DEBUG( 4,("call_trans2setfsinfo: "
3687 "request transport encryption.\n"));
3689 status = srv_request_encryption_setup(conn,
3690 (unsigned char **)ppdata,
3691 &data_len,
3692 (unsigned char **)pparams,
3693 &param_len);
3695 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3696 !NT_STATUS_IS_OK(status)) {
3697 reply_nterror(req, status);
3698 return;
3701 send_trans2_replies(conn, req,
3702 *pparams,
3703 param_len,
3704 *ppdata,
3705 data_len,
3706 max_data_bytes);
3708 if (NT_STATUS_IS_OK(status)) {
3709 /* Server-side transport
3710 * encryption is now *on*. */
3711 status = srv_encryption_start(conn);
3712 if (!NT_STATUS_IS_OK(status)) {
3713 char *reason = talloc_asprintf(talloc_tos(),
3714 "Failure in setting "
3715 "up encrypted transport: %s",
3716 nt_errstr(status));
3717 exit_server_cleanly(reason);
3720 return;
3723 case SMB_FS_QUOTA_INFORMATION:
3725 files_struct *fsp = NULL;
3726 SMB_NTQUOTA_STRUCT quotas;
3728 ZERO_STRUCT(quotas);
3730 /* access check */
3731 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3732 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3733 lp_servicename(SNUM(conn)),
3734 conn->session_info->unix_info->unix_name));
3735 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3736 return;
3739 /* note: normaly there're 48 bytes,
3740 * but we didn't use the last 6 bytes for now
3741 * --metze
3743 fsp = file_fsp(req, SVAL(params,0));
3745 if (!check_fsp_ntquota_handle(conn, req,
3746 fsp)) {
3747 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3748 reply_nterror(
3749 req, NT_STATUS_INVALID_HANDLE);
3750 return;
3753 if (total_data < 42) {
3754 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3755 total_data));
3756 reply_nterror(
3757 req,
3758 NT_STATUS_INVALID_PARAMETER);
3759 return;
3762 /* unknown_1 24 NULL bytes in pdata*/
3764 /* the soft quotas 8 bytes (uint64_t)*/
3765 quotas.softlim = BVAL(pdata,24);
3767 /* the hard quotas 8 bytes (uint64_t)*/
3768 quotas.hardlim = BVAL(pdata,32);
3770 /* quota_flags 2 bytes **/
3771 quotas.qflags = SVAL(pdata,40);
3773 /* unknown_2 6 NULL bytes follow*/
3775 /* now set the quotas */
3776 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3777 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3778 reply_nterror(req, map_nt_error_from_unix(errno));
3779 return;
3782 break;
3784 default:
3785 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3786 info_level));
3787 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3788 return;
3789 break;
3793 * sending this reply works fine,
3794 * but I'm not sure it's the same
3795 * like windows do...
3796 * --metze
3798 reply_outbuf(req, 10, 0);
3801 #if defined(HAVE_POSIX_ACLS)
3802 /****************************************************************************
3803 Utility function to count the number of entries in a POSIX acl.
3804 ****************************************************************************/
3806 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3808 unsigned int ace_count = 0;
3809 int entry_id = SMB_ACL_FIRST_ENTRY;
3810 SMB_ACL_ENTRY_T entry;
3812 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3813 /* get_next... */
3814 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3815 entry_id = SMB_ACL_NEXT_ENTRY;
3817 ace_count++;
3819 return ace_count;
3822 /****************************************************************************
3823 Utility function to marshall a POSIX acl into wire format.
3824 ****************************************************************************/
3826 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3828 int entry_id = SMB_ACL_FIRST_ENTRY;
3829 SMB_ACL_ENTRY_T entry;
3831 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3832 SMB_ACL_TAG_T tagtype;
3833 SMB_ACL_PERMSET_T permset;
3834 unsigned char perms = 0;
3835 unsigned int own_grp;
3837 /* get_next... */
3838 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3839 entry_id = SMB_ACL_NEXT_ENTRY;
3842 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3843 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3844 return False;
3847 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3848 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3849 return False;
3852 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3853 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3854 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3856 SCVAL(pdata,1,perms);
3858 switch (tagtype) {
3859 case SMB_ACL_USER_OBJ:
3860 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3861 own_grp = (unsigned int)pst->st_ex_uid;
3862 SIVAL(pdata,2,own_grp);
3863 SIVAL(pdata,6,0);
3864 break;
3865 case SMB_ACL_USER:
3867 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3868 if (!puid) {
3869 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3870 return False;
3872 own_grp = (unsigned int)*puid;
3873 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3874 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3875 SIVAL(pdata,2,own_grp);
3876 SIVAL(pdata,6,0);
3877 break;
3879 case SMB_ACL_GROUP_OBJ:
3880 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3881 own_grp = (unsigned int)pst->st_ex_gid;
3882 SIVAL(pdata,2,own_grp);
3883 SIVAL(pdata,6,0);
3884 break;
3885 case SMB_ACL_GROUP:
3887 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3888 if (!pgid) {
3889 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3890 return False;
3892 own_grp = (unsigned int)*pgid;
3893 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3894 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3895 SIVAL(pdata,2,own_grp);
3896 SIVAL(pdata,6,0);
3897 break;
3899 case SMB_ACL_MASK:
3900 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3901 SIVAL(pdata,2,0xFFFFFFFF);
3902 SIVAL(pdata,6,0xFFFFFFFF);
3903 break;
3904 case SMB_ACL_OTHER:
3905 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3906 SIVAL(pdata,2,0xFFFFFFFF);
3907 SIVAL(pdata,6,0xFFFFFFFF);
3908 break;
3909 default:
3910 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3911 return False;
3913 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3916 return True;
3918 #endif
3920 /****************************************************************************
3921 Store the FILE_UNIX_BASIC info.
3922 ****************************************************************************/
3924 static char *store_file_unix_basic(connection_struct *conn,
3925 char *pdata,
3926 files_struct *fsp,
3927 const SMB_STRUCT_STAT *psbuf)
3929 uint64_t file_index = get_FileIndex(conn, psbuf);
3931 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3932 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3934 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3935 pdata += 8;
3937 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3938 pdata += 8;
3940 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3941 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3942 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3943 pdata += 24;
3945 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3946 SIVAL(pdata,4,0);
3947 pdata += 8;
3949 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3950 SIVAL(pdata,4,0);
3951 pdata += 8;
3953 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3954 pdata += 4;
3956 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3957 SIVAL(pdata,4,0);
3958 pdata += 8;
3960 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3961 SIVAL(pdata,4,0);
3962 pdata += 8;
3964 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3965 pdata += 8;
3967 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3968 SIVAL(pdata,4,0);
3969 pdata += 8;
3971 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3972 SIVAL(pdata,4,0);
3973 pdata += 8;
3975 return pdata;
3978 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3979 * the chflags(2) (or equivalent) flags.
3981 * XXX: this really should be behind the VFS interface. To do this, we would
3982 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3983 * Each VFS module could then implement its own mapping as appropriate for the
3984 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3986 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3987 info2_flags_map[] =
3989 #ifdef UF_NODUMP
3990 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3991 #endif
3993 #ifdef UF_IMMUTABLE
3994 { UF_IMMUTABLE, EXT_IMMUTABLE },
3995 #endif
3997 #ifdef UF_APPEND
3998 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3999 #endif
4001 #ifdef UF_HIDDEN
4002 { UF_HIDDEN, EXT_HIDDEN },
4003 #endif
4005 /* Do not remove. We need to guarantee that this array has at least one
4006 * entry to build on HP-UX.
4008 { 0, 0 }
4012 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4013 uint32 *smb_fflags, uint32 *smb_fmask)
4015 int i;
4017 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4018 *smb_fmask |= info2_flags_map[i].smb_fflag;
4019 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4020 *smb_fflags |= info2_flags_map[i].smb_fflag;
4025 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4026 const uint32 smb_fflags,
4027 const uint32 smb_fmask,
4028 int *stat_fflags)
4030 uint32 max_fmask = 0;
4031 int i;
4033 *stat_fflags = psbuf->st_ex_flags;
4035 /* For each flags requested in smb_fmask, check the state of the
4036 * corresponding flag in smb_fflags and set or clear the matching
4037 * stat flag.
4040 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4041 max_fmask |= info2_flags_map[i].smb_fflag;
4042 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4043 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4044 *stat_fflags |= info2_flags_map[i].stat_fflag;
4045 } else {
4046 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4051 /* If smb_fmask is asking to set any bits that are not supported by
4052 * our flag mappings, we should fail.
4054 if ((smb_fmask & max_fmask) != smb_fmask) {
4055 return False;
4058 return True;
4062 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4063 * of file flags and birth (create) time.
4065 static char *store_file_unix_basic_info2(connection_struct *conn,
4066 char *pdata,
4067 files_struct *fsp,
4068 const SMB_STRUCT_STAT *psbuf)
4070 uint32 file_flags = 0;
4071 uint32 flags_mask = 0;
4073 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4075 /* Create (birth) time 64 bit */
4076 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4077 pdata += 8;
4079 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4080 SIVAL(pdata, 0, file_flags); /* flags */
4081 SIVAL(pdata, 4, flags_mask); /* mask */
4082 pdata += 8;
4084 return pdata;
4087 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4088 const struct stream_struct *streams,
4089 char *data,
4090 unsigned int max_data_bytes,
4091 unsigned int *data_size)
4093 unsigned int i;
4094 unsigned int ofs = 0;
4096 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4097 unsigned int next_offset;
4098 size_t namelen;
4099 smb_ucs2_t *namebuf;
4101 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4102 streams[i].name, &namelen) ||
4103 namelen <= 2)
4105 return NT_STATUS_INVALID_PARAMETER;
4109 * name_buf is now null-terminated, we need to marshall as not
4110 * terminated
4113 namelen -= 2;
4115 SIVAL(data, ofs+4, namelen);
4116 SOFF_T(data, ofs+8, streams[i].size);
4117 SOFF_T(data, ofs+16, streams[i].alloc_size);
4118 memcpy(data+ofs+24, namebuf, namelen);
4119 TALLOC_FREE(namebuf);
4121 next_offset = ofs + 24 + namelen;
4123 if (i == num_streams-1) {
4124 SIVAL(data, ofs, 0);
4126 else {
4127 unsigned int align = ndr_align_size(next_offset, 8);
4129 memset(data+next_offset, 0, align);
4130 next_offset += align;
4132 SIVAL(data, ofs, next_offset - ofs);
4133 ofs = next_offset;
4136 ofs = next_offset;
4139 *data_size = ofs;
4141 return NT_STATUS_OK;
4144 /****************************************************************************
4145 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4146 ****************************************************************************/
4148 static void call_trans2qpipeinfo(connection_struct *conn,
4149 struct smb_request *req,
4150 unsigned int tran_call,
4151 char **pparams, int total_params,
4152 char **ppdata, int total_data,
4153 unsigned int max_data_bytes)
4155 char *params = *pparams;
4156 char *pdata = *ppdata;
4157 unsigned int data_size = 0;
4158 unsigned int param_size = 2;
4159 uint16 info_level;
4160 files_struct *fsp;
4162 if (!params) {
4163 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4164 return;
4167 if (total_params < 4) {
4168 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4169 return;
4172 fsp = file_fsp(req, SVAL(params,0));
4173 if (!fsp_is_np(fsp)) {
4174 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4175 return;
4178 info_level = SVAL(params,2);
4180 *pparams = (char *)SMB_REALLOC(*pparams,2);
4181 if (*pparams == NULL) {
4182 reply_nterror(req, NT_STATUS_NO_MEMORY);
4183 return;
4185 params = *pparams;
4186 SSVAL(params,0,0);
4187 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4188 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4189 if (*ppdata == NULL ) {
4190 reply_nterror(req, NT_STATUS_NO_MEMORY);
4191 return;
4193 pdata = *ppdata;
4195 switch (info_level) {
4196 case SMB_FILE_STANDARD_INFORMATION:
4197 memset(pdata,0,24);
4198 SOFF_T(pdata,0,4096LL);
4199 SIVAL(pdata,16,1);
4200 SIVAL(pdata,20,1);
4201 data_size = 24;
4202 break;
4204 default:
4205 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4206 return;
4209 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4210 max_data_bytes);
4212 return;
4215 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4216 TALLOC_CTX *mem_ctx,
4217 uint16_t info_level,
4218 files_struct *fsp,
4219 struct smb_filename *smb_fname,
4220 bool delete_pending,
4221 struct timespec write_time_ts,
4222 struct ea_list *ea_list,
4223 int lock_data_count,
4224 char *lock_data,
4225 uint16_t flags2,
4226 unsigned int max_data_bytes,
4227 char **ppdata,
4228 unsigned int *pdata_size)
4230 char *pdata = *ppdata;
4231 char *dstart, *dend;
4232 unsigned int data_size;
4233 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4234 time_t create_time, mtime, atime, c_time;
4235 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4236 char *p;
4237 char *base_name;
4238 char *dos_fname;
4239 int mode;
4240 int nlink;
4241 NTSTATUS status;
4242 uint64_t file_size = 0;
4243 uint64_t pos = 0;
4244 uint64_t allocation_size = 0;
4245 uint64_t file_index = 0;
4246 uint32_t access_mask = 0;
4248 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4249 return NT_STATUS_INVALID_LEVEL;
4252 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4253 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4254 info_level, max_data_bytes));
4256 mode = dos_mode(conn, smb_fname);
4257 nlink = psbuf->st_ex_nlink;
4259 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4260 nlink = 1;
4263 if ((nlink > 0) && delete_pending) {
4264 nlink -= 1;
4267 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4268 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4269 if (*ppdata == NULL) {
4270 return NT_STATUS_NO_MEMORY;
4272 pdata = *ppdata;
4273 dstart = pdata;
4274 dend = dstart + data_size - 1;
4276 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4277 update_stat_ex_mtime(psbuf, write_time_ts);
4280 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4281 mtime_ts = psbuf->st_ex_mtime;
4282 atime_ts = psbuf->st_ex_atime;
4283 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4285 if (lp_dos_filetime_resolution(SNUM(conn))) {
4286 dos_filetime_timespec(&create_time_ts);
4287 dos_filetime_timespec(&mtime_ts);
4288 dos_filetime_timespec(&atime_ts);
4289 dos_filetime_timespec(&ctime_ts);
4292 create_time = convert_timespec_to_time_t(create_time_ts);
4293 mtime = convert_timespec_to_time_t(mtime_ts);
4294 atime = convert_timespec_to_time_t(atime_ts);
4295 c_time = convert_timespec_to_time_t(ctime_ts);
4297 p = strrchr_m(smb_fname->base_name,'/');
4298 if (!p)
4299 base_name = smb_fname->base_name;
4300 else
4301 base_name = p+1;
4303 /* NT expects the name to be in an exact form of the *full*
4304 filename. See the trans2 torture test */
4305 if (ISDOT(base_name)) {
4306 dos_fname = talloc_strdup(mem_ctx, "\\");
4307 if (!dos_fname) {
4308 return NT_STATUS_NO_MEMORY;
4310 } else {
4311 dos_fname = talloc_asprintf(mem_ctx,
4312 "\\%s",
4313 smb_fname->base_name);
4314 if (!dos_fname) {
4315 return NT_STATUS_NO_MEMORY;
4317 if (is_ntfs_stream_smb_fname(smb_fname)) {
4318 dos_fname = talloc_asprintf(dos_fname, "%s",
4319 smb_fname->stream_name);
4320 if (!dos_fname) {
4321 return NT_STATUS_NO_MEMORY;
4325 string_replace(dos_fname, '/', '\\');
4328 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4330 if (!fsp) {
4331 /* Do we have this path open ? */
4332 files_struct *fsp1;
4333 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4334 fsp1 = file_find_di_first(conn->sconn, fileid);
4335 if (fsp1 && fsp1->initial_allocation_size) {
4336 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4340 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4341 file_size = get_file_size_stat(psbuf);
4344 if (fsp) {
4345 pos = fsp->fh->position_information;
4348 if (fsp) {
4349 access_mask = fsp->access_mask;
4350 } else {
4351 /* GENERIC_EXECUTE mapping from Windows */
4352 access_mask = 0x12019F;
4355 /* This should be an index number - looks like
4356 dev/ino to me :-)
4358 I think this causes us to fail the IFSKIT
4359 BasicFileInformationTest. -tpot */
4360 file_index = get_FileIndex(conn, psbuf);
4362 switch (info_level) {
4363 case SMB_INFO_STANDARD:
4364 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4365 data_size = 22;
4366 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4367 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4368 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4369 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4370 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4371 SSVAL(pdata,l1_attrFile,mode);
4372 break;
4374 case SMB_INFO_QUERY_EA_SIZE:
4376 unsigned int ea_size =
4377 estimate_ea_size(conn, fsp,
4378 smb_fname->base_name);
4379 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4380 data_size = 26;
4381 srv_put_dos_date2(pdata,0,create_time);
4382 srv_put_dos_date2(pdata,4,atime);
4383 srv_put_dos_date2(pdata,8,mtime); /* write time */
4384 SIVAL(pdata,12,(uint32)file_size);
4385 SIVAL(pdata,16,(uint32)allocation_size);
4386 SSVAL(pdata,20,mode);
4387 SIVAL(pdata,22,ea_size);
4388 break;
4391 case SMB_INFO_IS_NAME_VALID:
4392 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4393 if (fsp) {
4394 /* os/2 needs this ? really ?*/
4395 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4397 /* This is only reached for qpathinfo */
4398 data_size = 0;
4399 break;
4401 case SMB_INFO_QUERY_EAS_FROM_LIST:
4403 size_t total_ea_len = 0;
4404 struct ea_list *ea_file_list = NULL;
4406 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4408 ea_file_list =
4409 get_ea_list_from_file(mem_ctx, conn, fsp,
4410 smb_fname->base_name,
4411 &total_ea_len);
4412 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4414 if (!ea_list || (total_ea_len > data_size)) {
4415 data_size = 4;
4416 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4417 break;
4420 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4421 break;
4424 case SMB_INFO_QUERY_ALL_EAS:
4426 /* We have data_size bytes to put EA's into. */
4427 size_t total_ea_len = 0;
4429 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4431 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4432 smb_fname->base_name,
4433 &total_ea_len);
4434 if (!ea_list || (total_ea_len > data_size)) {
4435 data_size = 4;
4436 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4437 break;
4440 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4441 break;
4444 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4446 /* This is FileFullEaInformation - 0xF which maps to
4447 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4449 /* We have data_size bytes to put EA's into. */
4450 size_t total_ea_len = 0;
4451 struct ea_list *ea_file_list = NULL;
4453 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4455 /*TODO: add filtering and index handling */
4457 ea_file_list =
4458 get_ea_list_from_file(mem_ctx, conn, fsp,
4459 smb_fname->base_name,
4460 &total_ea_len);
4461 if (!ea_file_list) {
4462 return NT_STATUS_NO_EAS_ON_FILE;
4465 status = fill_ea_chained_buffer(mem_ctx,
4466 pdata,
4467 data_size,
4468 &data_size,
4469 conn, ea_file_list);
4470 if (!NT_STATUS_IS_OK(status)) {
4471 return status;
4473 break;
4476 case SMB_FILE_BASIC_INFORMATION:
4477 case SMB_QUERY_FILE_BASIC_INFO:
4479 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4480 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4481 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4482 } else {
4483 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4484 data_size = 40;
4485 SIVAL(pdata,36,0);
4487 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4488 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4489 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4490 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4491 SIVAL(pdata,32,mode);
4493 DEBUG(5,("SMB_QFBI - "));
4494 DEBUG(5,("create: %s ", ctime(&create_time)));
4495 DEBUG(5,("access: %s ", ctime(&atime)));
4496 DEBUG(5,("write: %s ", ctime(&mtime)));
4497 DEBUG(5,("change: %s ", ctime(&c_time)));
4498 DEBUG(5,("mode: %x\n", mode));
4499 break;
4501 case SMB_FILE_STANDARD_INFORMATION:
4502 case SMB_QUERY_FILE_STANDARD_INFO:
4504 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4505 data_size = 24;
4506 SOFF_T(pdata,0,allocation_size);
4507 SOFF_T(pdata,8,file_size);
4508 SIVAL(pdata,16,nlink);
4509 SCVAL(pdata,20,delete_pending?1:0);
4510 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4511 SSVAL(pdata,22,0); /* Padding. */
4512 break;
4514 case SMB_FILE_EA_INFORMATION:
4515 case SMB_QUERY_FILE_EA_INFO:
4517 unsigned int ea_size =
4518 estimate_ea_size(conn, fsp, smb_fname->base_name);
4519 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4520 data_size = 4;
4521 SIVAL(pdata,0,ea_size);
4522 break;
4525 /* Get the 8.3 name - used if NT SMB was negotiated. */
4526 case SMB_QUERY_FILE_ALT_NAME_INFO:
4527 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4529 int len;
4530 char mangled_name[13];
4531 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4532 if (!name_to_8_3(base_name,mangled_name,
4533 True,conn->params)) {
4534 return NT_STATUS_NO_MEMORY;
4536 len = srvstr_push(dstart, flags2,
4537 pdata+4, mangled_name,
4538 PTR_DIFF(dend, pdata+4),
4539 STR_UNICODE);
4540 data_size = 4 + len;
4541 SIVAL(pdata,0,len);
4542 break;
4545 case SMB_QUERY_FILE_NAME_INFO:
4547 int len;
4549 this must be *exactly* right for ACLs on mapped drives to work
4551 len = srvstr_push(dstart, flags2,
4552 pdata+4, dos_fname,
4553 PTR_DIFF(dend, pdata+4),
4554 STR_UNICODE);
4555 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4556 data_size = 4 + len;
4557 SIVAL(pdata,0,len);
4558 break;
4561 case SMB_FILE_ALLOCATION_INFORMATION:
4562 case SMB_QUERY_FILE_ALLOCATION_INFO:
4563 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4564 data_size = 8;
4565 SOFF_T(pdata,0,allocation_size);
4566 break;
4568 case SMB_FILE_END_OF_FILE_INFORMATION:
4569 case SMB_QUERY_FILE_END_OF_FILEINFO:
4570 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4571 data_size = 8;
4572 SOFF_T(pdata,0,file_size);
4573 break;
4575 case SMB_QUERY_FILE_ALL_INFO:
4576 case SMB_FILE_ALL_INFORMATION:
4578 int len;
4579 unsigned int ea_size =
4580 estimate_ea_size(conn, fsp, smb_fname->base_name);
4581 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4582 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4583 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4584 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4585 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4586 SIVAL(pdata,32,mode);
4587 SIVAL(pdata,36,0); /* padding. */
4588 pdata += 40;
4589 SOFF_T(pdata,0,allocation_size);
4590 SOFF_T(pdata,8,file_size);
4591 SIVAL(pdata,16,nlink);
4592 SCVAL(pdata,20,delete_pending);
4593 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4594 SSVAL(pdata,22,0);
4595 pdata += 24;
4596 SIVAL(pdata,0,ea_size);
4597 pdata += 4; /* EA info */
4598 len = srvstr_push(dstart, flags2,
4599 pdata+4, dos_fname,
4600 PTR_DIFF(dend, pdata+4),
4601 STR_UNICODE);
4602 SIVAL(pdata,0,len);
4603 pdata += 4 + len;
4604 data_size = PTR_DIFF(pdata,(*ppdata));
4605 break;
4608 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4610 int len;
4611 unsigned int ea_size =
4612 estimate_ea_size(conn, fsp, smb_fname->base_name);
4613 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4614 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4615 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4616 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4617 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4618 SIVAL(pdata, 0x20, mode);
4619 SIVAL(pdata, 0x24, 0); /* padding. */
4620 SBVAL(pdata, 0x28, allocation_size);
4621 SBVAL(pdata, 0x30, file_size);
4622 SIVAL(pdata, 0x38, nlink);
4623 SCVAL(pdata, 0x3C, delete_pending);
4624 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4625 SSVAL(pdata, 0x3E, 0); /* padding */
4626 SBVAL(pdata, 0x40, file_index);
4627 SIVAL(pdata, 0x48, ea_size);
4628 SIVAL(pdata, 0x4C, access_mask);
4629 SBVAL(pdata, 0x50, pos);
4630 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4631 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4633 pdata += 0x60;
4635 len = srvstr_push(dstart, flags2,
4636 pdata+4, dos_fname,
4637 PTR_DIFF(dend, pdata+4),
4638 STR_UNICODE);
4639 SIVAL(pdata,0,len);
4640 pdata += 4 + len;
4641 data_size = PTR_DIFF(pdata,(*ppdata));
4642 break;
4644 case SMB_FILE_INTERNAL_INFORMATION:
4646 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4647 SBVAL(pdata, 0, file_index);
4648 data_size = 8;
4649 break;
4651 case SMB_FILE_ACCESS_INFORMATION:
4652 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4653 SIVAL(pdata, 0, access_mask);
4654 data_size = 4;
4655 break;
4657 case SMB_FILE_NAME_INFORMATION:
4658 /* Pathname with leading '\'. */
4660 size_t byte_len;
4661 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4662 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4663 SIVAL(pdata,0,byte_len);
4664 data_size = 4 + byte_len;
4665 break;
4668 case SMB_FILE_DISPOSITION_INFORMATION:
4669 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4670 data_size = 1;
4671 SCVAL(pdata,0,delete_pending);
4672 break;
4674 case SMB_FILE_POSITION_INFORMATION:
4675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4676 data_size = 8;
4677 SOFF_T(pdata,0,pos);
4678 break;
4680 case SMB_FILE_MODE_INFORMATION:
4681 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4682 SIVAL(pdata,0,mode);
4683 data_size = 4;
4684 break;
4686 case SMB_FILE_ALIGNMENT_INFORMATION:
4687 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4688 SIVAL(pdata,0,0); /* No alignment needed. */
4689 data_size = 4;
4690 break;
4693 * NT4 server just returns "invalid query" to this - if we try
4694 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4695 * want this. JRA.
4697 /* The first statement above is false - verified using Thursby
4698 * client against NT4 -- gcolley.
4700 case SMB_QUERY_FILE_STREAM_INFO:
4701 case SMB_FILE_STREAM_INFORMATION: {
4702 unsigned int num_streams = 0;
4703 struct stream_struct *streams = NULL;
4705 DEBUG(10,("smbd_do_qfilepathinfo: "
4706 "SMB_FILE_STREAM_INFORMATION\n"));
4708 if (is_ntfs_stream_smb_fname(smb_fname)) {
4709 return NT_STATUS_INVALID_PARAMETER;
4712 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4713 talloc_tos(), &num_streams, &streams);
4715 if (!NT_STATUS_IS_OK(status)) {
4716 DEBUG(10, ("could not get stream info: %s\n",
4717 nt_errstr(status)));
4718 return status;
4721 status = marshall_stream_info(num_streams, streams,
4722 pdata, max_data_bytes,
4723 &data_size);
4725 if (!NT_STATUS_IS_OK(status)) {
4726 DEBUG(10, ("marshall_stream_info failed: %s\n",
4727 nt_errstr(status)));
4728 return status;
4731 TALLOC_FREE(streams);
4733 break;
4735 case SMB_QUERY_COMPRESSION_INFO:
4736 case SMB_FILE_COMPRESSION_INFORMATION:
4737 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4738 SOFF_T(pdata,0,file_size);
4739 SIVAL(pdata,8,0); /* ??? */
4740 SIVAL(pdata,12,0); /* ??? */
4741 data_size = 16;
4742 break;
4744 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4745 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4746 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4747 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4748 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4749 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4750 SOFF_T(pdata,32,allocation_size);
4751 SOFF_T(pdata,40,file_size);
4752 SIVAL(pdata,48,mode);
4753 SIVAL(pdata,52,0); /* ??? */
4754 data_size = 56;
4755 break;
4757 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4758 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4759 SIVAL(pdata,0,mode);
4760 SIVAL(pdata,4,0);
4761 data_size = 8;
4762 break;
4765 * CIFS UNIX Extensions.
4768 case SMB_QUERY_FILE_UNIX_BASIC:
4770 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4771 data_size = PTR_DIFF(pdata,(*ppdata));
4773 DEBUG(4,("smbd_do_qfilepathinfo: "
4774 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4775 dump_data(4, (uint8_t *)(*ppdata), data_size);
4777 break;
4779 case SMB_QUERY_FILE_UNIX_INFO2:
4781 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4782 data_size = PTR_DIFF(pdata,(*ppdata));
4785 int i;
4786 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4788 for (i=0; i<100; i++)
4789 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4790 DEBUG(4,("\n"));
4793 break;
4795 case SMB_QUERY_FILE_UNIX_LINK:
4797 int len;
4798 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4800 if (!buffer) {
4801 return NT_STATUS_NO_MEMORY;
4804 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4805 #ifdef S_ISLNK
4806 if(!S_ISLNK(psbuf->st_ex_mode)) {
4807 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4809 #else
4810 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4811 #endif
4812 len = SMB_VFS_READLINK(conn,
4813 smb_fname->base_name,
4814 buffer, PATH_MAX);
4815 if (len == -1) {
4816 return map_nt_error_from_unix(errno);
4818 buffer[len] = 0;
4819 len = srvstr_push(dstart, flags2,
4820 pdata, buffer,
4821 PTR_DIFF(dend, pdata),
4822 STR_TERMINATE);
4823 pdata += len;
4824 data_size = PTR_DIFF(pdata,(*ppdata));
4826 break;
4829 #if defined(HAVE_POSIX_ACLS)
4830 case SMB_QUERY_POSIX_ACL:
4832 SMB_ACL_T file_acl = NULL;
4833 SMB_ACL_T def_acl = NULL;
4834 uint16 num_file_acls = 0;
4835 uint16 num_def_acls = 0;
4837 if (fsp && fsp->fh->fd != -1) {
4838 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4839 } else {
4840 file_acl =
4841 SMB_VFS_SYS_ACL_GET_FILE(conn,
4842 smb_fname->base_name,
4843 SMB_ACL_TYPE_ACCESS);
4846 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4847 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4848 "not implemented on "
4849 "filesystem containing %s\n",
4850 smb_fname->base_name));
4851 return NT_STATUS_NOT_IMPLEMENTED;
4854 if (S_ISDIR(psbuf->st_ex_mode)) {
4855 if (fsp && fsp->is_directory) {
4856 def_acl =
4857 SMB_VFS_SYS_ACL_GET_FILE(
4858 conn,
4859 fsp->fsp_name->base_name,
4860 SMB_ACL_TYPE_DEFAULT);
4861 } else {
4862 def_acl =
4863 SMB_VFS_SYS_ACL_GET_FILE(
4864 conn,
4865 smb_fname->base_name,
4866 SMB_ACL_TYPE_DEFAULT);
4868 def_acl = free_empty_sys_acl(conn, def_acl);
4871 num_file_acls = count_acl_entries(conn, file_acl);
4872 num_def_acls = count_acl_entries(conn, def_acl);
4874 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4875 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4876 data_size,
4877 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4878 SMB_POSIX_ACL_HEADER_SIZE) ));
4879 if (file_acl) {
4880 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4882 if (def_acl) {
4883 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4885 return NT_STATUS_BUFFER_TOO_SMALL;
4888 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4889 SSVAL(pdata,2,num_file_acls);
4890 SSVAL(pdata,4,num_def_acls);
4891 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4892 if (file_acl) {
4893 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4895 if (def_acl) {
4896 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4898 return NT_STATUS_INTERNAL_ERROR;
4900 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4901 if (file_acl) {
4902 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4904 if (def_acl) {
4905 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4907 return NT_STATUS_INTERNAL_ERROR;
4910 if (file_acl) {
4911 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4913 if (def_acl) {
4914 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4916 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4917 break;
4919 #endif
4922 case SMB_QUERY_POSIX_LOCK:
4924 uint64_t count;
4925 uint64_t offset;
4926 uint64_t smblctx;
4927 enum brl_type lock_type;
4929 /* We need an open file with a real fd for this. */
4930 if (!fsp || fsp->fh->fd == -1) {
4931 return NT_STATUS_INVALID_LEVEL;
4934 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4935 return NT_STATUS_INVALID_PARAMETER;
4938 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4939 case POSIX_LOCK_TYPE_READ:
4940 lock_type = READ_LOCK;
4941 break;
4942 case POSIX_LOCK_TYPE_WRITE:
4943 lock_type = WRITE_LOCK;
4944 break;
4945 case POSIX_LOCK_TYPE_UNLOCK:
4946 default:
4947 /* There's no point in asking for an unlock... */
4948 return NT_STATUS_INVALID_PARAMETER;
4951 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4952 #if defined(HAVE_LONGLONG)
4953 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4954 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4955 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4956 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4957 #else /* HAVE_LONGLONG */
4958 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4959 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4960 #endif /* HAVE_LONGLONG */
4962 status = query_lock(fsp,
4963 &smblctx,
4964 &count,
4965 &offset,
4966 &lock_type,
4967 POSIX_LOCK);
4969 if (ERROR_WAS_LOCK_DENIED(status)) {
4970 /* Here we need to report who has it locked... */
4971 data_size = POSIX_LOCK_DATA_SIZE;
4973 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4974 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4975 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4976 #if defined(HAVE_LONGLONG)
4977 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4978 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4979 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4980 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4981 #else /* HAVE_LONGLONG */
4982 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4983 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4984 #endif /* HAVE_LONGLONG */
4986 } else if (NT_STATUS_IS_OK(status)) {
4987 /* For success we just return a copy of what we sent
4988 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4989 data_size = POSIX_LOCK_DATA_SIZE;
4990 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4991 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4992 } else {
4993 return status;
4995 break;
4998 default:
4999 return NT_STATUS_INVALID_LEVEL;
5002 *pdata_size = data_size;
5003 return NT_STATUS_OK;
5006 /****************************************************************************
5007 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5008 file name or file id).
5009 ****************************************************************************/
5011 static void call_trans2qfilepathinfo(connection_struct *conn,
5012 struct smb_request *req,
5013 unsigned int tran_call,
5014 char **pparams, int total_params,
5015 char **ppdata, int total_data,
5016 unsigned int max_data_bytes)
5018 char *params = *pparams;
5019 char *pdata = *ppdata;
5020 uint16 info_level;
5021 unsigned int data_size = 0;
5022 unsigned int param_size = 2;
5023 struct smb_filename *smb_fname = NULL;
5024 bool delete_pending = False;
5025 struct timespec write_time_ts;
5026 files_struct *fsp = NULL;
5027 struct file_id fileid;
5028 struct ea_list *ea_list = NULL;
5029 int lock_data_count = 0;
5030 char *lock_data = NULL;
5031 NTSTATUS status = NT_STATUS_OK;
5033 if (!params) {
5034 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5035 return;
5038 ZERO_STRUCT(write_time_ts);
5040 if (tran_call == TRANSACT2_QFILEINFO) {
5041 if (total_params < 4) {
5042 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5043 return;
5046 if (IS_IPC(conn)) {
5047 call_trans2qpipeinfo(conn, req, tran_call,
5048 pparams, total_params,
5049 ppdata, total_data,
5050 max_data_bytes);
5051 return;
5054 fsp = file_fsp(req, SVAL(params,0));
5055 info_level = SVAL(params,2);
5057 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5059 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5060 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5061 return;
5064 /* Initial check for valid fsp ptr. */
5065 if (!check_fsp_open(conn, req, fsp)) {
5066 return;
5069 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5070 &smb_fname);
5071 if (!NT_STATUS_IS_OK(status)) {
5072 reply_nterror(req, status);
5073 return;
5076 if(fsp->fake_file_handle) {
5078 * This is actually for the QUOTA_FAKE_FILE --metze
5081 /* We know this name is ok, it's already passed the checks. */
5083 } else if(fsp->fh->fd == -1) {
5085 * This is actually a QFILEINFO on a directory
5086 * handle (returned from an NT SMB). NT5.0 seems
5087 * to do this call. JRA.
5090 if (INFO_LEVEL_IS_UNIX(info_level)) {
5091 /* Always do lstat for UNIX calls. */
5092 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5093 DEBUG(3,("call_trans2qfilepathinfo: "
5094 "SMB_VFS_LSTAT of %s failed "
5095 "(%s)\n",
5096 smb_fname_str_dbg(smb_fname),
5097 strerror(errno)));
5098 reply_nterror(req,
5099 map_nt_error_from_unix(errno));
5100 return;
5102 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5103 DEBUG(3,("call_trans2qfilepathinfo: "
5104 "SMB_VFS_STAT of %s failed (%s)\n",
5105 smb_fname_str_dbg(smb_fname),
5106 strerror(errno)));
5107 reply_nterror(req,
5108 map_nt_error_from_unix(errno));
5109 return;
5112 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5113 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5114 } else {
5116 * Original code - this is an open file.
5118 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5119 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5120 fsp->fnum, strerror(errno)));
5121 reply_nterror(req,
5122 map_nt_error_from_unix(errno));
5123 return;
5125 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5126 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5129 } else {
5130 uint32_t name_hash;
5131 char *fname = NULL;
5132 uint32_t ucf_flags = 0;
5134 /* qpathinfo */
5135 if (total_params < 7) {
5136 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5137 return;
5140 info_level = SVAL(params,0);
5142 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5144 if (INFO_LEVEL_IS_UNIX(info_level)) {
5145 if (!lp_unix_extensions()) {
5146 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5147 return;
5149 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5150 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5151 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5152 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5156 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5157 total_params - 6,
5158 STR_TERMINATE, &status);
5159 if (!NT_STATUS_IS_OK(status)) {
5160 reply_nterror(req, status);
5161 return;
5164 status = filename_convert(req,
5165 conn,
5166 req->flags2 & FLAGS2_DFS_PATHNAMES,
5167 fname,
5168 ucf_flags,
5169 NULL,
5170 &smb_fname);
5171 if (!NT_STATUS_IS_OK(status)) {
5172 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5173 reply_botherror(req,
5174 NT_STATUS_PATH_NOT_COVERED,
5175 ERRSRV, ERRbadpath);
5176 return;
5178 reply_nterror(req, status);
5179 return;
5182 /* If this is a stream, check if there is a delete_pending. */
5183 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5184 && is_ntfs_stream_smb_fname(smb_fname)) {
5185 struct smb_filename *smb_fname_base = NULL;
5187 /* Create an smb_filename with stream_name == NULL. */
5188 status =
5189 create_synthetic_smb_fname(talloc_tos(),
5190 smb_fname->base_name,
5191 NULL, NULL,
5192 &smb_fname_base);
5193 if (!NT_STATUS_IS_OK(status)) {
5194 reply_nterror(req, status);
5195 return;
5198 if (INFO_LEVEL_IS_UNIX(info_level)) {
5199 /* Always do lstat for UNIX calls. */
5200 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5201 DEBUG(3,("call_trans2qfilepathinfo: "
5202 "SMB_VFS_LSTAT of %s failed "
5203 "(%s)\n",
5204 smb_fname_str_dbg(smb_fname_base),
5205 strerror(errno)));
5206 TALLOC_FREE(smb_fname_base);
5207 reply_nterror(req,
5208 map_nt_error_from_unix(errno));
5209 return;
5211 } else {
5212 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5213 DEBUG(3,("call_trans2qfilepathinfo: "
5214 "fileinfo of %s failed "
5215 "(%s)\n",
5216 smb_fname_str_dbg(smb_fname_base),
5217 strerror(errno)));
5218 TALLOC_FREE(smb_fname_base);
5219 reply_nterror(req,
5220 map_nt_error_from_unix(errno));
5221 return;
5225 status = file_name_hash(conn,
5226 smb_fname_str_dbg(smb_fname_base),
5227 &name_hash);
5228 if (!NT_STATUS_IS_OK(status)) {
5229 TALLOC_FREE(smb_fname_base);
5230 reply_nterror(req, status);
5231 return;
5234 fileid = vfs_file_id_from_sbuf(conn,
5235 &smb_fname_base->st);
5236 TALLOC_FREE(smb_fname_base);
5237 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5238 if (delete_pending) {
5239 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5240 return;
5244 if (INFO_LEVEL_IS_UNIX(info_level)) {
5245 /* Always do lstat for UNIX calls. */
5246 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5247 DEBUG(3,("call_trans2qfilepathinfo: "
5248 "SMB_VFS_LSTAT of %s failed (%s)\n",
5249 smb_fname_str_dbg(smb_fname),
5250 strerror(errno)));
5251 reply_nterror(req,
5252 map_nt_error_from_unix(errno));
5253 return;
5256 } else {
5257 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5258 DEBUG(3,("call_trans2qfilepathinfo: "
5259 "SMB_VFS_STAT of %s failed (%s)\n",
5260 smb_fname_str_dbg(smb_fname),
5261 strerror(errno)));
5262 reply_nterror(req,
5263 map_nt_error_from_unix(errno));
5264 return;
5268 status = file_name_hash(conn,
5269 smb_fname_str_dbg(smb_fname),
5270 &name_hash);
5271 if (!NT_STATUS_IS_OK(status)) {
5272 reply_nterror(req, status);
5273 return;
5276 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5277 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5278 if (delete_pending) {
5279 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5280 return;
5284 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5285 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5286 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5288 /* Pull out any data sent here before we realloc. */
5289 switch (info_level) {
5290 case SMB_INFO_QUERY_EAS_FROM_LIST:
5292 /* Pull any EA list from the data portion. */
5293 uint32 ea_size;
5295 if (total_data < 4) {
5296 reply_nterror(
5297 req, NT_STATUS_INVALID_PARAMETER);
5298 return;
5300 ea_size = IVAL(pdata,0);
5302 if (total_data > 0 && ea_size != total_data) {
5303 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5304 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5305 reply_nterror(
5306 req, NT_STATUS_INVALID_PARAMETER);
5307 return;
5310 if (!lp_ea_support(SNUM(conn))) {
5311 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5312 return;
5315 /* Pull out the list of names. */
5316 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5317 if (!ea_list) {
5318 reply_nterror(
5319 req, NT_STATUS_INVALID_PARAMETER);
5320 return;
5322 break;
5325 case SMB_QUERY_POSIX_LOCK:
5327 if (fsp == NULL || fsp->fh->fd == -1) {
5328 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5329 return;
5332 if (total_data != POSIX_LOCK_DATA_SIZE) {
5333 reply_nterror(
5334 req, NT_STATUS_INVALID_PARAMETER);
5335 return;
5338 /* Copy the lock range data. */
5339 lock_data = (char *)talloc_memdup(
5340 req, pdata, total_data);
5341 if (!lock_data) {
5342 reply_nterror(req, NT_STATUS_NO_MEMORY);
5343 return;
5345 lock_data_count = total_data;
5347 default:
5348 break;
5351 *pparams = (char *)SMB_REALLOC(*pparams,2);
5352 if (*pparams == NULL) {
5353 reply_nterror(req, NT_STATUS_NO_MEMORY);
5354 return;
5356 params = *pparams;
5357 SSVAL(params,0,0);
5360 * draft-leach-cifs-v1-spec-02.txt
5361 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5362 * says:
5364 * The requested information is placed in the Data portion of the
5365 * transaction response. For the information levels greater than 0x100,
5366 * the transaction response has 1 parameter word which should be
5367 * ignored by the client.
5369 * However Windows only follows this rule for the IS_NAME_VALID call.
5371 switch (info_level) {
5372 case SMB_INFO_IS_NAME_VALID:
5373 param_size = 0;
5374 break;
5377 if ((info_level & 0xFF00) == 0xFF00) {
5379 * We use levels that start with 0xFF00
5380 * internally to represent SMB2 specific levels
5382 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5383 return;
5386 status = smbd_do_qfilepathinfo(conn, req, info_level,
5387 fsp, smb_fname,
5388 delete_pending, write_time_ts,
5389 ea_list,
5390 lock_data_count, lock_data,
5391 req->flags2, max_data_bytes,
5392 ppdata, &data_size);
5393 if (!NT_STATUS_IS_OK(status)) {
5394 reply_nterror(req, status);
5395 return;
5398 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5399 max_data_bytes);
5401 return;
5404 /****************************************************************************
5405 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5406 code.
5407 ****************************************************************************/
5409 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5410 connection_struct *conn,
5411 struct smb_request *req,
5412 bool overwrite_if_exists,
5413 const struct smb_filename *smb_fname_old,
5414 struct smb_filename *smb_fname_new)
5416 NTSTATUS status = NT_STATUS_OK;
5418 /* source must already exist. */
5419 if (!VALID_STAT(smb_fname_old->st)) {
5420 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5423 if (VALID_STAT(smb_fname_new->st)) {
5424 if (overwrite_if_exists) {
5425 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5426 return NT_STATUS_FILE_IS_A_DIRECTORY;
5428 status = unlink_internals(conn,
5429 req,
5430 FILE_ATTRIBUTE_NORMAL,
5431 smb_fname_new,
5432 false);
5433 if (!NT_STATUS_IS_OK(status)) {
5434 return status;
5436 } else {
5437 /* Disallow if newname already exists. */
5438 return NT_STATUS_OBJECT_NAME_COLLISION;
5442 /* No links from a directory. */
5443 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5444 return NT_STATUS_FILE_IS_A_DIRECTORY;
5447 /* Setting a hardlink to/from a stream isn't currently supported. */
5448 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5449 is_ntfs_stream_smb_fname(smb_fname_new)) {
5450 return NT_STATUS_INVALID_PARAMETER;
5453 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5454 smb_fname_old->base_name, smb_fname_new->base_name));
5456 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5457 smb_fname_new->base_name) != 0) {
5458 status = map_nt_error_from_unix(errno);
5459 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5460 nt_errstr(status), smb_fname_old->base_name,
5461 smb_fname_new->base_name));
5463 return status;
5466 /****************************************************************************
5467 Deal with setting the time from any of the setfilepathinfo functions.
5468 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5469 calling this function.
5470 ****************************************************************************/
5472 NTSTATUS smb_set_file_time(connection_struct *conn,
5473 files_struct *fsp,
5474 const struct smb_filename *smb_fname,
5475 struct smb_file_time *ft,
5476 bool setting_write_time)
5478 struct smb_filename smb_fname_base;
5479 uint32 action =
5480 FILE_NOTIFY_CHANGE_LAST_ACCESS
5481 |FILE_NOTIFY_CHANGE_LAST_WRITE
5482 |FILE_NOTIFY_CHANGE_CREATION;
5484 if (!VALID_STAT(smb_fname->st)) {
5485 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5488 /* get some defaults (no modifications) if any info is zero or -1. */
5489 if (null_timespec(ft->create_time)) {
5490 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5493 if (null_timespec(ft->atime)) {
5494 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5497 if (null_timespec(ft->mtime)) {
5498 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5501 if (!setting_write_time) {
5502 /* ft->mtime comes from change time, not write time. */
5503 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5506 /* Ensure the resolution is the correct for
5507 * what we can store on this filesystem. */
5509 round_timespec(conn->ts_res, &ft->create_time);
5510 round_timespec(conn->ts_res, &ft->ctime);
5511 round_timespec(conn->ts_res, &ft->atime);
5512 round_timespec(conn->ts_res, &ft->mtime);
5514 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5515 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5516 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5517 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5518 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5519 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5520 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5521 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5523 if (setting_write_time) {
5525 * This was a Windows setfileinfo on an open file.
5526 * NT does this a lot. We also need to
5527 * set the time here, as it can be read by
5528 * FindFirst/FindNext and with the patch for bug #2045
5529 * in smbd/fileio.c it ensures that this timestamp is
5530 * kept sticky even after a write. We save the request
5531 * away and will set it on file close and after a write. JRA.
5534 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5535 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5537 if (fsp != NULL) {
5538 if (fsp->base_fsp) {
5539 set_sticky_write_time_fsp(fsp->base_fsp,
5540 ft->mtime);
5541 } else {
5542 set_sticky_write_time_fsp(fsp, ft->mtime);
5544 } else {
5545 set_sticky_write_time_path(
5546 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5547 ft->mtime);
5551 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5553 /* Always call ntimes on the base, even if a stream was passed in. */
5554 smb_fname_base = *smb_fname;
5555 smb_fname_base.stream_name = NULL;
5557 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5558 return map_nt_error_from_unix(errno);
5561 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5562 smb_fname->base_name);
5563 return NT_STATUS_OK;
5566 /****************************************************************************
5567 Deal with setting the dosmode from any of the setfilepathinfo functions.
5568 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5569 done before calling this function.
5570 ****************************************************************************/
5572 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5573 const struct smb_filename *smb_fname,
5574 uint32 dosmode)
5576 struct smb_filename *smb_fname_base = NULL;
5577 NTSTATUS status;
5579 if (!VALID_STAT(smb_fname->st)) {
5580 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5583 /* Always operate on the base_name, even if a stream was passed in. */
5584 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5585 NULL, &smb_fname->st,
5586 &smb_fname_base);
5587 if (!NT_STATUS_IS_OK(status)) {
5588 return status;
5591 if (dosmode) {
5592 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5593 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5594 } else {
5595 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5599 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5601 /* check the mode isn't different, before changing it */
5602 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5603 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5604 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5605 (unsigned int)dosmode));
5607 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5608 false)) {
5609 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5610 "%s failed (%s)\n",
5611 smb_fname_str_dbg(smb_fname_base),
5612 strerror(errno)));
5613 status = map_nt_error_from_unix(errno);
5614 goto out;
5617 status = NT_STATUS_OK;
5618 out:
5619 TALLOC_FREE(smb_fname_base);
5620 return status;
5623 /****************************************************************************
5624 Deal with setting the size from any of the setfilepathinfo functions.
5625 ****************************************************************************/
5627 static NTSTATUS smb_set_file_size(connection_struct *conn,
5628 struct smb_request *req,
5629 files_struct *fsp,
5630 const struct smb_filename *smb_fname,
5631 const SMB_STRUCT_STAT *psbuf,
5632 SMB_OFF_T size,
5633 bool fail_after_createfile)
5635 NTSTATUS status = NT_STATUS_OK;
5636 struct smb_filename *smb_fname_tmp = NULL;
5637 files_struct *new_fsp = NULL;
5639 if (!VALID_STAT(*psbuf)) {
5640 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5643 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5645 if (size == get_file_size_stat(psbuf)) {
5646 return NT_STATUS_OK;
5649 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5650 smb_fname_str_dbg(smb_fname), (double)size));
5652 if (fsp && fsp->fh->fd != -1) {
5653 /* Handle based call. */
5654 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5655 return NT_STATUS_ACCESS_DENIED;
5658 if (vfs_set_filelen(fsp, size) == -1) {
5659 return map_nt_error_from_unix(errno);
5661 trigger_write_time_update_immediate(fsp);
5662 return NT_STATUS_OK;
5665 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5666 if (!NT_STATUS_IS_OK(status)) {
5667 return status;
5670 smb_fname_tmp->st = *psbuf;
5672 status = SMB_VFS_CREATE_FILE(
5673 conn, /* conn */
5674 req, /* req */
5675 0, /* root_dir_fid */
5676 smb_fname_tmp, /* fname */
5677 FILE_WRITE_DATA, /* access_mask */
5678 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5679 FILE_SHARE_DELETE),
5680 FILE_OPEN, /* create_disposition*/
5681 0, /* create_options */
5682 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5683 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5684 0, /* allocation_size */
5685 0, /* private_flags */
5686 NULL, /* sd */
5687 NULL, /* ea_list */
5688 &new_fsp, /* result */
5689 NULL); /* pinfo */
5691 TALLOC_FREE(smb_fname_tmp);
5693 if (!NT_STATUS_IS_OK(status)) {
5694 /* NB. We check for open_was_deferred in the caller. */
5695 return status;
5698 /* See RAW-SFILEINFO-END-OF-FILE */
5699 if (fail_after_createfile) {
5700 close_file(req, new_fsp,NORMAL_CLOSE);
5701 return NT_STATUS_INVALID_LEVEL;
5704 if (vfs_set_filelen(new_fsp, size) == -1) {
5705 status = map_nt_error_from_unix(errno);
5706 close_file(req, new_fsp,NORMAL_CLOSE);
5707 return status;
5710 trigger_write_time_update_immediate(new_fsp);
5711 close_file(req, new_fsp,NORMAL_CLOSE);
5712 return NT_STATUS_OK;
5715 /****************************************************************************
5716 Deal with SMB_INFO_SET_EA.
5717 ****************************************************************************/
5719 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5720 const char *pdata,
5721 int total_data,
5722 files_struct *fsp,
5723 const struct smb_filename *smb_fname)
5725 struct ea_list *ea_list = NULL;
5726 TALLOC_CTX *ctx = NULL;
5727 NTSTATUS status = NT_STATUS_OK;
5729 if (total_data < 10) {
5731 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5732 length. They seem to have no effect. Bug #3212. JRA */
5734 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5735 /* We're done. We only get EA info in this call. */
5736 return NT_STATUS_OK;
5739 return NT_STATUS_INVALID_PARAMETER;
5742 if (IVAL(pdata,0) > total_data) {
5743 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5744 IVAL(pdata,0), (unsigned int)total_data));
5745 return NT_STATUS_INVALID_PARAMETER;
5748 ctx = talloc_tos();
5749 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5750 if (!ea_list) {
5751 return NT_STATUS_INVALID_PARAMETER;
5754 status = set_ea(conn, fsp, smb_fname, ea_list);
5756 return status;
5759 /****************************************************************************
5760 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5761 ****************************************************************************/
5763 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5764 const char *pdata,
5765 int total_data,
5766 files_struct *fsp)
5768 struct ea_list *ea_list = NULL;
5769 NTSTATUS status;
5771 if (!fsp) {
5772 return NT_STATUS_INVALID_HANDLE;
5775 if (!lp_ea_support(SNUM(conn))) {
5776 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5777 "EA's not supported.\n",
5778 (unsigned int)total_data));
5779 return NT_STATUS_EAS_NOT_SUPPORTED;
5782 if (total_data < 10) {
5783 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5784 "too small.\n",
5785 (unsigned int)total_data));
5786 return NT_STATUS_INVALID_PARAMETER;
5789 ea_list = read_nttrans_ea_list(talloc_tos(),
5790 pdata,
5791 total_data);
5793 if (!ea_list) {
5794 return NT_STATUS_INVALID_PARAMETER;
5797 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5799 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5800 smb_fname_str_dbg(fsp->fsp_name),
5801 nt_errstr(status) ));
5803 return status;
5807 /****************************************************************************
5808 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5809 ****************************************************************************/
5811 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5812 const char *pdata,
5813 int total_data,
5814 files_struct *fsp,
5815 struct smb_filename *smb_fname)
5817 NTSTATUS status = NT_STATUS_OK;
5818 bool delete_on_close;
5819 uint32 dosmode = 0;
5821 if (total_data < 1) {
5822 return NT_STATUS_INVALID_PARAMETER;
5825 if (fsp == NULL) {
5826 return NT_STATUS_INVALID_HANDLE;
5829 delete_on_close = (CVAL(pdata,0) ? True : False);
5830 dosmode = dos_mode(conn, smb_fname);
5832 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5833 "delete_on_close = %u\n",
5834 smb_fname_str_dbg(smb_fname),
5835 (unsigned int)dosmode,
5836 (unsigned int)delete_on_close ));
5838 if (delete_on_close) {
5839 status = can_set_delete_on_close(fsp, dosmode);
5840 if (!NT_STATUS_IS_OK(status)) {
5841 return status;
5845 /* The set is across all open files on this dev/inode pair. */
5846 if (!set_delete_on_close(fsp, delete_on_close,
5847 conn->session_info->unix_token)) {
5848 return NT_STATUS_ACCESS_DENIED;
5850 return NT_STATUS_OK;
5853 /****************************************************************************
5854 Deal with SMB_FILE_POSITION_INFORMATION.
5855 ****************************************************************************/
5857 static NTSTATUS smb_file_position_information(connection_struct *conn,
5858 const char *pdata,
5859 int total_data,
5860 files_struct *fsp)
5862 uint64_t position_information;
5864 if (total_data < 8) {
5865 return NT_STATUS_INVALID_PARAMETER;
5868 if (fsp == NULL) {
5869 /* Ignore on pathname based set. */
5870 return NT_STATUS_OK;
5873 position_information = (uint64_t)IVAL(pdata,0);
5874 #ifdef LARGE_SMB_OFF_T
5875 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5876 #else /* LARGE_SMB_OFF_T */
5877 if (IVAL(pdata,4) != 0) {
5878 /* more than 32 bits? */
5879 return NT_STATUS_INVALID_PARAMETER;
5881 #endif /* LARGE_SMB_OFF_T */
5883 DEBUG(10,("smb_file_position_information: Set file position "
5884 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5885 (double)position_information));
5886 fsp->fh->position_information = position_information;
5887 return NT_STATUS_OK;
5890 /****************************************************************************
5891 Deal with SMB_FILE_MODE_INFORMATION.
5892 ****************************************************************************/
5894 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5895 const char *pdata,
5896 int total_data)
5898 uint32 mode;
5900 if (total_data < 4) {
5901 return NT_STATUS_INVALID_PARAMETER;
5903 mode = IVAL(pdata,0);
5904 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5905 return NT_STATUS_INVALID_PARAMETER;
5907 return NT_STATUS_OK;
5910 /****************************************************************************
5911 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5912 ****************************************************************************/
5914 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5915 struct smb_request *req,
5916 const char *pdata,
5917 int total_data,
5918 const struct smb_filename *smb_fname)
5920 char *link_target = NULL;
5921 const char *newname = smb_fname->base_name;
5922 TALLOC_CTX *ctx = talloc_tos();
5924 /* Set a symbolic link. */
5925 /* Don't allow this if follow links is false. */
5927 if (total_data == 0) {
5928 return NT_STATUS_INVALID_PARAMETER;
5931 if (!lp_symlinks(SNUM(conn))) {
5932 return NT_STATUS_ACCESS_DENIED;
5935 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5936 total_data, STR_TERMINATE);
5938 if (!link_target) {
5939 return NT_STATUS_INVALID_PARAMETER;
5942 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5943 newname, link_target ));
5945 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5946 return map_nt_error_from_unix(errno);
5949 return NT_STATUS_OK;
5952 /****************************************************************************
5953 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5954 ****************************************************************************/
5956 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5957 struct smb_request *req,
5958 const char *pdata, int total_data,
5959 struct smb_filename *smb_fname_new)
5961 char *oldname = NULL;
5962 struct smb_filename *smb_fname_old = NULL;
5963 TALLOC_CTX *ctx = talloc_tos();
5964 NTSTATUS status = NT_STATUS_OK;
5966 /* Set a hard link. */
5967 if (total_data == 0) {
5968 return NT_STATUS_INVALID_PARAMETER;
5971 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5972 total_data, STR_TERMINATE, &status);
5973 if (!NT_STATUS_IS_OK(status)) {
5974 return status;
5977 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5978 smb_fname_str_dbg(smb_fname_new), oldname));
5980 status = filename_convert(ctx,
5981 conn,
5982 req->flags2 & FLAGS2_DFS_PATHNAMES,
5983 oldname,
5985 NULL,
5986 &smb_fname_old);
5987 if (!NT_STATUS_IS_OK(status)) {
5988 return status;
5991 return hardlink_internals(ctx, conn, req, false,
5992 smb_fname_old, smb_fname_new);
5995 /****************************************************************************
5996 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5997 ****************************************************************************/
5999 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6000 struct smb_request *req,
6001 const char *pdata,
6002 int total_data,
6003 files_struct *fsp,
6004 struct smb_filename *smb_fname_src)
6006 bool overwrite;
6007 uint32_t len;
6008 char *newname = NULL;
6009 struct smb_filename *smb_fname_dst = NULL;
6010 NTSTATUS status = NT_STATUS_OK;
6011 TALLOC_CTX *ctx = talloc_tos();
6013 if (!fsp) {
6014 return NT_STATUS_INVALID_HANDLE;
6017 if (total_data < 20) {
6018 return NT_STATUS_INVALID_PARAMETER;
6021 overwrite = (CVAL(pdata,0) ? True : False);
6022 len = IVAL(pdata,16);
6024 if (len > (total_data - 20) || (len == 0)) {
6025 return NT_STATUS_INVALID_PARAMETER;
6028 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6029 &pdata[20], len, STR_TERMINATE,
6030 &status);
6031 if (!NT_STATUS_IS_OK(status)) {
6032 return status;
6035 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6036 newname));
6038 status = filename_convert(ctx,
6039 conn,
6040 req->flags2 & FLAGS2_DFS_PATHNAMES,
6041 newname,
6042 UCF_SAVE_LCOMP,
6043 NULL,
6044 &smb_fname_dst);
6045 if (!NT_STATUS_IS_OK(status)) {
6046 return status;
6049 if (fsp->base_fsp) {
6050 /* newname must be a stream name. */
6051 if (newname[0] != ':') {
6052 return NT_STATUS_NOT_SUPPORTED;
6055 /* Create an smb_fname to call rename_internals_fsp() with. */
6056 status = create_synthetic_smb_fname(talloc_tos(),
6057 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6058 &smb_fname_dst);
6059 if (!NT_STATUS_IS_OK(status)) {
6060 goto out;
6064 * Set the original last component, since
6065 * rename_internals_fsp() requires it.
6067 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6068 newname);
6069 if (smb_fname_dst->original_lcomp == NULL) {
6070 status = NT_STATUS_NO_MEMORY;
6071 goto out;
6076 DEBUG(10,("smb2_file_rename_information: "
6077 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6078 fsp->fnum, fsp_str_dbg(fsp),
6079 smb_fname_str_dbg(smb_fname_dst)));
6080 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6081 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6082 overwrite);
6084 out:
6085 TALLOC_FREE(smb_fname_dst);
6086 return status;
6089 static NTSTATUS smb_file_link_information(connection_struct *conn,
6090 struct smb_request *req,
6091 const char *pdata,
6092 int total_data,
6093 files_struct *fsp,
6094 struct smb_filename *smb_fname_src)
6096 bool overwrite;
6097 uint32_t len;
6098 char *newname = NULL;
6099 struct smb_filename *smb_fname_dst = NULL;
6100 NTSTATUS status = NT_STATUS_OK;
6101 TALLOC_CTX *ctx = talloc_tos();
6103 if (!fsp) {
6104 return NT_STATUS_INVALID_HANDLE;
6107 if (total_data < 20) {
6108 return NT_STATUS_INVALID_PARAMETER;
6111 overwrite = (CVAL(pdata,0) ? true : false);
6112 len = IVAL(pdata,16);
6114 if (len > (total_data - 20) || (len == 0)) {
6115 return NT_STATUS_INVALID_PARAMETER;
6118 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6119 &pdata[20], len, STR_TERMINATE,
6120 &status);
6121 if (!NT_STATUS_IS_OK(status)) {
6122 return status;
6125 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6126 newname));
6128 status = filename_convert(ctx,
6129 conn,
6130 req->flags2 & FLAGS2_DFS_PATHNAMES,
6131 newname,
6132 UCF_SAVE_LCOMP,
6133 NULL,
6134 &smb_fname_dst);
6135 if (!NT_STATUS_IS_OK(status)) {
6136 return status;
6139 if (fsp->base_fsp) {
6140 /* No stream names. */
6141 return NT_STATUS_NOT_SUPPORTED;
6144 DEBUG(10,("smb_file_link_information: "
6145 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6146 fsp->fnum, fsp_str_dbg(fsp),
6147 smb_fname_str_dbg(smb_fname_dst)));
6148 status = hardlink_internals(ctx,
6149 conn,
6150 req,
6151 overwrite,
6152 fsp->fsp_name,
6153 smb_fname_dst);
6155 TALLOC_FREE(smb_fname_dst);
6156 return status;
6159 /****************************************************************************
6160 Deal with SMB_FILE_RENAME_INFORMATION.
6161 ****************************************************************************/
6163 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6164 struct smb_request *req,
6165 const char *pdata,
6166 int total_data,
6167 files_struct *fsp,
6168 struct smb_filename *smb_fname_src)
6170 bool overwrite;
6171 uint32 root_fid;
6172 uint32 len;
6173 char *newname = NULL;
6174 struct smb_filename *smb_fname_dst = NULL;
6175 bool dest_has_wcard = False;
6176 NTSTATUS status = NT_STATUS_OK;
6177 char *p;
6178 TALLOC_CTX *ctx = talloc_tos();
6180 if (total_data < 13) {
6181 return NT_STATUS_INVALID_PARAMETER;
6184 overwrite = (CVAL(pdata,0) ? True : False);
6185 root_fid = IVAL(pdata,4);
6186 len = IVAL(pdata,8);
6188 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6189 return NT_STATUS_INVALID_PARAMETER;
6192 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6193 len, 0, &status,
6194 &dest_has_wcard);
6195 if (!NT_STATUS_IS_OK(status)) {
6196 return status;
6199 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6200 newname));
6202 status = resolve_dfspath_wcard(ctx, conn,
6203 req->flags2 & FLAGS2_DFS_PATHNAMES,
6204 newname,
6205 true,
6206 &newname,
6207 &dest_has_wcard);
6208 if (!NT_STATUS_IS_OK(status)) {
6209 return status;
6212 /* Check the new name has no '/' characters. */
6213 if (strchr_m(newname, '/')) {
6214 return NT_STATUS_NOT_SUPPORTED;
6217 if (fsp && fsp->base_fsp) {
6218 /* newname must be a stream name. */
6219 if (newname[0] != ':') {
6220 return NT_STATUS_NOT_SUPPORTED;
6223 /* Create an smb_fname to call rename_internals_fsp() with. */
6224 status = create_synthetic_smb_fname(talloc_tos(),
6225 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6226 &smb_fname_dst);
6227 if (!NT_STATUS_IS_OK(status)) {
6228 goto out;
6232 * Set the original last component, since
6233 * rename_internals_fsp() requires it.
6235 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6236 newname);
6237 if (smb_fname_dst->original_lcomp == NULL) {
6238 status = NT_STATUS_NO_MEMORY;
6239 goto out;
6242 } else {
6244 * Build up an smb_fname_dst based on the filename passed in.
6245 * We basically just strip off the last component, and put on
6246 * the newname instead.
6248 char *base_name = NULL;
6250 /* newname must *not* be a stream name. */
6251 if (newname[0] == ':') {
6252 return NT_STATUS_NOT_SUPPORTED;
6256 * Strip off the last component (filename) of the path passed
6257 * in.
6259 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6260 if (!base_name) {
6261 return NT_STATUS_NO_MEMORY;
6263 p = strrchr_m(base_name, '/');
6264 if (p) {
6265 p[1] = '\0';
6266 } else {
6267 base_name = talloc_strdup(ctx, "");
6268 if (!base_name) {
6269 return NT_STATUS_NO_MEMORY;
6272 /* Append the new name. */
6273 base_name = talloc_asprintf_append(base_name,
6274 "%s",
6275 newname);
6276 if (!base_name) {
6277 return NT_STATUS_NO_MEMORY;
6280 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6281 (UCF_SAVE_LCOMP |
6282 (dest_has_wcard ?
6283 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6284 0)));
6286 /* If an error we expect this to be
6287 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6289 if (!NT_STATUS_IS_OK(status)) {
6290 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6291 status)) {
6292 goto out;
6294 /* Create an smb_fname to call rename_internals_fsp() */
6295 status = create_synthetic_smb_fname(ctx,
6296 base_name, NULL,
6297 NULL,
6298 &smb_fname_dst);
6299 if (!NT_STATUS_IS_OK(status)) {
6300 goto out;
6305 if (fsp) {
6306 DEBUG(10,("smb_file_rename_information: "
6307 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6308 fsp->fnum, fsp_str_dbg(fsp),
6309 smb_fname_str_dbg(smb_fname_dst)));
6310 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6311 overwrite);
6312 } else {
6313 DEBUG(10,("smb_file_rename_information: "
6314 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6315 smb_fname_str_dbg(smb_fname_src),
6316 smb_fname_str_dbg(smb_fname_dst)));
6317 status = rename_internals(ctx, conn, req, smb_fname_src,
6318 smb_fname_dst, 0, overwrite, false,
6319 dest_has_wcard,
6320 FILE_WRITE_ATTRIBUTES);
6322 out:
6323 TALLOC_FREE(smb_fname_dst);
6324 return status;
6327 /****************************************************************************
6328 Deal with SMB_SET_POSIX_ACL.
6329 ****************************************************************************/
6331 #if defined(HAVE_POSIX_ACLS)
6332 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6333 const char *pdata,
6334 int total_data,
6335 files_struct *fsp,
6336 const struct smb_filename *smb_fname)
6338 uint16 posix_acl_version;
6339 uint16 num_file_acls;
6340 uint16 num_def_acls;
6341 bool valid_file_acls = True;
6342 bool valid_def_acls = True;
6344 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6345 return NT_STATUS_INVALID_PARAMETER;
6347 posix_acl_version = SVAL(pdata,0);
6348 num_file_acls = SVAL(pdata,2);
6349 num_def_acls = SVAL(pdata,4);
6351 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6352 valid_file_acls = False;
6353 num_file_acls = 0;
6356 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6357 valid_def_acls = False;
6358 num_def_acls = 0;
6361 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6362 return NT_STATUS_INVALID_PARAMETER;
6365 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6366 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6367 return NT_STATUS_INVALID_PARAMETER;
6370 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6371 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6372 (unsigned int)num_file_acls,
6373 (unsigned int)num_def_acls));
6375 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6376 smb_fname->base_name, num_file_acls,
6377 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6378 return map_nt_error_from_unix(errno);
6381 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6382 smb_fname->base_name, &smb_fname->st, num_def_acls,
6383 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6384 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6385 return map_nt_error_from_unix(errno);
6387 return NT_STATUS_OK;
6389 #endif
6391 /****************************************************************************
6392 Deal with SMB_SET_POSIX_LOCK.
6393 ****************************************************************************/
6395 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6396 struct smb_request *req,
6397 const char *pdata,
6398 int total_data,
6399 files_struct *fsp)
6401 uint64_t count;
6402 uint64_t offset;
6403 uint64_t smblctx;
6404 bool blocking_lock = False;
6405 enum brl_type lock_type;
6407 NTSTATUS status = NT_STATUS_OK;
6409 if (fsp == NULL || fsp->fh->fd == -1) {
6410 return NT_STATUS_INVALID_HANDLE;
6413 if (total_data != POSIX_LOCK_DATA_SIZE) {
6414 return NT_STATUS_INVALID_PARAMETER;
6417 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6418 case POSIX_LOCK_TYPE_READ:
6419 lock_type = READ_LOCK;
6420 break;
6421 case POSIX_LOCK_TYPE_WRITE:
6422 /* Return the right POSIX-mappable error code for files opened read-only. */
6423 if (!fsp->can_write) {
6424 return NT_STATUS_INVALID_HANDLE;
6426 lock_type = WRITE_LOCK;
6427 break;
6428 case POSIX_LOCK_TYPE_UNLOCK:
6429 lock_type = UNLOCK_LOCK;
6430 break;
6431 default:
6432 return NT_STATUS_INVALID_PARAMETER;
6435 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6436 blocking_lock = False;
6437 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6438 blocking_lock = True;
6439 } else {
6440 return NT_STATUS_INVALID_PARAMETER;
6443 if (!lp_blocking_locks(SNUM(conn))) {
6444 blocking_lock = False;
6447 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6448 #if defined(HAVE_LONGLONG)
6449 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6450 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6451 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6452 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6453 #else /* HAVE_LONGLONG */
6454 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6455 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6456 #endif /* HAVE_LONGLONG */
6458 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6459 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6460 fsp_str_dbg(fsp),
6461 (unsigned int)lock_type,
6462 (unsigned long long)smblctx,
6463 (double)count,
6464 (double)offset ));
6466 if (lock_type == UNLOCK_LOCK) {
6467 status = do_unlock(req->sconn->msg_ctx,
6468 fsp,
6469 smblctx,
6470 count,
6471 offset,
6472 POSIX_LOCK);
6473 } else {
6474 uint64_t block_smblctx;
6476 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6477 fsp,
6478 smblctx,
6479 count,
6480 offset,
6481 lock_type,
6482 POSIX_LOCK,
6483 blocking_lock,
6484 &status,
6485 &block_smblctx,
6486 NULL);
6488 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6490 * A blocking lock was requested. Package up
6491 * this smb into a queued request and push it
6492 * onto the blocking lock queue.
6494 if(push_blocking_lock_request(br_lck,
6495 req,
6496 fsp,
6497 -1, /* infinite timeout. */
6499 smblctx,
6500 lock_type,
6501 POSIX_LOCK,
6502 offset,
6503 count,
6504 block_smblctx)) {
6505 TALLOC_FREE(br_lck);
6506 return status;
6509 TALLOC_FREE(br_lck);
6512 return status;
6515 /****************************************************************************
6516 Deal with SMB_SET_FILE_BASIC_INFO.
6517 ****************************************************************************/
6519 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6520 const char *pdata,
6521 int total_data,
6522 files_struct *fsp,
6523 const struct smb_filename *smb_fname)
6525 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6526 struct smb_file_time ft;
6527 uint32 dosmode = 0;
6528 NTSTATUS status = NT_STATUS_OK;
6530 ZERO_STRUCT(ft);
6532 if (total_data < 36) {
6533 return NT_STATUS_INVALID_PARAMETER;
6536 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6537 if (!NT_STATUS_IS_OK(status)) {
6538 return status;
6541 /* Set the attributes */
6542 dosmode = IVAL(pdata,32);
6543 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6544 if (!NT_STATUS_IS_OK(status)) {
6545 return status;
6548 /* create time */
6549 ft.create_time = interpret_long_date(pdata);
6551 /* access time */
6552 ft.atime = interpret_long_date(pdata+8);
6554 /* write time. */
6555 ft.mtime = interpret_long_date(pdata+16);
6557 /* change time. */
6558 ft.ctime = interpret_long_date(pdata+24);
6560 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6561 smb_fname_str_dbg(smb_fname)));
6563 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6564 true);
6567 /****************************************************************************
6568 Deal with SMB_INFO_STANDARD.
6569 ****************************************************************************/
6571 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6572 const char *pdata,
6573 int total_data,
6574 files_struct *fsp,
6575 const struct smb_filename *smb_fname)
6577 NTSTATUS status;
6578 struct smb_file_time ft;
6580 ZERO_STRUCT(ft);
6582 if (total_data < 12) {
6583 return NT_STATUS_INVALID_PARAMETER;
6586 /* create time */
6587 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6588 /* access time */
6589 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6590 /* write time */
6591 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6593 DEBUG(10,("smb_set_info_standard: file %s\n",
6594 smb_fname_str_dbg(smb_fname)));
6596 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6597 if (!NT_STATUS_IS_OK(status)) {
6598 return status;
6601 return smb_set_file_time(conn,
6602 fsp,
6603 smb_fname,
6604 &ft,
6605 true);
6608 /****************************************************************************
6609 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6610 ****************************************************************************/
6612 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6613 struct smb_request *req,
6614 const char *pdata,
6615 int total_data,
6616 files_struct *fsp,
6617 struct smb_filename *smb_fname)
6619 uint64_t allocation_size = 0;
6620 NTSTATUS status = NT_STATUS_OK;
6621 files_struct *new_fsp = NULL;
6623 if (!VALID_STAT(smb_fname->st)) {
6624 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6627 if (total_data < 8) {
6628 return NT_STATUS_INVALID_PARAMETER;
6631 allocation_size = (uint64_t)IVAL(pdata,0);
6632 #ifdef LARGE_SMB_OFF_T
6633 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6634 #else /* LARGE_SMB_OFF_T */
6635 if (IVAL(pdata,4) != 0) {
6636 /* more than 32 bits? */
6637 return NT_STATUS_INVALID_PARAMETER;
6639 #endif /* LARGE_SMB_OFF_T */
6641 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6642 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6643 (double)allocation_size));
6645 if (allocation_size) {
6646 allocation_size = smb_roundup(conn, allocation_size);
6649 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6650 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6651 (double)allocation_size));
6653 if (fsp && fsp->fh->fd != -1) {
6654 /* Open file handle. */
6655 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6656 return NT_STATUS_ACCESS_DENIED;
6659 /* Only change if needed. */
6660 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6661 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6662 return map_nt_error_from_unix(errno);
6665 /* But always update the time. */
6667 * This is equivalent to a write. Ensure it's seen immediately
6668 * if there are no pending writes.
6670 trigger_write_time_update_immediate(fsp);
6671 return NT_STATUS_OK;
6674 /* Pathname or stat or directory file. */
6675 status = SMB_VFS_CREATE_FILE(
6676 conn, /* conn */
6677 req, /* req */
6678 0, /* root_dir_fid */
6679 smb_fname, /* fname */
6680 FILE_WRITE_DATA, /* access_mask */
6681 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6682 FILE_SHARE_DELETE),
6683 FILE_OPEN, /* create_disposition*/
6684 0, /* create_options */
6685 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6686 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6687 0, /* allocation_size */
6688 0, /* private_flags */
6689 NULL, /* sd */
6690 NULL, /* ea_list */
6691 &new_fsp, /* result */
6692 NULL); /* pinfo */
6694 if (!NT_STATUS_IS_OK(status)) {
6695 /* NB. We check for open_was_deferred in the caller. */
6696 return status;
6699 /* Only change if needed. */
6700 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6701 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6702 status = map_nt_error_from_unix(errno);
6703 close_file(req, new_fsp, NORMAL_CLOSE);
6704 return status;
6708 /* Changing the allocation size should set the last mod time. */
6710 * This is equivalent to a write. Ensure it's seen immediately
6711 * if there are no pending writes.
6713 trigger_write_time_update_immediate(new_fsp);
6715 close_file(req, new_fsp, NORMAL_CLOSE);
6716 return NT_STATUS_OK;
6719 /****************************************************************************
6720 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6721 ****************************************************************************/
6723 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6724 struct smb_request *req,
6725 const char *pdata,
6726 int total_data,
6727 files_struct *fsp,
6728 const struct smb_filename *smb_fname,
6729 bool fail_after_createfile)
6731 SMB_OFF_T size;
6733 if (total_data < 8) {
6734 return NT_STATUS_INVALID_PARAMETER;
6737 size = IVAL(pdata,0);
6738 #ifdef LARGE_SMB_OFF_T
6739 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6740 #else /* LARGE_SMB_OFF_T */
6741 if (IVAL(pdata,4) != 0) {
6742 /* more than 32 bits? */
6743 return NT_STATUS_INVALID_PARAMETER;
6745 #endif /* LARGE_SMB_OFF_T */
6746 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6747 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6748 (double)size));
6750 return smb_set_file_size(conn, req,
6751 fsp,
6752 smb_fname,
6753 &smb_fname->st,
6754 size,
6755 fail_after_createfile);
6758 /****************************************************************************
6759 Allow a UNIX info mknod.
6760 ****************************************************************************/
6762 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6763 const char *pdata,
6764 int total_data,
6765 const struct smb_filename *smb_fname)
6767 uint32 file_type = IVAL(pdata,56);
6768 #if defined(HAVE_MAKEDEV)
6769 uint32 dev_major = IVAL(pdata,60);
6770 uint32 dev_minor = IVAL(pdata,68);
6771 #endif
6772 SMB_DEV_T dev = (SMB_DEV_T)0;
6773 uint32 raw_unixmode = IVAL(pdata,84);
6774 NTSTATUS status;
6775 mode_t unixmode;
6777 if (total_data < 100) {
6778 return NT_STATUS_INVALID_PARAMETER;
6781 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6782 PERM_NEW_FILE, &unixmode);
6783 if (!NT_STATUS_IS_OK(status)) {
6784 return status;
6787 #if defined(HAVE_MAKEDEV)
6788 dev = makedev(dev_major, dev_minor);
6789 #endif
6791 switch (file_type) {
6792 #if defined(S_IFIFO)
6793 case UNIX_TYPE_FIFO:
6794 unixmode |= S_IFIFO;
6795 break;
6796 #endif
6797 #if defined(S_IFSOCK)
6798 case UNIX_TYPE_SOCKET:
6799 unixmode |= S_IFSOCK;
6800 break;
6801 #endif
6802 #if defined(S_IFCHR)
6803 case UNIX_TYPE_CHARDEV:
6804 unixmode |= S_IFCHR;
6805 break;
6806 #endif
6807 #if defined(S_IFBLK)
6808 case UNIX_TYPE_BLKDEV:
6809 unixmode |= S_IFBLK;
6810 break;
6811 #endif
6812 default:
6813 return NT_STATUS_INVALID_PARAMETER;
6816 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6817 "%.0f mode 0%o for file %s\n", (double)dev,
6818 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6820 /* Ok - do the mknod. */
6821 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6822 return map_nt_error_from_unix(errno);
6825 /* If any of the other "set" calls fail we
6826 * don't want to end up with a half-constructed mknod.
6829 if (lp_inherit_perms(SNUM(conn))) {
6830 char *parent;
6831 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6832 &parent, NULL)) {
6833 return NT_STATUS_NO_MEMORY;
6835 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6836 unixmode);
6837 TALLOC_FREE(parent);
6840 return NT_STATUS_OK;
6843 /****************************************************************************
6844 Deal with SMB_SET_FILE_UNIX_BASIC.
6845 ****************************************************************************/
6847 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6848 struct smb_request *req,
6849 const char *pdata,
6850 int total_data,
6851 files_struct *fsp,
6852 const struct smb_filename *smb_fname)
6854 struct smb_file_time ft;
6855 uint32 raw_unixmode;
6856 mode_t unixmode;
6857 SMB_OFF_T size = 0;
6858 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6859 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6860 NTSTATUS status = NT_STATUS_OK;
6861 bool delete_on_fail = False;
6862 enum perm_type ptype;
6863 files_struct *all_fsps = NULL;
6864 bool modify_mtime = true;
6865 struct file_id id;
6866 struct smb_filename *smb_fname_tmp = NULL;
6867 SMB_STRUCT_STAT sbuf;
6869 ZERO_STRUCT(ft);
6871 if (total_data < 100) {
6872 return NT_STATUS_INVALID_PARAMETER;
6875 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6876 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6877 size=IVAL(pdata,0); /* first 8 Bytes are size */
6878 #ifdef LARGE_SMB_OFF_T
6879 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6880 #else /* LARGE_SMB_OFF_T */
6881 if (IVAL(pdata,4) != 0) {
6882 /* more than 32 bits? */
6883 return NT_STATUS_INVALID_PARAMETER;
6885 #endif /* LARGE_SMB_OFF_T */
6888 ft.atime = interpret_long_date(pdata+24); /* access_time */
6889 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6890 set_owner = (uid_t)IVAL(pdata,40);
6891 set_grp = (gid_t)IVAL(pdata,48);
6892 raw_unixmode = IVAL(pdata,84);
6894 if (VALID_STAT(smb_fname->st)) {
6895 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6896 ptype = PERM_EXISTING_DIR;
6897 } else {
6898 ptype = PERM_EXISTING_FILE;
6900 } else {
6901 ptype = PERM_NEW_FILE;
6904 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6905 ptype, &unixmode);
6906 if (!NT_STATUS_IS_OK(status)) {
6907 return status;
6910 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6911 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6912 smb_fname_str_dbg(smb_fname), (double)size,
6913 (unsigned int)set_owner, (unsigned int)set_grp,
6914 (int)raw_unixmode));
6916 sbuf = smb_fname->st;
6918 if (!VALID_STAT(sbuf)) {
6920 * The only valid use of this is to create character and block
6921 * devices, and named pipes. This is deprecated (IMHO) and
6922 * a new info level should be used for mknod. JRA.
6925 status = smb_unix_mknod(conn,
6926 pdata,
6927 total_data,
6928 smb_fname);
6929 if (!NT_STATUS_IS_OK(status)) {
6930 return status;
6933 status = copy_smb_filename(talloc_tos(), smb_fname,
6934 &smb_fname_tmp);
6935 if (!NT_STATUS_IS_OK(status)) {
6936 return status;
6939 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6940 status = map_nt_error_from_unix(errno);
6941 TALLOC_FREE(smb_fname_tmp);
6942 SMB_VFS_UNLINK(conn, smb_fname);
6943 return status;
6946 sbuf = smb_fname_tmp->st;
6947 smb_fname = smb_fname_tmp;
6949 /* Ensure we don't try and change anything else. */
6950 raw_unixmode = SMB_MODE_NO_CHANGE;
6951 size = get_file_size_stat(&sbuf);
6952 ft.atime = sbuf.st_ex_atime;
6953 ft.mtime = sbuf.st_ex_mtime;
6955 * We continue here as we might want to change the
6956 * owner uid/gid.
6958 delete_on_fail = True;
6961 #if 1
6962 /* Horrible backwards compatibility hack as an old server bug
6963 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6964 * */
6966 if (!size) {
6967 size = get_file_size_stat(&sbuf);
6969 #endif
6972 * Deal with the UNIX specific mode set.
6975 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6976 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6977 "setting mode 0%o for file %s\n",
6978 (unsigned int)unixmode,
6979 smb_fname_str_dbg(smb_fname)));
6980 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6981 return map_nt_error_from_unix(errno);
6986 * Deal with the UNIX specific uid set.
6989 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6990 (sbuf.st_ex_uid != set_owner)) {
6991 int ret;
6993 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6994 "changing owner %u for path %s\n",
6995 (unsigned int)set_owner,
6996 smb_fname_str_dbg(smb_fname)));
6998 if (S_ISLNK(sbuf.st_ex_mode)) {
6999 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7000 set_owner, (gid_t)-1);
7001 } else {
7002 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7003 set_owner, (gid_t)-1);
7006 if (ret != 0) {
7007 status = map_nt_error_from_unix(errno);
7008 if (delete_on_fail) {
7009 SMB_VFS_UNLINK(conn, smb_fname);
7011 return status;
7016 * Deal with the UNIX specific gid set.
7019 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7020 (sbuf.st_ex_gid != set_grp)) {
7021 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7022 "changing group %u for file %s\n",
7023 (unsigned int)set_owner,
7024 smb_fname_str_dbg(smb_fname)));
7025 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7026 set_grp) != 0) {
7027 status = map_nt_error_from_unix(errno);
7028 if (delete_on_fail) {
7029 SMB_VFS_UNLINK(conn, smb_fname);
7031 return status;
7035 /* Deal with any size changes. */
7037 status = smb_set_file_size(conn, req,
7038 fsp,
7039 smb_fname,
7040 &sbuf,
7041 size,
7042 false);
7043 if (!NT_STATUS_IS_OK(status)) {
7044 return status;
7047 /* Deal with any time changes. */
7048 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7049 /* No change, don't cancel anything. */
7050 return status;
7053 id = vfs_file_id_from_sbuf(conn, &sbuf);
7054 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7055 all_fsps = file_find_di_next(all_fsps)) {
7057 * We're setting the time explicitly for UNIX.
7058 * Cancel any pending changes over all handles.
7060 all_fsps->update_write_time_on_close = false;
7061 TALLOC_FREE(all_fsps->update_write_time_event);
7065 * Override the "setting_write_time"
7066 * parameter here as it almost does what
7067 * we need. Just remember if we modified
7068 * mtime and send the notify ourselves.
7070 if (null_timespec(ft.mtime)) {
7071 modify_mtime = false;
7074 status = smb_set_file_time(conn,
7075 fsp,
7076 smb_fname,
7077 &ft,
7078 false);
7079 if (modify_mtime) {
7080 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7081 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7083 return status;
7086 /****************************************************************************
7087 Deal with SMB_SET_FILE_UNIX_INFO2.
7088 ****************************************************************************/
7090 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7091 struct smb_request *req,
7092 const char *pdata,
7093 int total_data,
7094 files_struct *fsp,
7095 const struct smb_filename *smb_fname)
7097 NTSTATUS status;
7098 uint32 smb_fflags;
7099 uint32 smb_fmask;
7101 if (total_data < 116) {
7102 return NT_STATUS_INVALID_PARAMETER;
7105 /* Start by setting all the fields that are common between UNIX_BASIC
7106 * and UNIX_INFO2.
7108 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7109 fsp, smb_fname);
7110 if (!NT_STATUS_IS_OK(status)) {
7111 return status;
7114 smb_fflags = IVAL(pdata, 108);
7115 smb_fmask = IVAL(pdata, 112);
7117 /* NB: We should only attempt to alter the file flags if the client
7118 * sends a non-zero mask.
7120 if (smb_fmask != 0) {
7121 int stat_fflags = 0;
7123 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7124 smb_fmask, &stat_fflags)) {
7125 /* Client asked to alter a flag we don't understand. */
7126 return NT_STATUS_INVALID_PARAMETER;
7129 if (fsp && fsp->fh->fd != -1) {
7130 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7131 return NT_STATUS_NOT_SUPPORTED;
7132 } else {
7133 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7134 stat_fflags) != 0) {
7135 return map_nt_error_from_unix(errno);
7140 /* XXX: need to add support for changing the create_time here. You
7141 * can do this for paths on Darwin with setattrlist(2). The right way
7142 * to hook this up is probably by extending the VFS utimes interface.
7145 return NT_STATUS_OK;
7148 /****************************************************************************
7149 Create a directory with POSIX semantics.
7150 ****************************************************************************/
7152 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7153 struct smb_request *req,
7154 char **ppdata,
7155 int total_data,
7156 struct smb_filename *smb_fname,
7157 int *pdata_return_size)
7159 NTSTATUS status = NT_STATUS_OK;
7160 uint32 raw_unixmode = 0;
7161 uint32 mod_unixmode = 0;
7162 mode_t unixmode = (mode_t)0;
7163 files_struct *fsp = NULL;
7164 uint16 info_level_return = 0;
7165 int info;
7166 char *pdata = *ppdata;
7168 if (total_data < 18) {
7169 return NT_STATUS_INVALID_PARAMETER;
7172 raw_unixmode = IVAL(pdata,8);
7173 /* Next 4 bytes are not yet defined. */
7175 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7176 PERM_NEW_DIR, &unixmode);
7177 if (!NT_STATUS_IS_OK(status)) {
7178 return status;
7181 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7183 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7184 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7186 status = SMB_VFS_CREATE_FILE(
7187 conn, /* conn */
7188 req, /* req */
7189 0, /* root_dir_fid */
7190 smb_fname, /* fname */
7191 FILE_READ_ATTRIBUTES, /* access_mask */
7192 FILE_SHARE_NONE, /* share_access */
7193 FILE_CREATE, /* create_disposition*/
7194 FILE_DIRECTORY_FILE, /* create_options */
7195 mod_unixmode, /* file_attributes */
7196 0, /* oplock_request */
7197 0, /* allocation_size */
7198 0, /* private_flags */
7199 NULL, /* sd */
7200 NULL, /* ea_list */
7201 &fsp, /* result */
7202 &info); /* pinfo */
7204 if (NT_STATUS_IS_OK(status)) {
7205 close_file(req, fsp, NORMAL_CLOSE);
7208 info_level_return = SVAL(pdata,16);
7210 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7211 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7212 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7213 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7214 } else {
7215 *pdata_return_size = 12;
7218 /* Realloc the data size */
7219 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7220 if (*ppdata == NULL) {
7221 *pdata_return_size = 0;
7222 return NT_STATUS_NO_MEMORY;
7224 pdata = *ppdata;
7226 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7227 SSVAL(pdata,2,0); /* No fnum. */
7228 SIVAL(pdata,4,info); /* Was directory created. */
7230 switch (info_level_return) {
7231 case SMB_QUERY_FILE_UNIX_BASIC:
7232 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7233 SSVAL(pdata,10,0); /* Padding. */
7234 store_file_unix_basic(conn, pdata + 12, fsp,
7235 &smb_fname->st);
7236 break;
7237 case SMB_QUERY_FILE_UNIX_INFO2:
7238 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7239 SSVAL(pdata,10,0); /* Padding. */
7240 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7241 &smb_fname->st);
7242 break;
7243 default:
7244 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7245 SSVAL(pdata,10,0); /* Padding. */
7246 break;
7249 return status;
7252 /****************************************************************************
7253 Open/Create a file with POSIX semantics.
7254 ****************************************************************************/
7256 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7257 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7259 static NTSTATUS smb_posix_open(connection_struct *conn,
7260 struct smb_request *req,
7261 char **ppdata,
7262 int total_data,
7263 struct smb_filename *smb_fname,
7264 int *pdata_return_size)
7266 bool extended_oplock_granted = False;
7267 char *pdata = *ppdata;
7268 uint32 flags = 0;
7269 uint32 wire_open_mode = 0;
7270 uint32 raw_unixmode = 0;
7271 uint32 mod_unixmode = 0;
7272 uint32 create_disp = 0;
7273 uint32 access_mask = 0;
7274 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7275 NTSTATUS status = NT_STATUS_OK;
7276 mode_t unixmode = (mode_t)0;
7277 files_struct *fsp = NULL;
7278 int oplock_request = 0;
7279 int info = 0;
7280 uint16 info_level_return = 0;
7282 if (total_data < 18) {
7283 return NT_STATUS_INVALID_PARAMETER;
7286 flags = IVAL(pdata,0);
7287 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7288 if (oplock_request) {
7289 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7292 wire_open_mode = IVAL(pdata,4);
7294 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7295 return smb_posix_mkdir(conn, req,
7296 ppdata,
7297 total_data,
7298 smb_fname,
7299 pdata_return_size);
7302 switch (wire_open_mode & SMB_ACCMODE) {
7303 case SMB_O_RDONLY:
7304 access_mask = SMB_O_RDONLY_MAPPING;
7305 break;
7306 case SMB_O_WRONLY:
7307 access_mask = SMB_O_WRONLY_MAPPING;
7308 break;
7309 case SMB_O_RDWR:
7310 access_mask = (SMB_O_RDONLY_MAPPING|
7311 SMB_O_WRONLY_MAPPING);
7312 break;
7313 default:
7314 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7315 (unsigned int)wire_open_mode ));
7316 return NT_STATUS_INVALID_PARAMETER;
7319 wire_open_mode &= ~SMB_ACCMODE;
7321 /* First take care of O_CREAT|O_EXCL interactions. */
7322 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7323 case (SMB_O_CREAT | SMB_O_EXCL):
7324 /* File exists fail. File not exist create. */
7325 create_disp = FILE_CREATE;
7326 break;
7327 case SMB_O_CREAT:
7328 /* File exists open. File not exist create. */
7329 create_disp = FILE_OPEN_IF;
7330 break;
7331 case 0:
7332 /* File exists open. File not exist fail. */
7333 create_disp = FILE_OPEN;
7334 break;
7335 case SMB_O_EXCL:
7336 /* O_EXCL on its own without O_CREAT is undefined. */
7337 default:
7338 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7339 (unsigned int)wire_open_mode ));
7340 return NT_STATUS_INVALID_PARAMETER;
7343 /* Next factor in the effects of O_TRUNC. */
7344 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7346 if (wire_open_mode & SMB_O_TRUNC) {
7347 switch (create_disp) {
7348 case FILE_CREATE:
7349 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7350 /* Leave create_disp alone as
7351 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7353 /* File exists fail. File not exist create. */
7354 break;
7355 case FILE_OPEN_IF:
7356 /* SMB_O_CREAT | SMB_O_TRUNC */
7357 /* File exists overwrite. File not exist create. */
7358 create_disp = FILE_OVERWRITE_IF;
7359 break;
7360 case FILE_OPEN:
7361 /* SMB_O_TRUNC */
7362 /* File exists overwrite. File not exist fail. */
7363 create_disp = FILE_OVERWRITE;
7364 break;
7365 default:
7366 /* Cannot get here. */
7367 smb_panic("smb_posix_open: logic error");
7368 return NT_STATUS_INVALID_PARAMETER;
7372 raw_unixmode = IVAL(pdata,8);
7373 /* Next 4 bytes are not yet defined. */
7375 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7376 (VALID_STAT(smb_fname->st) ?
7377 PERM_EXISTING_FILE : PERM_NEW_FILE),
7378 &unixmode);
7380 if (!NT_STATUS_IS_OK(status)) {
7381 return status;
7384 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7386 if (wire_open_mode & SMB_O_SYNC) {
7387 create_options |= FILE_WRITE_THROUGH;
7389 if (wire_open_mode & SMB_O_APPEND) {
7390 access_mask |= FILE_APPEND_DATA;
7392 if (wire_open_mode & SMB_O_DIRECT) {
7393 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7396 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7397 VALID_STAT_OF_DIR(smb_fname->st)) {
7398 if (access_mask != SMB_O_RDONLY_MAPPING) {
7399 return NT_STATUS_FILE_IS_A_DIRECTORY;
7401 create_options &= ~FILE_NON_DIRECTORY_FILE;
7402 create_options |= FILE_DIRECTORY_FILE;
7405 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7406 smb_fname_str_dbg(smb_fname),
7407 (unsigned int)wire_open_mode,
7408 (unsigned int)unixmode ));
7410 status = SMB_VFS_CREATE_FILE(
7411 conn, /* conn */
7412 req, /* req */
7413 0, /* root_dir_fid */
7414 smb_fname, /* fname */
7415 access_mask, /* access_mask */
7416 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7417 FILE_SHARE_DELETE),
7418 create_disp, /* create_disposition*/
7419 create_options, /* create_options */
7420 mod_unixmode, /* file_attributes */
7421 oplock_request, /* oplock_request */
7422 0, /* allocation_size */
7423 0, /* private_flags */
7424 NULL, /* sd */
7425 NULL, /* ea_list */
7426 &fsp, /* result */
7427 &info); /* pinfo */
7429 if (!NT_STATUS_IS_OK(status)) {
7430 return status;
7433 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7434 extended_oplock_granted = True;
7437 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7438 extended_oplock_granted = True;
7441 info_level_return = SVAL(pdata,16);
7443 /* Allocate the correct return size. */
7445 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7446 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7447 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7448 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7449 } else {
7450 *pdata_return_size = 12;
7453 /* Realloc the data size */
7454 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7455 if (*ppdata == NULL) {
7456 close_file(req, fsp, ERROR_CLOSE);
7457 *pdata_return_size = 0;
7458 return NT_STATUS_NO_MEMORY;
7460 pdata = *ppdata;
7462 if (extended_oplock_granted) {
7463 if (flags & REQUEST_BATCH_OPLOCK) {
7464 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7465 } else {
7466 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7468 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7469 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7470 } else {
7471 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7474 SSVAL(pdata,2,fsp->fnum);
7475 SIVAL(pdata,4,info); /* Was file created etc. */
7477 switch (info_level_return) {
7478 case SMB_QUERY_FILE_UNIX_BASIC:
7479 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7480 SSVAL(pdata,10,0); /* padding. */
7481 store_file_unix_basic(conn, pdata + 12, fsp,
7482 &smb_fname->st);
7483 break;
7484 case SMB_QUERY_FILE_UNIX_INFO2:
7485 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7486 SSVAL(pdata,10,0); /* padding. */
7487 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7488 &smb_fname->st);
7489 break;
7490 default:
7491 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7492 SSVAL(pdata,10,0); /* padding. */
7493 break;
7495 return NT_STATUS_OK;
7498 /****************************************************************************
7499 Delete a file with POSIX semantics.
7500 ****************************************************************************/
7502 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7503 struct smb_request *req,
7504 const char *pdata,
7505 int total_data,
7506 struct smb_filename *smb_fname)
7508 NTSTATUS status = NT_STATUS_OK;
7509 files_struct *fsp = NULL;
7510 uint16 flags = 0;
7511 char del = 1;
7512 int info = 0;
7513 int create_options = 0;
7514 int i;
7515 struct share_mode_lock *lck = NULL;
7517 if (total_data < 2) {
7518 return NT_STATUS_INVALID_PARAMETER;
7521 flags = SVAL(pdata,0);
7523 if (!VALID_STAT(smb_fname->st)) {
7524 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7527 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7528 !VALID_STAT_OF_DIR(smb_fname->st)) {
7529 return NT_STATUS_NOT_A_DIRECTORY;
7532 DEBUG(10,("smb_posix_unlink: %s %s\n",
7533 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7534 smb_fname_str_dbg(smb_fname)));
7536 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7537 create_options |= FILE_DIRECTORY_FILE;
7540 status = SMB_VFS_CREATE_FILE(
7541 conn, /* conn */
7542 req, /* req */
7543 0, /* root_dir_fid */
7544 smb_fname, /* fname */
7545 DELETE_ACCESS, /* access_mask */
7546 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7547 FILE_SHARE_DELETE),
7548 FILE_OPEN, /* create_disposition*/
7549 create_options, /* create_options */
7550 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7551 0, /* oplock_request */
7552 0, /* allocation_size */
7553 0, /* private_flags */
7554 NULL, /* sd */
7555 NULL, /* ea_list */
7556 &fsp, /* result */
7557 &info); /* pinfo */
7559 if (!NT_STATUS_IS_OK(status)) {
7560 return status;
7564 * Don't lie to client. If we can't really delete due to
7565 * non-POSIX opens return SHARING_VIOLATION.
7568 lck = get_share_mode_lock(talloc_tos(), fsp->file_id);
7569 if (lck == NULL) {
7570 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7571 "lock for file %s\n", fsp_str_dbg(fsp)));
7572 close_file(req, fsp, NORMAL_CLOSE);
7573 return NT_STATUS_INVALID_PARAMETER;
7577 * See if others still have the file open. If this is the case, then
7578 * don't delete. If all opens are POSIX delete we can set the delete
7579 * on close disposition.
7581 for (i=0; i<lck->data->num_share_modes; i++) {
7582 struct share_mode_entry *e = &lck->data->share_modes[i];
7583 if (is_valid_share_mode_entry(e)) {
7584 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7585 continue;
7587 /* Fail with sharing violation. */
7588 close_file(req, fsp, NORMAL_CLOSE);
7589 TALLOC_FREE(lck);
7590 return NT_STATUS_SHARING_VIOLATION;
7595 * Set the delete on close.
7597 status = smb_set_file_disposition_info(conn,
7598 &del,
7600 fsp,
7601 smb_fname);
7603 if (!NT_STATUS_IS_OK(status)) {
7604 close_file(req, fsp, NORMAL_CLOSE);
7605 TALLOC_FREE(lck);
7606 return status;
7608 TALLOC_FREE(lck);
7609 return close_file(req, fsp, NORMAL_CLOSE);
7612 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7613 struct smb_request *req,
7614 TALLOC_CTX *mem_ctx,
7615 uint16_t info_level,
7616 files_struct *fsp,
7617 struct smb_filename *smb_fname,
7618 char **ppdata, int total_data,
7619 int *ret_data_size)
7621 char *pdata = *ppdata;
7622 NTSTATUS status = NT_STATUS_OK;
7623 int data_return_size = 0;
7625 *ret_data_size = 0;
7627 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7628 return NT_STATUS_INVALID_LEVEL;
7631 if (!CAN_WRITE(conn)) {
7632 /* Allow POSIX opens. The open path will deny
7633 * any non-readonly opens. */
7634 if (info_level != SMB_POSIX_PATH_OPEN) {
7635 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7639 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7640 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7641 fsp ? fsp->fnum : -1, info_level, total_data));
7643 switch (info_level) {
7645 case SMB_INFO_STANDARD:
7647 status = smb_set_info_standard(conn,
7648 pdata,
7649 total_data,
7650 fsp,
7651 smb_fname);
7652 break;
7655 case SMB_INFO_SET_EA:
7657 status = smb_info_set_ea(conn,
7658 pdata,
7659 total_data,
7660 fsp,
7661 smb_fname);
7662 break;
7665 case SMB_SET_FILE_BASIC_INFO:
7666 case SMB_FILE_BASIC_INFORMATION:
7668 status = smb_set_file_basic_info(conn,
7669 pdata,
7670 total_data,
7671 fsp,
7672 smb_fname);
7673 break;
7676 case SMB_FILE_ALLOCATION_INFORMATION:
7677 case SMB_SET_FILE_ALLOCATION_INFO:
7679 status = smb_set_file_allocation_info(conn, req,
7680 pdata,
7681 total_data,
7682 fsp,
7683 smb_fname);
7684 break;
7687 case SMB_FILE_END_OF_FILE_INFORMATION:
7688 case SMB_SET_FILE_END_OF_FILE_INFO:
7691 * XP/Win7 both fail after the createfile with
7692 * SMB_SET_FILE_END_OF_FILE_INFO but not
7693 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7694 * The level is known here, so pass it down
7695 * appropriately.
7697 bool should_fail =
7698 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7700 status = smb_set_file_end_of_file_info(conn, req,
7701 pdata,
7702 total_data,
7703 fsp,
7704 smb_fname,
7705 should_fail);
7706 break;
7709 case SMB_FILE_DISPOSITION_INFORMATION:
7710 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7712 #if 0
7713 /* JRA - We used to just ignore this on a path ?
7714 * Shouldn't this be invalid level on a pathname
7715 * based call ?
7717 if (tran_call != TRANSACT2_SETFILEINFO) {
7718 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7720 #endif
7721 status = smb_set_file_disposition_info(conn,
7722 pdata,
7723 total_data,
7724 fsp,
7725 smb_fname);
7726 break;
7729 case SMB_FILE_POSITION_INFORMATION:
7731 status = smb_file_position_information(conn,
7732 pdata,
7733 total_data,
7734 fsp);
7735 break;
7738 case SMB_FILE_FULL_EA_INFORMATION:
7740 status = smb_set_file_full_ea_info(conn,
7741 pdata,
7742 total_data,
7743 fsp);
7744 break;
7747 /* From tridge Samba4 :
7748 * MODE_INFORMATION in setfileinfo (I have no
7749 * idea what "mode information" on a file is - it takes a value of 0,
7750 * 2, 4 or 6. What could it be?).
7753 case SMB_FILE_MODE_INFORMATION:
7755 status = smb_file_mode_information(conn,
7756 pdata,
7757 total_data);
7758 break;
7762 * CIFS UNIX extensions.
7765 case SMB_SET_FILE_UNIX_BASIC:
7767 status = smb_set_file_unix_basic(conn, req,
7768 pdata,
7769 total_data,
7770 fsp,
7771 smb_fname);
7772 break;
7775 case SMB_SET_FILE_UNIX_INFO2:
7777 status = smb_set_file_unix_info2(conn, req,
7778 pdata,
7779 total_data,
7780 fsp,
7781 smb_fname);
7782 break;
7785 case SMB_SET_FILE_UNIX_LINK:
7787 if (fsp) {
7788 /* We must have a pathname for this. */
7789 return NT_STATUS_INVALID_LEVEL;
7791 status = smb_set_file_unix_link(conn, req, pdata,
7792 total_data, smb_fname);
7793 break;
7796 case SMB_SET_FILE_UNIX_HLINK:
7798 if (fsp) {
7799 /* We must have a pathname for this. */
7800 return NT_STATUS_INVALID_LEVEL;
7802 status = smb_set_file_unix_hlink(conn, req,
7803 pdata, total_data,
7804 smb_fname);
7805 break;
7808 case SMB_FILE_RENAME_INFORMATION:
7810 status = smb_file_rename_information(conn, req,
7811 pdata, total_data,
7812 fsp, smb_fname);
7813 break;
7816 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7818 /* SMB2 rename information. */
7819 status = smb2_file_rename_information(conn, req,
7820 pdata, total_data,
7821 fsp, smb_fname);
7822 break;
7825 case SMB_FILE_LINK_INFORMATION:
7827 status = smb_file_link_information(conn, req,
7828 pdata, total_data,
7829 fsp, smb_fname);
7830 break;
7833 #if defined(HAVE_POSIX_ACLS)
7834 case SMB_SET_POSIX_ACL:
7836 status = smb_set_posix_acl(conn,
7837 pdata,
7838 total_data,
7839 fsp,
7840 smb_fname);
7841 break;
7843 #endif
7845 case SMB_SET_POSIX_LOCK:
7847 if (!fsp) {
7848 return NT_STATUS_INVALID_LEVEL;
7850 status = smb_set_posix_lock(conn, req,
7851 pdata, total_data, fsp);
7852 break;
7855 case SMB_POSIX_PATH_OPEN:
7857 if (fsp) {
7858 /* We must have a pathname for this. */
7859 return NT_STATUS_INVALID_LEVEL;
7862 status = smb_posix_open(conn, req,
7863 ppdata,
7864 total_data,
7865 smb_fname,
7866 &data_return_size);
7867 break;
7870 case SMB_POSIX_PATH_UNLINK:
7872 if (fsp) {
7873 /* We must have a pathname for this. */
7874 return NT_STATUS_INVALID_LEVEL;
7877 status = smb_posix_unlink(conn, req,
7878 pdata,
7879 total_data,
7880 smb_fname);
7881 break;
7884 default:
7885 return NT_STATUS_INVALID_LEVEL;
7888 if (!NT_STATUS_IS_OK(status)) {
7889 return status;
7892 *ret_data_size = data_return_size;
7893 return NT_STATUS_OK;
7896 /****************************************************************************
7897 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7898 ****************************************************************************/
7900 static void call_trans2setfilepathinfo(connection_struct *conn,
7901 struct smb_request *req,
7902 unsigned int tran_call,
7903 char **pparams, int total_params,
7904 char **ppdata, int total_data,
7905 unsigned int max_data_bytes)
7907 char *params = *pparams;
7908 char *pdata = *ppdata;
7909 uint16 info_level;
7910 struct smb_filename *smb_fname = NULL;
7911 files_struct *fsp = NULL;
7912 NTSTATUS status = NT_STATUS_OK;
7913 int data_return_size = 0;
7915 if (!params) {
7916 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7917 return;
7920 if (tran_call == TRANSACT2_SETFILEINFO) {
7921 if (total_params < 4) {
7922 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7923 return;
7926 fsp = file_fsp(req, SVAL(params,0));
7927 /* Basic check for non-null fsp. */
7928 if (!check_fsp_open(conn, req, fsp)) {
7929 return;
7931 info_level = SVAL(params,2);
7933 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7934 &smb_fname);
7935 if (!NT_STATUS_IS_OK(status)) {
7936 reply_nterror(req, status);
7937 return;
7940 if(fsp->fh->fd == -1) {
7942 * This is actually a SETFILEINFO on a directory
7943 * handle (returned from an NT SMB). NT5.0 seems
7944 * to do this call. JRA.
7946 if (INFO_LEVEL_IS_UNIX(info_level)) {
7947 /* Always do lstat for UNIX calls. */
7948 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7949 DEBUG(3,("call_trans2setfilepathinfo: "
7950 "SMB_VFS_LSTAT of %s failed "
7951 "(%s)\n",
7952 smb_fname_str_dbg(smb_fname),
7953 strerror(errno)));
7954 reply_nterror(req, map_nt_error_from_unix(errno));
7955 return;
7957 } else {
7958 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7959 DEBUG(3,("call_trans2setfilepathinfo: "
7960 "fileinfo of %s failed (%s)\n",
7961 smb_fname_str_dbg(smb_fname),
7962 strerror(errno)));
7963 reply_nterror(req, map_nt_error_from_unix(errno));
7964 return;
7967 } else if (fsp->print_file) {
7969 * Doing a DELETE_ON_CLOSE should cancel a print job.
7971 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7972 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7974 DEBUG(3,("call_trans2setfilepathinfo: "
7975 "Cancelling print job (%s)\n",
7976 fsp_str_dbg(fsp)));
7978 SSVAL(params,0,0);
7979 send_trans2_replies(conn, req, params, 2,
7980 *ppdata, 0,
7981 max_data_bytes);
7982 return;
7983 } else {
7984 reply_nterror(req,
7985 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7986 return;
7988 } else {
7990 * Original code - this is an open file.
7992 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7993 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7994 "of fnum %d failed (%s)\n", fsp->fnum,
7995 strerror(errno)));
7996 reply_nterror(req, map_nt_error_from_unix(errno));
7997 return;
8000 } else {
8001 char *fname = NULL;
8002 uint32_t ucf_flags = 0;
8004 /* set path info */
8005 if (total_params < 7) {
8006 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8007 return;
8010 info_level = SVAL(params,0);
8011 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
8012 total_params - 6, STR_TERMINATE,
8013 &status);
8014 if (!NT_STATUS_IS_OK(status)) {
8015 reply_nterror(req, status);
8016 return;
8019 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8020 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8021 info_level == SMB_FILE_RENAME_INFORMATION ||
8022 info_level == SMB_POSIX_PATH_UNLINK) {
8023 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8026 status = filename_convert(req, conn,
8027 req->flags2 & FLAGS2_DFS_PATHNAMES,
8028 fname,
8029 ucf_flags,
8030 NULL,
8031 &smb_fname);
8032 if (!NT_STATUS_IS_OK(status)) {
8033 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8034 reply_botherror(req,
8035 NT_STATUS_PATH_NOT_COVERED,
8036 ERRSRV, ERRbadpath);
8037 return;
8039 reply_nterror(req, status);
8040 return;
8043 if (INFO_LEVEL_IS_UNIX(info_level)) {
8045 * For CIFS UNIX extensions the target name may not exist.
8048 /* Always do lstat for UNIX calls. */
8049 SMB_VFS_LSTAT(conn, smb_fname);
8051 } else if (!VALID_STAT(smb_fname->st) &&
8052 SMB_VFS_STAT(conn, smb_fname)) {
8053 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8054 "%s failed (%s)\n",
8055 smb_fname_str_dbg(smb_fname),
8056 strerror(errno)));
8057 reply_nterror(req, map_nt_error_from_unix(errno));
8058 return;
8062 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8063 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8064 fsp ? fsp->fnum : -1, info_level,total_data));
8066 /* Realloc the parameter size */
8067 *pparams = (char *)SMB_REALLOC(*pparams,2);
8068 if (*pparams == NULL) {
8069 reply_nterror(req, NT_STATUS_NO_MEMORY);
8070 return;
8072 params = *pparams;
8074 SSVAL(params,0,0);
8076 status = smbd_do_setfilepathinfo(conn, req, req,
8077 info_level,
8078 fsp,
8079 smb_fname,
8080 ppdata, total_data,
8081 &data_return_size);
8082 if (!NT_STATUS_IS_OK(status)) {
8083 if (open_was_deferred(req->sconn, req->mid)) {
8084 /* We have re-scheduled this call. */
8085 return;
8087 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8088 /* We have re-scheduled this call. */
8089 return;
8091 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8092 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8093 ERRSRV, ERRbadpath);
8094 return;
8096 if (info_level == SMB_POSIX_PATH_OPEN) {
8097 reply_openerror(req, status);
8098 return;
8101 reply_nterror(req, status);
8102 return;
8105 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8106 max_data_bytes);
8108 return;
8111 /****************************************************************************
8112 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8113 ****************************************************************************/
8115 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8116 char **pparams, int total_params,
8117 char **ppdata, int total_data,
8118 unsigned int max_data_bytes)
8120 struct smb_filename *smb_dname = NULL;
8121 char *params = *pparams;
8122 char *pdata = *ppdata;
8123 char *directory = NULL;
8124 NTSTATUS status = NT_STATUS_OK;
8125 struct ea_list *ea_list = NULL;
8126 TALLOC_CTX *ctx = talloc_tos();
8128 if (!CAN_WRITE(conn)) {
8129 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8130 return;
8133 if (total_params < 5) {
8134 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8135 return;
8138 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8139 total_params - 4, STR_TERMINATE,
8140 &status);
8141 if (!NT_STATUS_IS_OK(status)) {
8142 reply_nterror(req, status);
8143 return;
8146 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8148 status = filename_convert(ctx,
8149 conn,
8150 req->flags2 & FLAGS2_DFS_PATHNAMES,
8151 directory,
8153 NULL,
8154 &smb_dname);
8156 if (!NT_STATUS_IS_OK(status)) {
8157 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8158 reply_botherror(req,
8159 NT_STATUS_PATH_NOT_COVERED,
8160 ERRSRV, ERRbadpath);
8161 return;
8163 reply_nterror(req, status);
8164 return;
8168 * OS/2 workplace shell seems to send SET_EA requests of "null"
8169 * length (4 bytes containing IVAL 4).
8170 * They seem to have no effect. Bug #3212. JRA.
8173 if (total_data && (total_data != 4)) {
8174 /* Any data in this call is an EA list. */
8175 if (total_data < 10) {
8176 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8177 goto out;
8180 if (IVAL(pdata,0) > total_data) {
8181 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8182 IVAL(pdata,0), (unsigned int)total_data));
8183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8184 goto out;
8187 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8188 total_data - 4);
8189 if (!ea_list) {
8190 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8191 goto out;
8194 if (!lp_ea_support(SNUM(conn))) {
8195 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8196 goto out;
8199 /* If total_data == 4 Windows doesn't care what values
8200 * are placed in that field, it just ignores them.
8201 * The System i QNTC IBM SMB client puts bad values here,
8202 * so ignore them. */
8204 status = create_directory(conn, req, smb_dname);
8206 if (!NT_STATUS_IS_OK(status)) {
8207 reply_nterror(req, status);
8208 goto out;
8211 /* Try and set any given EA. */
8212 if (ea_list) {
8213 status = set_ea(conn, NULL, smb_dname, ea_list);
8214 if (!NT_STATUS_IS_OK(status)) {
8215 reply_nterror(req, status);
8216 goto out;
8220 /* Realloc the parameter and data sizes */
8221 *pparams = (char *)SMB_REALLOC(*pparams,2);
8222 if(*pparams == NULL) {
8223 reply_nterror(req, NT_STATUS_NO_MEMORY);
8224 goto out;
8226 params = *pparams;
8228 SSVAL(params,0,0);
8230 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8232 out:
8233 TALLOC_FREE(smb_dname);
8234 return;
8237 /****************************************************************************
8238 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8239 We don't actually do this - we just send a null response.
8240 ****************************************************************************/
8242 static void call_trans2findnotifyfirst(connection_struct *conn,
8243 struct smb_request *req,
8244 char **pparams, int total_params,
8245 char **ppdata, int total_data,
8246 unsigned int max_data_bytes)
8248 char *params = *pparams;
8249 uint16 info_level;
8251 if (total_params < 6) {
8252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8253 return;
8256 info_level = SVAL(params,4);
8257 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8259 switch (info_level) {
8260 case 1:
8261 case 2:
8262 break;
8263 default:
8264 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8265 return;
8268 /* Realloc the parameter and data sizes */
8269 *pparams = (char *)SMB_REALLOC(*pparams,6);
8270 if (*pparams == NULL) {
8271 reply_nterror(req, NT_STATUS_NO_MEMORY);
8272 return;
8274 params = *pparams;
8276 SSVAL(params,0,fnf_handle);
8277 SSVAL(params,2,0); /* No changes */
8278 SSVAL(params,4,0); /* No EA errors */
8280 fnf_handle++;
8282 if(fnf_handle == 0)
8283 fnf_handle = 257;
8285 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8287 return;
8290 /****************************************************************************
8291 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8292 changes). Currently this does nothing.
8293 ****************************************************************************/
8295 static void call_trans2findnotifynext(connection_struct *conn,
8296 struct smb_request *req,
8297 char **pparams, int total_params,
8298 char **ppdata, int total_data,
8299 unsigned int max_data_bytes)
8301 char *params = *pparams;
8303 DEBUG(3,("call_trans2findnotifynext\n"));
8305 /* Realloc the parameter and data sizes */
8306 *pparams = (char *)SMB_REALLOC(*pparams,4);
8307 if (*pparams == NULL) {
8308 reply_nterror(req, NT_STATUS_NO_MEMORY);
8309 return;
8311 params = *pparams;
8313 SSVAL(params,0,0); /* No changes */
8314 SSVAL(params,2,0); /* No EA errors */
8316 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8318 return;
8321 /****************************************************************************
8322 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8323 ****************************************************************************/
8325 static void call_trans2getdfsreferral(connection_struct *conn,
8326 struct smb_request *req,
8327 char **pparams, int total_params,
8328 char **ppdata, int total_data,
8329 unsigned int max_data_bytes)
8331 char *params = *pparams;
8332 char *pathname = NULL;
8333 int reply_size = 0;
8334 int max_referral_level;
8335 NTSTATUS status = NT_STATUS_OK;
8336 TALLOC_CTX *ctx = talloc_tos();
8338 DEBUG(10,("call_trans2getdfsreferral\n"));
8340 if (total_params < 3) {
8341 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8342 return;
8345 max_referral_level = SVAL(params,0);
8347 if(!lp_host_msdfs()) {
8348 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8349 return;
8352 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8353 total_params - 2, STR_TERMINATE);
8354 if (!pathname) {
8355 reply_nterror(req, NT_STATUS_NOT_FOUND);
8356 return;
8358 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8359 ppdata,&status)) < 0) {
8360 reply_nterror(req, status);
8361 return;
8364 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8365 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8366 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8368 return;
8371 #define LMCAT_SPL 0x53
8372 #define LMFUNC_GETJOBID 0x60
8374 /****************************************************************************
8375 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8376 ****************************************************************************/
8378 static void call_trans2ioctl(connection_struct *conn,
8379 struct smb_request *req,
8380 char **pparams, int total_params,
8381 char **ppdata, int total_data,
8382 unsigned int max_data_bytes)
8384 char *pdata = *ppdata;
8385 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8387 /* check for an invalid fid before proceeding */
8389 if (!fsp) {
8390 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8391 return;
8394 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8395 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8396 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8397 if (*ppdata == NULL) {
8398 reply_nterror(req, NT_STATUS_NO_MEMORY);
8399 return;
8401 pdata = *ppdata;
8403 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8404 CAN ACCEPT THIS IN UNICODE. JRA. */
8406 /* Job number */
8407 if (fsp->print_file) {
8408 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8409 } else {
8410 SSVAL(pdata, 0, 0);
8412 srvstr_push(pdata, req->flags2, pdata + 2,
8413 lp_netbios_name(), 15,
8414 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8415 srvstr_push(pdata, req->flags2, pdata+18,
8416 lp_servicename(SNUM(conn)), 13,
8417 STR_ASCII|STR_TERMINATE); /* Service name */
8418 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8419 max_data_bytes);
8420 return;
8423 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8424 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8427 /****************************************************************************
8428 Reply to a SMBfindclose (stop trans2 directory search).
8429 ****************************************************************************/
8431 void reply_findclose(struct smb_request *req)
8433 int dptr_num;
8434 struct smbd_server_connection *sconn = req->sconn;
8436 START_PROFILE(SMBfindclose);
8438 if (req->wct < 1) {
8439 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8440 END_PROFILE(SMBfindclose);
8441 return;
8444 dptr_num = SVALS(req->vwv+0, 0);
8446 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8448 dptr_close(sconn, &dptr_num);
8450 reply_outbuf(req, 0, 0);
8452 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8454 END_PROFILE(SMBfindclose);
8455 return;
8458 /****************************************************************************
8459 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8460 ****************************************************************************/
8462 void reply_findnclose(struct smb_request *req)
8464 int dptr_num;
8466 START_PROFILE(SMBfindnclose);
8468 if (req->wct < 1) {
8469 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8470 END_PROFILE(SMBfindnclose);
8471 return;
8474 dptr_num = SVAL(req->vwv+0, 0);
8476 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8478 /* We never give out valid handles for a
8479 findnotifyfirst - so any dptr_num is ok here.
8480 Just ignore it. */
8482 reply_outbuf(req, 0, 0);
8484 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8486 END_PROFILE(SMBfindnclose);
8487 return;
8490 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8491 struct trans_state *state)
8493 if (get_Protocol() >= PROTOCOL_NT1) {
8494 req->flags2 |= 0x40; /* IS_LONG_NAME */
8495 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8498 if (conn->encrypt_level == Required && !req->encrypted) {
8499 if (state->call != TRANSACT2_QFSINFO &&
8500 state->call != TRANSACT2_SETFSINFO) {
8501 DEBUG(0,("handle_trans2: encryption required "
8502 "with call 0x%x\n",
8503 (unsigned int)state->call));
8504 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8505 return;
8509 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8511 /* Now we must call the relevant TRANS2 function */
8512 switch(state->call) {
8513 case TRANSACT2_OPEN:
8515 START_PROFILE(Trans2_open);
8516 call_trans2open(conn, req,
8517 &state->param, state->total_param,
8518 &state->data, state->total_data,
8519 state->max_data_return);
8520 END_PROFILE(Trans2_open);
8521 break;
8524 case TRANSACT2_FINDFIRST:
8526 START_PROFILE(Trans2_findfirst);
8527 call_trans2findfirst(conn, req,
8528 &state->param, state->total_param,
8529 &state->data, state->total_data,
8530 state->max_data_return);
8531 END_PROFILE(Trans2_findfirst);
8532 break;
8535 case TRANSACT2_FINDNEXT:
8537 START_PROFILE(Trans2_findnext);
8538 call_trans2findnext(conn, req,
8539 &state->param, state->total_param,
8540 &state->data, state->total_data,
8541 state->max_data_return);
8542 END_PROFILE(Trans2_findnext);
8543 break;
8546 case TRANSACT2_QFSINFO:
8548 START_PROFILE(Trans2_qfsinfo);
8549 call_trans2qfsinfo(conn, req,
8550 &state->param, state->total_param,
8551 &state->data, state->total_data,
8552 state->max_data_return);
8553 END_PROFILE(Trans2_qfsinfo);
8554 break;
8557 case TRANSACT2_SETFSINFO:
8559 START_PROFILE(Trans2_setfsinfo);
8560 call_trans2setfsinfo(conn, req,
8561 &state->param, state->total_param,
8562 &state->data, state->total_data,
8563 state->max_data_return);
8564 END_PROFILE(Trans2_setfsinfo);
8565 break;
8568 case TRANSACT2_QPATHINFO:
8569 case TRANSACT2_QFILEINFO:
8571 START_PROFILE(Trans2_qpathinfo);
8572 call_trans2qfilepathinfo(conn, req, state->call,
8573 &state->param, state->total_param,
8574 &state->data, state->total_data,
8575 state->max_data_return);
8576 END_PROFILE(Trans2_qpathinfo);
8577 break;
8580 case TRANSACT2_SETPATHINFO:
8581 case TRANSACT2_SETFILEINFO:
8583 START_PROFILE(Trans2_setpathinfo);
8584 call_trans2setfilepathinfo(conn, req, state->call,
8585 &state->param, state->total_param,
8586 &state->data, state->total_data,
8587 state->max_data_return);
8588 END_PROFILE(Trans2_setpathinfo);
8589 break;
8592 case TRANSACT2_FINDNOTIFYFIRST:
8594 START_PROFILE(Trans2_findnotifyfirst);
8595 call_trans2findnotifyfirst(conn, req,
8596 &state->param, state->total_param,
8597 &state->data, state->total_data,
8598 state->max_data_return);
8599 END_PROFILE(Trans2_findnotifyfirst);
8600 break;
8603 case TRANSACT2_FINDNOTIFYNEXT:
8605 START_PROFILE(Trans2_findnotifynext);
8606 call_trans2findnotifynext(conn, req,
8607 &state->param, state->total_param,
8608 &state->data, state->total_data,
8609 state->max_data_return);
8610 END_PROFILE(Trans2_findnotifynext);
8611 break;
8614 case TRANSACT2_MKDIR:
8616 START_PROFILE(Trans2_mkdir);
8617 call_trans2mkdir(conn, req,
8618 &state->param, state->total_param,
8619 &state->data, state->total_data,
8620 state->max_data_return);
8621 END_PROFILE(Trans2_mkdir);
8622 break;
8625 case TRANSACT2_GET_DFS_REFERRAL:
8627 START_PROFILE(Trans2_get_dfs_referral);
8628 call_trans2getdfsreferral(conn, req,
8629 &state->param, state->total_param,
8630 &state->data, state->total_data,
8631 state->max_data_return);
8632 END_PROFILE(Trans2_get_dfs_referral);
8633 break;
8636 case TRANSACT2_IOCTL:
8638 START_PROFILE(Trans2_ioctl);
8639 call_trans2ioctl(conn, req,
8640 &state->param, state->total_param,
8641 &state->data, state->total_data,
8642 state->max_data_return);
8643 END_PROFILE(Trans2_ioctl);
8644 break;
8647 default:
8648 /* Error in request */
8649 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8650 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8654 /****************************************************************************
8655 Reply to a SMBtrans2.
8656 ****************************************************************************/
8658 void reply_trans2(struct smb_request *req)
8660 connection_struct *conn = req->conn;
8661 unsigned int dsoff;
8662 unsigned int dscnt;
8663 unsigned int psoff;
8664 unsigned int pscnt;
8665 unsigned int tran_call;
8666 struct trans_state *state;
8667 NTSTATUS result;
8669 START_PROFILE(SMBtrans2);
8671 if (req->wct < 14) {
8672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8673 END_PROFILE(SMBtrans2);
8674 return;
8677 dsoff = SVAL(req->vwv+12, 0);
8678 dscnt = SVAL(req->vwv+11, 0);
8679 psoff = SVAL(req->vwv+10, 0);
8680 pscnt = SVAL(req->vwv+9, 0);
8681 tran_call = SVAL(req->vwv+14, 0);
8683 result = allow_new_trans(conn->pending_trans, req->mid);
8684 if (!NT_STATUS_IS_OK(result)) {
8685 DEBUG(2, ("Got invalid trans2 request: %s\n",
8686 nt_errstr(result)));
8687 reply_nterror(req, result);
8688 END_PROFILE(SMBtrans2);
8689 return;
8692 if (IS_IPC(conn)) {
8693 switch (tran_call) {
8694 /* List the allowed trans2 calls on IPC$ */
8695 case TRANSACT2_OPEN:
8696 case TRANSACT2_GET_DFS_REFERRAL:
8697 case TRANSACT2_QFILEINFO:
8698 case TRANSACT2_QFSINFO:
8699 case TRANSACT2_SETFSINFO:
8700 break;
8701 default:
8702 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8703 END_PROFILE(SMBtrans2);
8704 return;
8708 if ((state = talloc(conn, struct trans_state)) == NULL) {
8709 DEBUG(0, ("talloc failed\n"));
8710 reply_nterror(req, NT_STATUS_NO_MEMORY);
8711 END_PROFILE(SMBtrans2);
8712 return;
8715 state->cmd = SMBtrans2;
8717 state->mid = req->mid;
8718 state->vuid = req->vuid;
8719 state->setup_count = SVAL(req->vwv+13, 0);
8720 state->setup = NULL;
8721 state->total_param = SVAL(req->vwv+0, 0);
8722 state->param = NULL;
8723 state->total_data = SVAL(req->vwv+1, 0);
8724 state->data = NULL;
8725 state->max_param_return = SVAL(req->vwv+2, 0);
8726 state->max_data_return = SVAL(req->vwv+3, 0);
8727 state->max_setup_return = SVAL(req->vwv+4, 0);
8728 state->close_on_completion = BITSETW(req->vwv+5, 0);
8729 state->one_way = BITSETW(req->vwv+5, 1);
8731 state->call = tran_call;
8733 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8734 is so as a sanity check */
8735 if (state->setup_count != 1) {
8737 * Need to have rc=0 for ioctl to get job id for OS/2.
8738 * Network printing will fail if function is not successful.
8739 * Similar function in reply.c will be used if protocol
8740 * is LANMAN1.0 instead of LM1.2X002.
8741 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8742 * outbuf doesn't have to be set(only job id is used).
8744 if ( (state->setup_count == 4)
8745 && (tran_call == TRANSACT2_IOCTL)
8746 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8747 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8748 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8749 } else {
8750 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8751 DEBUG(2,("Transaction is %d\n",tran_call));
8752 TALLOC_FREE(state);
8753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8754 END_PROFILE(SMBtrans2);
8755 return;
8759 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8760 goto bad_param;
8762 if (state->total_data) {
8764 if (trans_oob(state->total_data, 0, dscnt)
8765 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8766 goto bad_param;
8769 /* Can't use talloc here, the core routines do realloc on the
8770 * params and data. */
8771 state->data = (char *)SMB_MALLOC(state->total_data);
8772 if (state->data == NULL) {
8773 DEBUG(0,("reply_trans2: data malloc fail for %u "
8774 "bytes !\n", (unsigned int)state->total_data));
8775 TALLOC_FREE(state);
8776 reply_nterror(req, NT_STATUS_NO_MEMORY);
8777 END_PROFILE(SMBtrans2);
8778 return;
8781 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8784 if (state->total_param) {
8786 if (trans_oob(state->total_param, 0, pscnt)
8787 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8788 goto bad_param;
8791 /* Can't use talloc here, the core routines do realloc on the
8792 * params and data. */
8793 state->param = (char *)SMB_MALLOC(state->total_param);
8794 if (state->param == NULL) {
8795 DEBUG(0,("reply_trans: param malloc fail for %u "
8796 "bytes !\n", (unsigned int)state->total_param));
8797 SAFE_FREE(state->data);
8798 TALLOC_FREE(state);
8799 reply_nterror(req, NT_STATUS_NO_MEMORY);
8800 END_PROFILE(SMBtrans2);
8801 return;
8804 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8807 state->received_data = dscnt;
8808 state->received_param = pscnt;
8810 if ((state->received_param == state->total_param) &&
8811 (state->received_data == state->total_data)) {
8813 handle_trans2(conn, req, state);
8815 SAFE_FREE(state->data);
8816 SAFE_FREE(state->param);
8817 TALLOC_FREE(state);
8818 END_PROFILE(SMBtrans2);
8819 return;
8822 DLIST_ADD(conn->pending_trans, state);
8824 /* We need to send an interim response then receive the rest
8825 of the parameter/data bytes */
8826 reply_outbuf(req, 0, 0);
8827 show_msg((char *)req->outbuf);
8828 END_PROFILE(SMBtrans2);
8829 return;
8831 bad_param:
8833 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8834 SAFE_FREE(state->data);
8835 SAFE_FREE(state->param);
8836 TALLOC_FREE(state);
8837 END_PROFILE(SMBtrans2);
8838 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8842 /****************************************************************************
8843 Reply to a SMBtranss2
8844 ****************************************************************************/
8846 void reply_transs2(struct smb_request *req)
8848 connection_struct *conn = req->conn;
8849 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8850 struct trans_state *state;
8852 START_PROFILE(SMBtranss2);
8854 show_msg((const char *)req->inbuf);
8856 if (req->wct < 8) {
8857 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8858 END_PROFILE(SMBtranss2);
8859 return;
8862 for (state = conn->pending_trans; state != NULL;
8863 state = state->next) {
8864 if (state->mid == req->mid) {
8865 break;
8869 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8871 END_PROFILE(SMBtranss2);
8872 return;
8875 /* Revise state->total_param and state->total_data in case they have
8876 changed downwards */
8878 if (SVAL(req->vwv+0, 0) < state->total_param)
8879 state->total_param = SVAL(req->vwv+0, 0);
8880 if (SVAL(req->vwv+1, 0) < state->total_data)
8881 state->total_data = SVAL(req->vwv+1, 0);
8883 pcnt = SVAL(req->vwv+2, 0);
8884 poff = SVAL(req->vwv+3, 0);
8885 pdisp = SVAL(req->vwv+4, 0);
8887 dcnt = SVAL(req->vwv+5, 0);
8888 doff = SVAL(req->vwv+6, 0);
8889 ddisp = SVAL(req->vwv+7, 0);
8891 state->received_param += pcnt;
8892 state->received_data += dcnt;
8894 if ((state->received_data > state->total_data) ||
8895 (state->received_param > state->total_param))
8896 goto bad_param;
8898 if (pcnt) {
8899 if (trans_oob(state->total_param, pdisp, pcnt)
8900 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8901 goto bad_param;
8903 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8906 if (dcnt) {
8907 if (trans_oob(state->total_data, ddisp, dcnt)
8908 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8909 goto bad_param;
8911 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8914 if ((state->received_param < state->total_param) ||
8915 (state->received_data < state->total_data)) {
8916 END_PROFILE(SMBtranss2);
8917 return;
8920 handle_trans2(conn, req, state);
8922 DLIST_REMOVE(conn->pending_trans, state);
8923 SAFE_FREE(state->data);
8924 SAFE_FREE(state->param);
8925 TALLOC_FREE(state);
8927 END_PROFILE(SMBtranss2);
8928 return;
8930 bad_param:
8932 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8933 DLIST_REMOVE(conn->pending_trans, state);
8934 SAFE_FREE(state->data);
8935 SAFE_FREE(state->param);
8936 TALLOC_FREE(state);
8937 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8938 END_PROFILE(SMBtranss2);
8939 return;