Fix bug #7651 - mknod and mkfifo fails with "No such file or directory"
[Samba/bb.git] / source3 / smbd / trans2.c
blob84139daa0e199c578fd49e40040e7d63dbff2c90
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "version.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 #define DIR_ENTRY_SAFETY_MARGIN 4096
33 static char *store_file_unix_basic(connection_struct *conn,
34 char *pdata,
35 files_struct *fsp,
36 const SMB_STRUCT_STAT *psbuf);
38 static char *store_file_unix_basic_info2(connection_struct *conn,
39 char *pdata,
40 files_struct *fsp,
41 const SMB_STRUCT_STAT *psbuf);
43 /********************************************************************
44 Roundup a value to the nearest allocation roundup size boundary.
45 Only do this for Windows clients.
46 ********************************************************************/
48 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
50 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
52 /* Only roundup for Windows clients. */
53 enum remote_arch_types ra_type = get_remote_arch();
54 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
55 val = SMB_ROUNDUP(val,rval);
57 return val;
60 /********************************************************************
61 Create a 64 bit FileIndex. If the file is on the same device as
62 the root of the share, just return the 64-bit inode. If it isn't,
63 mangle as we used to do.
64 ********************************************************************/
66 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
68 uint64_t file_index;
69 if (conn->base_share_dev == psbuf->st_ex_dev) {
70 return (uint64_t)psbuf->st_ex_ino;
72 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
73 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
74 return file_index;
77 /****************************************************************************
78 Utility functions for dealing with extended attributes.
79 ****************************************************************************/
81 /****************************************************************************
82 Refuse to allow clients to overwrite our private xattrs.
83 ****************************************************************************/
85 static bool samba_private_attr_name(const char *unix_ea_name)
87 static const char * const prohibited_ea_names[] = {
88 SAMBA_POSIX_INHERITANCE_EA_NAME,
89 SAMBA_XATTR_DOS_ATTRIB,
90 SAMBA_XATTR_MARKER,
91 XATTR_NTACL_NAME,
92 NULL
95 int i;
97 for (i = 0; prohibited_ea_names[i]; i++) {
98 if (strequal( prohibited_ea_names[i], unix_ea_name))
99 return true;
101 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
102 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
103 return true;
105 return false;
108 /****************************************************************************
109 Get one EA value. Fill in a struct ea_struct.
110 ****************************************************************************/
112 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
113 files_struct *fsp, const char *fname,
114 const char *ea_name, struct ea_struct *pea)
116 /* Get the value of this xattr. Max size is 64k. */
117 size_t attr_size = 256;
118 char *val = NULL;
119 ssize_t sizeret;
121 again:
123 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
124 if (!val) {
125 return NT_STATUS_NO_MEMORY;
128 if (fsp && fsp->fh->fd != -1) {
129 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
130 } else {
131 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
134 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
135 attr_size = 65536;
136 goto again;
139 if (sizeret == -1) {
140 return map_nt_error_from_unix(errno);
143 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
144 dump_data(10, (uint8 *)val, sizeret);
146 pea->flags = 0;
147 if (strnequal(ea_name, "user.", 5)) {
148 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
149 } else {
150 pea->name = talloc_strdup(mem_ctx, ea_name);
152 if (pea->name == NULL) {
153 TALLOC_FREE(val);
154 return NT_STATUS_NO_MEMORY;
156 pea->value.data = (unsigned char *)val;
157 pea->value.length = (size_t)sizeret;
158 return NT_STATUS_OK;
161 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
162 files_struct *fsp, const char *fname,
163 char ***pnames, size_t *pnum_names)
165 /* Get a list of all xattrs. Max namesize is 64k. */
166 size_t ea_namelist_size = 1024;
167 char *ea_namelist = NULL;
169 char *p;
170 char **names, **tmp;
171 size_t num_names;
172 ssize_t sizeret = -1;
174 if (!lp_ea_support(SNUM(conn))) {
175 if (pnames) {
176 *pnames = NULL;
178 *pnum_names = 0;
179 return NT_STATUS_OK;
183 * TALLOC the result early to get the talloc hierarchy right.
186 names = TALLOC_ARRAY(mem_ctx, char *, 1);
187 if (names == NULL) {
188 DEBUG(0, ("talloc failed\n"));
189 return NT_STATUS_NO_MEMORY;
192 while (ea_namelist_size <= 65536) {
194 ea_namelist = TALLOC_REALLOC_ARRAY(
195 names, ea_namelist, char, ea_namelist_size);
196 if (ea_namelist == NULL) {
197 DEBUG(0, ("talloc failed\n"));
198 TALLOC_FREE(names);
199 return NT_STATUS_NO_MEMORY;
202 if (fsp && fsp->fh->fd != -1) {
203 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
204 ea_namelist_size);
205 } else {
206 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
207 ea_namelist_size);
210 if ((sizeret == -1) && (errno == ERANGE)) {
211 ea_namelist_size *= 2;
213 else {
214 break;
218 if (sizeret == -1) {
219 TALLOC_FREE(names);
220 return map_nt_error_from_unix(errno);
223 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
224 (unsigned int)sizeret));
226 if (sizeret == 0) {
227 TALLOC_FREE(names);
228 if (pnames) {
229 *pnames = NULL;
231 *pnum_names = 0;
232 return NT_STATUS_OK;
236 * Ensure the result is 0-terminated
239 if (ea_namelist[sizeret-1] != '\0') {
240 TALLOC_FREE(names);
241 return NT_STATUS_INTERNAL_ERROR;
245 * count the names
247 num_names = 0;
249 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
250 num_names += 1;
253 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
254 if (tmp == NULL) {
255 DEBUG(0, ("talloc failed\n"));
256 TALLOC_FREE(names);
257 return NT_STATUS_NO_MEMORY;
260 names = tmp;
261 num_names = 0;
263 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
264 names[num_names++] = p;
267 if (pnames) {
268 *pnames = names;
269 } else {
270 TALLOC_FREE(names);
272 *pnum_names = num_names;
273 return NT_STATUS_OK;
276 /****************************************************************************
277 Return a linked list of the total EA's. Plus the total size
278 ****************************************************************************/
280 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
281 const char *fname, size_t *pea_total_len)
283 /* Get a list of all xattrs. Max namesize is 64k. */
284 size_t i, num_names;
285 char **names;
286 struct ea_list *ea_list_head = NULL;
287 NTSTATUS status;
289 *pea_total_len = 0;
291 if (!lp_ea_support(SNUM(conn))) {
292 return NULL;
295 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
296 &names, &num_names);
298 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
299 return NULL;
302 for (i=0; i<num_names; i++) {
303 struct ea_list *listp;
304 fstring dos_ea_name;
306 if (strnequal(names[i], "system.", 7)
307 || samba_private_attr_name(names[i]))
308 continue;
310 listp = TALLOC_P(mem_ctx, struct ea_list);
311 if (listp == NULL) {
312 return NULL;
315 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
316 fname, names[i],
317 &listp->ea))) {
318 return NULL;
321 push_ascii_fstring(dos_ea_name, listp->ea.name);
323 *pea_total_len +=
324 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
326 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
327 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
328 (unsigned int)listp->ea.value.length));
330 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
334 /* Add on 4 for total length. */
335 if (*pea_total_len) {
336 *pea_total_len += 4;
339 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
340 (unsigned int)*pea_total_len));
342 return ea_list_head;
345 /****************************************************************************
346 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
347 that was filled.
348 ****************************************************************************/
350 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
351 connection_struct *conn, struct ea_list *ea_list)
353 unsigned int ret_data_size = 4;
354 char *p = pdata;
356 SMB_ASSERT(total_data_size >= 4);
358 if (!lp_ea_support(SNUM(conn))) {
359 SIVAL(pdata,4,0);
360 return 4;
363 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
364 size_t dos_namelen;
365 fstring dos_ea_name;
366 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
367 dos_namelen = strlen(dos_ea_name);
368 if (dos_namelen > 255 || dos_namelen == 0) {
369 break;
371 if (ea_list->ea.value.length > 65535) {
372 break;
374 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
375 break;
378 /* We know we have room. */
379 SCVAL(p,0,ea_list->ea.flags);
380 SCVAL(p,1,dos_namelen);
381 SSVAL(p,2,ea_list->ea.value.length);
382 fstrcpy(p+4, dos_ea_name);
383 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
385 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
386 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
389 ret_data_size = PTR_DIFF(p, pdata);
390 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
391 SIVAL(pdata,0,ret_data_size);
392 return ret_data_size;
395 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
396 char *pdata,
397 unsigned int total_data_size,
398 unsigned int *ret_data_size,
399 connection_struct *conn,
400 struct ea_list *ea_list)
402 uint8_t *p = (uint8_t *)pdata;
403 uint8_t *last_start = NULL;
405 *ret_data_size = 0;
407 if (!lp_ea_support(SNUM(conn))) {
408 return NT_STATUS_NO_EAS_ON_FILE;
411 for (; ea_list; ea_list = ea_list->next) {
412 size_t dos_namelen;
413 fstring dos_ea_name;
414 size_t this_size;
416 if (last_start) {
417 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
419 last_start = p;
421 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
422 dos_namelen = strlen(dos_ea_name);
423 if (dos_namelen > 255 || dos_namelen == 0) {
424 return NT_STATUS_INTERNAL_ERROR;
426 if (ea_list->ea.value.length > 65535) {
427 return NT_STATUS_INTERNAL_ERROR;
430 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
432 if (ea_list->next) {
433 size_t pad = 4 - (this_size % 4);
434 this_size += pad;
437 if (this_size > total_data_size) {
438 return NT_STATUS_INFO_LENGTH_MISMATCH;
441 /* We know we have room. */
442 SIVAL(p, 0x00, 0); /* next offset */
443 SCVAL(p, 0x04, ea_list->ea.flags);
444 SCVAL(p, 0x05, dos_namelen);
445 SSVAL(p, 0x06, ea_list->ea.value.length);
446 fstrcpy((char *)(p+0x08), dos_ea_name);
447 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
449 total_data_size -= this_size;
450 p += this_size;
453 *ret_data_size = PTR_DIFF(p, pdata);
454 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
455 return NT_STATUS_OK;
458 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
460 size_t total_ea_len = 0;
461 TALLOC_CTX *mem_ctx = NULL;
463 if (!lp_ea_support(SNUM(conn))) {
464 return 0;
466 mem_ctx = talloc_tos();
467 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
468 return total_ea_len;
471 /****************************************************************************
472 Ensure the EA name is case insensitive by matching any existing EA name.
473 ****************************************************************************/
475 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
477 size_t total_ea_len;
478 TALLOC_CTX *mem_ctx = talloc_tos();
479 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
481 for (; ea_list; ea_list = ea_list->next) {
482 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
483 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
484 &unix_ea_name[5], ea_list->ea.name));
485 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
486 break;
491 /****************************************************************************
492 Set or delete an extended attribute.
493 ****************************************************************************/
495 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
496 const struct smb_filename *smb_fname, struct ea_list *ea_list)
498 char *fname = NULL;
500 if (!lp_ea_support(SNUM(conn))) {
501 return NT_STATUS_EAS_NOT_SUPPORTED;
504 /* For now setting EAs on streams isn't supported. */
505 fname = smb_fname->base_name;
507 for (;ea_list; ea_list = ea_list->next) {
508 int ret;
509 fstring unix_ea_name;
511 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
512 fstrcat(unix_ea_name, ea_list->ea.name);
514 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
516 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
518 if (samba_private_attr_name(unix_ea_name)) {
519 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
520 return NT_STATUS_ACCESS_DENIED;
523 if (ea_list->ea.value.length == 0) {
524 /* Remove the attribute. */
525 if (fsp && (fsp->fh->fd != -1)) {
526 DEBUG(10,("set_ea: deleting ea name %s on "
527 "file %s by file descriptor.\n",
528 unix_ea_name, fsp_str_dbg(fsp)));
529 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
530 } else {
531 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
532 unix_ea_name, fname));
533 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
535 #ifdef ENOATTR
536 /* Removing a non existent attribute always succeeds. */
537 if (ret == -1 && errno == ENOATTR) {
538 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
539 unix_ea_name));
540 ret = 0;
542 #endif
543 } else {
544 if (fsp && (fsp->fh->fd != -1)) {
545 DEBUG(10,("set_ea: setting ea name %s on file "
546 "%s by file descriptor.\n",
547 unix_ea_name, fsp_str_dbg(fsp)));
548 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
549 ea_list->ea.value.data, ea_list->ea.value.length, 0);
550 } else {
551 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
552 unix_ea_name, fname));
553 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
554 ea_list->ea.value.data, ea_list->ea.value.length, 0);
558 if (ret == -1) {
559 #ifdef ENOTSUP
560 if (errno == ENOTSUP) {
561 return NT_STATUS_EAS_NOT_SUPPORTED;
563 #endif
564 return map_nt_error_from_unix(errno);
568 return NT_STATUS_OK;
570 /****************************************************************************
571 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
572 ****************************************************************************/
574 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
576 struct ea_list *ea_list_head = NULL;
577 size_t converted_size, offset = 0;
579 while (offset + 2 < data_size) {
580 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
581 unsigned int namelen = CVAL(pdata,offset);
583 offset++; /* Go past the namelen byte. */
585 /* integer wrap paranioa. */
586 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
587 (offset > data_size) || (namelen > data_size) ||
588 (offset + namelen >= data_size)) {
589 break;
591 /* Ensure the name is null terminated. */
592 if (pdata[offset + namelen] != '\0') {
593 return NULL;
595 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
596 &converted_size)) {
597 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
598 "failed: %s", strerror(errno)));
600 if (!eal->ea.name) {
601 return NULL;
604 offset += (namelen + 1); /* Go past the name + terminating zero. */
605 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
606 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
609 return ea_list_head;
612 /****************************************************************************
613 Read one EA list entry from the buffer.
614 ****************************************************************************/
616 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
618 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
619 uint16 val_len;
620 unsigned int namelen;
621 size_t converted_size;
623 if (!eal) {
624 return NULL;
627 if (data_size < 6) {
628 return NULL;
631 eal->ea.flags = CVAL(pdata,0);
632 namelen = CVAL(pdata,1);
633 val_len = SVAL(pdata,2);
635 if (4 + namelen + 1 + val_len > data_size) {
636 return NULL;
639 /* Ensure the name is null terminated. */
640 if (pdata[namelen + 4] != '\0') {
641 return NULL;
643 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
644 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
645 strerror(errno)));
647 if (!eal->ea.name) {
648 return NULL;
651 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
652 if (!eal->ea.value.data) {
653 return NULL;
656 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
658 /* Ensure we're null terminated just in case we print the value. */
659 eal->ea.value.data[val_len] = '\0';
660 /* But don't count the null. */
661 eal->ea.value.length--;
663 if (pbytes_used) {
664 *pbytes_used = 4 + namelen + 1 + val_len;
667 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
668 dump_data(10, eal->ea.value.data, eal->ea.value.length);
670 return eal;
673 /****************************************************************************
674 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
675 ****************************************************************************/
677 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
679 struct ea_list *ea_list_head = NULL;
680 size_t offset = 0;
681 size_t bytes_used = 0;
683 while (offset < data_size) {
684 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
686 if (!eal) {
687 return NULL;
690 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
691 offset += bytes_used;
694 return ea_list_head;
697 /****************************************************************************
698 Count the total EA size needed.
699 ****************************************************************************/
701 static size_t ea_list_size(struct ea_list *ealist)
703 fstring dos_ea_name;
704 struct ea_list *listp;
705 size_t ret = 0;
707 for (listp = ealist; listp; listp = listp->next) {
708 push_ascii_fstring(dos_ea_name, listp->ea.name);
709 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
711 /* Add on 4 for total length. */
712 if (ret) {
713 ret += 4;
716 return ret;
719 /****************************************************************************
720 Return a union of EA's from a file list and a list of names.
721 The TALLOC context for the two lists *MUST* be identical as we steal
722 memory from one list to add to another. JRA.
723 ****************************************************************************/
725 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
727 struct ea_list *nlistp, *flistp;
729 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
730 for (flistp = file_list; flistp; flistp = flistp->next) {
731 if (strequal(nlistp->ea.name, flistp->ea.name)) {
732 break;
736 if (flistp) {
737 /* Copy the data from this entry. */
738 nlistp->ea.flags = flistp->ea.flags;
739 nlistp->ea.value = flistp->ea.value;
740 } else {
741 /* Null entry. */
742 nlistp->ea.flags = 0;
743 ZERO_STRUCT(nlistp->ea.value);
747 *total_ea_len = ea_list_size(name_list);
748 return name_list;
751 /****************************************************************************
752 Send the required number of replies back.
753 We assume all fields other than the data fields are
754 set correctly for the type of call.
755 HACK ! Always assumes smb_setup field is zero.
756 ****************************************************************************/
758 void send_trans2_replies(connection_struct *conn,
759 struct smb_request *req,
760 const char *params,
761 int paramsize,
762 const char *pdata,
763 int datasize,
764 int max_data_bytes)
766 /* As we are using a protocol > LANMAN1 then the max_send
767 variable must have been set in the sessetupX call.
768 This takes precedence over the max_xmit field in the
769 global struct. These different max_xmit variables should
770 be merged as this is now too confusing */
772 int data_to_send = datasize;
773 int params_to_send = paramsize;
774 int useable_space;
775 const char *pp = params;
776 const char *pd = pdata;
777 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
778 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
779 int data_alignment_offset = 0;
780 bool overflow = False;
781 struct smbd_server_connection *sconn = smbd_server_conn;
782 int max_send = sconn->smb1.sessions.max_send;
784 /* Modify the data_to_send and datasize and set the error if
785 we're trying to send more than max_data_bytes. We still send
786 the part of the packet(s) that fit. Strange, but needed
787 for OS/2. */
789 if (max_data_bytes > 0 && datasize > max_data_bytes) {
790 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
791 max_data_bytes, datasize ));
792 datasize = data_to_send = max_data_bytes;
793 overflow = True;
796 /* If there genuinely are no parameters or data to send just send the empty packet */
798 if(params_to_send == 0 && data_to_send == 0) {
799 reply_outbuf(req, 10, 0);
800 show_msg((char *)req->outbuf);
801 if (!srv_send_smb(smbd_server_fd(),
802 (char *)req->outbuf,
803 true, req->seqnum+1,
804 IS_CONN_ENCRYPTED(conn),
805 &req->pcd)) {
806 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
808 TALLOC_FREE(req->outbuf);
809 return;
812 /* When sending params and data ensure that both are nicely aligned */
813 /* Only do this alignment when there is also data to send - else
814 can cause NT redirector problems. */
816 if (((params_to_send % 4) != 0) && (data_to_send != 0))
817 data_alignment_offset = 4 - (params_to_send % 4);
819 /* Space is bufsize minus Netbios over TCP header minus SMB header */
820 /* The alignment_offset is to align the param bytes on an even byte
821 boundary. NT 4.0 Beta needs this to work correctly. */
823 useable_space = max_send - (smb_size
824 + 2 * 10 /* wct */
825 + alignment_offset
826 + data_alignment_offset);
828 if (useable_space < 0) {
829 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
830 "= %d!!!", useable_space));
831 exit_server_cleanly("send_trans2_replies: Not enough space");
834 while (params_to_send || data_to_send) {
835 /* Calculate whether we will totally or partially fill this packet */
837 total_sent_thistime = params_to_send + data_to_send;
839 /* We can never send more than useable_space */
841 * Note that 'useable_space' does not include the alignment offsets,
842 * but we must include the alignment offsets in the calculation of
843 * the length of the data we send over the wire, as the alignment offsets
844 * are sent here. Fix from Marc_Jacobsen@hp.com.
847 total_sent_thistime = MIN(total_sent_thistime, useable_space);
849 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
850 + data_alignment_offset);
853 * We might have SMBtrans2s in req which was transferred to
854 * the outbuf, fix that.
856 SCVAL(req->outbuf, smb_com, SMBtrans2);
858 /* Set total params and data to be sent */
859 SSVAL(req->outbuf,smb_tprcnt,paramsize);
860 SSVAL(req->outbuf,smb_tdrcnt,datasize);
862 /* Calculate how many parameters and data we can fit into
863 * this packet. Parameters get precedence
866 params_sent_thistime = MIN(params_to_send,useable_space);
867 data_sent_thistime = useable_space - params_sent_thistime;
868 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
870 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
872 /* smb_proff is the offset from the start of the SMB header to the
873 parameter bytes, however the first 4 bytes of outbuf are
874 the Netbios over TCP header. Thus use smb_base() to subtract
875 them from the calculation */
877 SSVAL(req->outbuf,smb_proff,
878 ((smb_buf(req->outbuf)+alignment_offset)
879 - smb_base(req->outbuf)));
881 if(params_sent_thistime == 0)
882 SSVAL(req->outbuf,smb_prdisp,0);
883 else
884 /* Absolute displacement of param bytes sent in this packet */
885 SSVAL(req->outbuf,smb_prdisp,pp - params);
887 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
888 if(data_sent_thistime == 0) {
889 SSVAL(req->outbuf,smb_droff,0);
890 SSVAL(req->outbuf,smb_drdisp, 0);
891 } else {
892 /* The offset of the data bytes is the offset of the
893 parameter bytes plus the number of parameters being sent this time */
894 SSVAL(req->outbuf, smb_droff,
895 ((smb_buf(req->outbuf)+alignment_offset)
896 - smb_base(req->outbuf))
897 + params_sent_thistime + data_alignment_offset);
898 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
901 /* Initialize the padding for alignment */
903 if (alignment_offset != 0) {
904 memset(smb_buf(req->outbuf), 0, alignment_offset);
907 /* Copy the param bytes into the packet */
909 if(params_sent_thistime) {
910 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
911 params_sent_thistime);
914 /* Copy in the data bytes */
915 if(data_sent_thistime) {
916 if (data_alignment_offset != 0) {
917 memset((smb_buf(req->outbuf)+alignment_offset+
918 params_sent_thistime), 0,
919 data_alignment_offset);
921 memcpy(smb_buf(req->outbuf)+alignment_offset
922 +params_sent_thistime+data_alignment_offset,
923 pd,data_sent_thistime);
926 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
927 params_sent_thistime, data_sent_thistime, useable_space));
928 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
929 params_to_send, data_to_send, paramsize, datasize));
931 if (overflow) {
932 error_packet_set((char *)req->outbuf,
933 ERRDOS,ERRbufferoverflow,
934 STATUS_BUFFER_OVERFLOW,
935 __LINE__,__FILE__);
938 /* Send the packet */
939 show_msg((char *)req->outbuf);
940 if (!srv_send_smb(smbd_server_fd(),
941 (char *)req->outbuf,
942 true, req->seqnum+1,
943 IS_CONN_ENCRYPTED(conn),
944 &req->pcd))
945 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
947 TALLOC_FREE(req->outbuf);
949 pp += params_sent_thistime;
950 pd += data_sent_thistime;
952 params_to_send -= params_sent_thistime;
953 data_to_send -= data_sent_thistime;
955 /* Sanity check */
956 if(params_to_send < 0 || data_to_send < 0) {
957 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
958 params_to_send, data_to_send));
959 return;
963 return;
966 /****************************************************************************
967 Reply to a TRANSACT2_OPEN.
968 ****************************************************************************/
970 static void call_trans2open(connection_struct *conn,
971 struct smb_request *req,
972 char **pparams, int total_params,
973 char **ppdata, int total_data,
974 unsigned int max_data_bytes)
976 struct smb_filename *smb_fname = NULL;
977 char *params = *pparams;
978 char *pdata = *ppdata;
979 int deny_mode;
980 int32 open_attr;
981 bool oplock_request;
982 #if 0
983 bool return_additional_info;
984 int16 open_sattr;
985 time_t open_time;
986 #endif
987 int open_ofun;
988 uint32 open_size;
989 char *pname;
990 char *fname = NULL;
991 SMB_OFF_T size=0;
992 int fattr=0,mtime=0;
993 SMB_INO_T inode = 0;
994 int smb_action = 0;
995 files_struct *fsp;
996 struct ea_list *ea_list = NULL;
997 uint16 flags = 0;
998 NTSTATUS status;
999 uint32 access_mask;
1000 uint32 share_mode;
1001 uint32 create_disposition;
1002 uint32 create_options = 0;
1003 TALLOC_CTX *ctx = talloc_tos();
1006 * Ensure we have enough parameters to perform the operation.
1009 if (total_params < 29) {
1010 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1011 goto out;
1014 flags = SVAL(params, 0);
1015 deny_mode = SVAL(params, 2);
1016 open_attr = SVAL(params,6);
1017 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1018 if (oplock_request) {
1019 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1022 #if 0
1023 return_additional_info = BITSETW(params,0);
1024 open_sattr = SVAL(params, 4);
1025 open_time = make_unix_date3(params+8);
1026 #endif
1027 open_ofun = SVAL(params,12);
1028 open_size = IVAL(params,14);
1029 pname = &params[28];
1031 if (IS_IPC(conn)) {
1032 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1033 goto out;
1036 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1037 total_params - 28, STR_TERMINATE,
1038 &status);
1039 if (!NT_STATUS_IS_OK(status)) {
1040 reply_nterror(req, status);
1041 goto out;
1044 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1045 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1046 (unsigned int)open_ofun, open_size));
1048 status = filename_convert(ctx,
1049 conn,
1050 req->flags2 & FLAGS2_DFS_PATHNAMES,
1051 fname,
1053 NULL,
1054 &smb_fname);
1055 if (!NT_STATUS_IS_OK(status)) {
1056 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1057 reply_botherror(req,
1058 NT_STATUS_PATH_NOT_COVERED,
1059 ERRSRV, ERRbadpath);
1060 goto out;
1062 reply_nterror(req, status);
1063 goto out;
1066 if (open_ofun == 0) {
1067 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1068 goto out;
1071 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1072 &access_mask, &share_mode,
1073 &create_disposition,
1074 &create_options)) {
1075 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1076 goto out;
1079 /* Any data in this call is an EA list. */
1080 if (total_data && (total_data != 4)) {
1081 if (total_data < 10) {
1082 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1083 goto out;
1086 if (IVAL(pdata,0) > total_data) {
1087 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1088 IVAL(pdata,0), (unsigned int)total_data));
1089 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1090 goto out;
1093 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1094 total_data - 4);
1095 if (!ea_list) {
1096 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1097 goto out;
1100 if (!lp_ea_support(SNUM(conn))) {
1101 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1102 goto out;
1106 status = SMB_VFS_CREATE_FILE(
1107 conn, /* conn */
1108 req, /* req */
1109 0, /* root_dir_fid */
1110 smb_fname, /* fname */
1111 access_mask, /* access_mask */
1112 share_mode, /* share_access */
1113 create_disposition, /* create_disposition*/
1114 create_options, /* create_options */
1115 open_attr, /* file_attributes */
1116 oplock_request, /* oplock_request */
1117 open_size, /* allocation_size */
1118 NULL, /* sd */
1119 ea_list, /* ea_list */
1120 &fsp, /* result */
1121 &smb_action); /* psbuf */
1123 if (!NT_STATUS_IS_OK(status)) {
1124 if (open_was_deferred(req->mid)) {
1125 /* We have re-scheduled this call. */
1126 goto out;
1128 reply_openerror(req, status);
1129 goto out;
1132 size = get_file_size_stat(&smb_fname->st);
1133 fattr = dos_mode(conn, smb_fname);
1134 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1135 inode = smb_fname->st.st_ex_ino;
1136 if (fattr & aDIR) {
1137 close_file(req, fsp, ERROR_CLOSE);
1138 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1139 goto out;
1142 /* Realloc the size of parameters and data we will return */
1143 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1144 if(*pparams == NULL ) {
1145 reply_nterror(req, NT_STATUS_NO_MEMORY);
1146 goto out;
1148 params = *pparams;
1150 SSVAL(params,0,fsp->fnum);
1151 SSVAL(params,2,fattr);
1152 srv_put_dos_date2(params,4, mtime);
1153 SIVAL(params,8, (uint32)size);
1154 SSVAL(params,12,deny_mode);
1155 SSVAL(params,14,0); /* open_type - file or directory. */
1156 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1158 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1159 smb_action |= EXTENDED_OPLOCK_GRANTED;
1162 SSVAL(params,18,smb_action);
1165 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1167 SIVAL(params,20,inode);
1168 SSVAL(params,24,0); /* Padding. */
1169 if (flags & 8) {
1170 uint32 ea_size = estimate_ea_size(conn, fsp,
1171 fsp->fsp_name->base_name);
1172 SIVAL(params, 26, ea_size);
1173 } else {
1174 SIVAL(params, 26, 0);
1177 /* Send the required number of replies */
1178 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1179 out:
1180 TALLOC_FREE(smb_fname);
1183 /*********************************************************
1184 Routine to check if a given string matches exactly.
1185 as a special case a mask of "." does NOT match. That
1186 is required for correct wildcard semantics
1187 Case can be significant or not.
1188 **********************************************************/
1190 static bool exact_match(bool has_wild,
1191 bool case_sensitive,
1192 const char *str,
1193 const char *mask)
1195 if (mask[0] == '.' && mask[1] == 0) {
1196 return false;
1199 if (has_wild) {
1200 return false;
1203 if (case_sensitive) {
1204 return strcmp(str,mask)==0;
1205 } else {
1206 return StrCaseCmp(str,mask) == 0;
1210 /****************************************************************************
1211 Return the filetype for UNIX extensions.
1212 ****************************************************************************/
1214 static uint32 unix_filetype(mode_t mode)
1216 if(S_ISREG(mode))
1217 return UNIX_TYPE_FILE;
1218 else if(S_ISDIR(mode))
1219 return UNIX_TYPE_DIR;
1220 #ifdef S_ISLNK
1221 else if(S_ISLNK(mode))
1222 return UNIX_TYPE_SYMLINK;
1223 #endif
1224 #ifdef S_ISCHR
1225 else if(S_ISCHR(mode))
1226 return UNIX_TYPE_CHARDEV;
1227 #endif
1228 #ifdef S_ISBLK
1229 else if(S_ISBLK(mode))
1230 return UNIX_TYPE_BLKDEV;
1231 #endif
1232 #ifdef S_ISFIFO
1233 else if(S_ISFIFO(mode))
1234 return UNIX_TYPE_FIFO;
1235 #endif
1236 #ifdef S_ISSOCK
1237 else if(S_ISSOCK(mode))
1238 return UNIX_TYPE_SOCKET;
1239 #endif
1241 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1242 return UNIX_TYPE_UNKNOWN;
1245 /****************************************************************************
1246 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1247 ****************************************************************************/
1249 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1251 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1252 const SMB_STRUCT_STAT *psbuf,
1253 uint32 perms,
1254 enum perm_type ptype,
1255 mode_t *ret_perms)
1257 mode_t ret = 0;
1259 if (perms == SMB_MODE_NO_CHANGE) {
1260 if (!VALID_STAT(*psbuf)) {
1261 return NT_STATUS_INVALID_PARAMETER;
1262 } else {
1263 *ret_perms = psbuf->st_ex_mode;
1264 return NT_STATUS_OK;
1268 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1269 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1270 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1271 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1272 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1273 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1274 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1275 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1276 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1277 #ifdef S_ISVTX
1278 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1279 #endif
1280 #ifdef S_ISGID
1281 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1282 #endif
1283 #ifdef S_ISUID
1284 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1285 #endif
1287 switch (ptype) {
1288 case PERM_NEW_FILE:
1289 /* Apply mode mask */
1290 ret &= lp_create_mask(SNUM(conn));
1291 /* Add in force bits */
1292 ret |= lp_force_create_mode(SNUM(conn));
1293 break;
1294 case PERM_NEW_DIR:
1295 ret &= lp_dir_mask(SNUM(conn));
1296 /* Add in force bits */
1297 ret |= lp_force_dir_mode(SNUM(conn));
1298 break;
1299 case PERM_EXISTING_FILE:
1300 /* Apply mode mask */
1301 ret &= lp_security_mask(SNUM(conn));
1302 /* Add in force bits */
1303 ret |= lp_force_security_mode(SNUM(conn));
1304 break;
1305 case PERM_EXISTING_DIR:
1306 /* Apply mode mask */
1307 ret &= lp_dir_security_mask(SNUM(conn));
1308 /* Add in force bits */
1309 ret |= lp_force_dir_security_mode(SNUM(conn));
1310 break;
1313 *ret_perms = ret;
1314 return NT_STATUS_OK;
1317 /****************************************************************************
1318 Needed to show the msdfs symlinks as directories. Modifies psbuf
1319 to be a directory if it's a msdfs link.
1320 ****************************************************************************/
1322 static bool check_msdfs_link(connection_struct *conn,
1323 const char *pathname,
1324 SMB_STRUCT_STAT *psbuf)
1326 int saved_errno = errno;
1327 if(lp_host_msdfs() &&
1328 lp_msdfs_root(SNUM(conn)) &&
1329 is_msdfs_link(conn, pathname, psbuf)) {
1331 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1332 "as a directory\n",
1333 pathname));
1334 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1335 errno = saved_errno;
1336 return true;
1338 errno = saved_errno;
1339 return false;
1343 /****************************************************************************
1344 Get a level dependent lanman2 dir entry.
1345 ****************************************************************************/
1347 struct smbd_dirptr_lanman2_state {
1348 connection_struct *conn;
1349 uint32_t info_level;
1350 bool check_mangled_names;
1351 bool has_wild;
1352 bool got_exact_match;
1355 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1356 void *private_data,
1357 const char *dname,
1358 const char *mask,
1359 char **_fname)
1361 struct smbd_dirptr_lanman2_state *state =
1362 (struct smbd_dirptr_lanman2_state *)private_data;
1363 bool ok;
1364 char mangled_name[13]; /* mangled 8.3 name. */
1365 bool got_match;
1366 const char *fname;
1368 /* Mangle fname if it's an illegal name. */
1369 if (mangle_must_mangle(dname, state->conn->params)) {
1370 ok = name_to_8_3(dname, mangled_name,
1371 true, state->conn->params);
1372 if (!ok) {
1373 return false;
1375 fname = mangled_name;
1376 } else {
1377 fname = dname;
1380 got_match = exact_match(state->has_wild,
1381 state->conn->case_sensitive,
1382 fname, mask);
1383 state->got_exact_match = got_match;
1384 if (!got_match) {
1385 got_match = mask_match(fname, mask,
1386 state->conn->case_sensitive);
1389 if(!got_match && state->check_mangled_names &&
1390 !mangle_is_8_3(fname, false, state->conn->params)) {
1392 * It turns out that NT matches wildcards against
1393 * both long *and* short names. This may explain some
1394 * of the wildcard wierdness from old DOS clients
1395 * that some people have been seeing.... JRA.
1397 /* Force the mangling into 8.3. */
1398 ok = name_to_8_3(fname, mangled_name,
1399 false, state->conn->params);
1400 if (!ok) {
1401 return false;
1404 got_match = exact_match(state->has_wild,
1405 state->conn->case_sensitive,
1406 mangled_name, mask);
1407 state->got_exact_match = got_match;
1408 if (!got_match) {
1409 got_match = mask_match(mangled_name, mask,
1410 state->conn->case_sensitive);
1414 if (!got_match) {
1415 return false;
1418 *_fname = talloc_strdup(ctx, fname);
1419 if (*_fname == NULL) {
1420 return false;
1423 return true;
1426 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1427 void *private_data,
1428 struct smb_filename *smb_fname,
1429 uint32_t *_mode)
1431 struct smbd_dirptr_lanman2_state *state =
1432 (struct smbd_dirptr_lanman2_state *)private_data;
1433 bool ms_dfs_link = false;
1434 uint32_t mode = 0;
1436 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1437 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1438 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1439 "Couldn't lstat [%s] (%s)\n",
1440 smb_fname_str_dbg(smb_fname),
1441 strerror(errno)));
1442 return false;
1444 } else if (!VALID_STAT(smb_fname->st) &&
1445 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1446 /* Needed to show the msdfs symlinks as
1447 * directories */
1449 ms_dfs_link = check_msdfs_link(state->conn,
1450 smb_fname->base_name,
1451 &smb_fname->st);
1452 if (!ms_dfs_link) {
1453 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1454 "Couldn't stat [%s] (%s)\n",
1455 smb_fname_str_dbg(smb_fname),
1456 strerror(errno)));
1457 return false;
1461 if (ms_dfs_link) {
1462 mode = dos_mode_msdfs(state->conn, smb_fname);
1463 } else {
1464 mode = dos_mode(state->conn, smb_fname);
1467 *_mode = mode;
1468 return true;
1471 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1472 connection_struct *conn,
1473 uint16_t flags2,
1474 uint32_t info_level,
1475 struct ea_list *name_list,
1476 bool check_mangled_names,
1477 bool requires_resume_key,
1478 uint32_t mode,
1479 const char *fname,
1480 const struct smb_filename *smb_fname,
1481 uint64_t space_remaining,
1482 uint8_t align,
1483 bool do_pad,
1484 char *base_data,
1485 char **ppdata,
1486 char *end_data,
1487 bool *out_of_space,
1488 uint64_t *last_entry_off)
1490 char *p, *q, *pdata = *ppdata;
1491 uint32_t reskey=0;
1492 uint64_t file_size = 0;
1493 uint64_t allocation_size = 0;
1494 uint64_t file_index = 0;
1495 uint32_t len;
1496 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1497 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1498 time_t c_date = (time_t)0;
1499 char *nameptr;
1500 char *last_entry_ptr;
1501 bool was_8_3;
1502 off_t off;
1503 off_t pad = 0;
1505 *out_of_space = false;
1507 ZERO_STRUCT(mdate_ts);
1508 ZERO_STRUCT(adate_ts);
1509 ZERO_STRUCT(create_date_ts);
1510 ZERO_STRUCT(cdate_ts);
1512 if (!(mode & aDIR)) {
1513 file_size = get_file_size_stat(&smb_fname->st);
1515 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1517 file_index = get_FileIndex(conn, &smb_fname->st);
1519 mdate_ts = smb_fname->st.st_ex_mtime;
1520 adate_ts = smb_fname->st.st_ex_atime;
1521 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1522 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1524 if (lp_dos_filetime_resolution(SNUM(conn))) {
1525 dos_filetime_timespec(&create_date_ts);
1526 dos_filetime_timespec(&mdate_ts);
1527 dos_filetime_timespec(&adate_ts);
1528 dos_filetime_timespec(&cdate_ts);
1531 create_date = convert_timespec_to_time_t(create_date_ts);
1532 mdate = convert_timespec_to_time_t(mdate_ts);
1533 adate = convert_timespec_to_time_t(adate_ts);
1534 c_date = convert_timespec_to_time_t(cdate_ts);
1536 /* align the record */
1537 off = PTR_DIFF(pdata, base_data);
1538 pad = (off + (align-1)) & ~(align-1);
1539 pad -= off;
1540 off += pad;
1541 /* initialize padding to 0 */
1542 if (pad) {
1543 memset(pdata, 0, pad);
1545 space_remaining -= pad;
1547 pdata += pad;
1548 p = pdata;
1549 last_entry_ptr = p;
1551 pad = 0;
1552 off = 0;
1554 switch (info_level) {
1555 case SMB_FIND_INFO_STANDARD:
1556 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1557 if(requires_resume_key) {
1558 SIVAL(p,0,reskey);
1559 p += 4;
1561 srv_put_dos_date2(p,0,create_date);
1562 srv_put_dos_date2(p,4,adate);
1563 srv_put_dos_date2(p,8,mdate);
1564 SIVAL(p,12,(uint32)file_size);
1565 SIVAL(p,16,(uint32)allocation_size);
1566 SSVAL(p,20,mode);
1567 p += 23;
1568 nameptr = p;
1569 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1570 p += ucs2_align(base_data, p, 0);
1572 len = srvstr_push(base_data, flags2, p,
1573 fname, PTR_DIFF(end_data, p),
1574 STR_TERMINATE);
1575 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1576 if (len > 2) {
1577 SCVAL(nameptr, -1, len - 2);
1578 } else {
1579 SCVAL(nameptr, -1, 0);
1581 } else {
1582 if (len > 1) {
1583 SCVAL(nameptr, -1, len - 1);
1584 } else {
1585 SCVAL(nameptr, -1, 0);
1588 p += len;
1589 break;
1591 case SMB_FIND_EA_SIZE:
1592 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1593 if (requires_resume_key) {
1594 SIVAL(p,0,reskey);
1595 p += 4;
1597 srv_put_dos_date2(p,0,create_date);
1598 srv_put_dos_date2(p,4,adate);
1599 srv_put_dos_date2(p,8,mdate);
1600 SIVAL(p,12,(uint32)file_size);
1601 SIVAL(p,16,(uint32)allocation_size);
1602 SSVAL(p,20,mode);
1604 unsigned int ea_size = estimate_ea_size(conn, NULL,
1605 smb_fname->base_name);
1606 SIVAL(p,22,ea_size); /* Extended attributes */
1608 p += 27;
1609 nameptr = p - 1;
1610 len = srvstr_push(base_data, flags2,
1611 p, fname, PTR_DIFF(end_data, p),
1612 STR_TERMINATE | STR_NOALIGN);
1613 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1614 if (len > 2) {
1615 len -= 2;
1616 } else {
1617 len = 0;
1619 } else {
1620 if (len > 1) {
1621 len -= 1;
1622 } else {
1623 len = 0;
1626 SCVAL(nameptr,0,len);
1627 p += len;
1628 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1629 break;
1631 case SMB_FIND_EA_LIST:
1633 struct ea_list *file_list = NULL;
1634 size_t ea_len = 0;
1636 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1637 if (!name_list) {
1638 return false;
1640 if (requires_resume_key) {
1641 SIVAL(p,0,reskey);
1642 p += 4;
1644 srv_put_dos_date2(p,0,create_date);
1645 srv_put_dos_date2(p,4,adate);
1646 srv_put_dos_date2(p,8,mdate);
1647 SIVAL(p,12,(uint32)file_size);
1648 SIVAL(p,16,(uint32)allocation_size);
1649 SSVAL(p,20,mode);
1650 p += 22; /* p now points to the EA area. */
1652 file_list = get_ea_list_from_file(ctx, conn, NULL,
1653 smb_fname->base_name,
1654 &ea_len);
1655 name_list = ea_list_union(name_list, file_list, &ea_len);
1657 /* We need to determine if this entry will fit in the space available. */
1658 /* Max string size is 255 bytes. */
1659 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1660 *out_of_space = true;
1661 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1662 return False; /* Not finished - just out of space */
1665 /* Push the ea_data followed by the name. */
1666 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1667 nameptr = p;
1668 len = srvstr_push(base_data, flags2,
1669 p + 1, fname, PTR_DIFF(end_data, p+1),
1670 STR_TERMINATE | STR_NOALIGN);
1671 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1672 if (len > 2) {
1673 len -= 2;
1674 } else {
1675 len = 0;
1677 } else {
1678 if (len > 1) {
1679 len -= 1;
1680 } else {
1681 len = 0;
1684 SCVAL(nameptr,0,len);
1685 p += len + 1;
1686 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1687 break;
1690 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1691 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1692 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1693 p += 4;
1694 SIVAL(p,0,reskey); p += 4;
1695 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1696 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1697 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1698 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1699 SOFF_T(p,0,file_size); p += 8;
1700 SOFF_T(p,0,allocation_size); p += 8;
1701 SIVAL(p,0,mode); p += 4;
1702 q = p; p += 4; /* q is placeholder for name length. */
1704 unsigned int ea_size = estimate_ea_size(conn, NULL,
1705 smb_fname->base_name);
1706 SIVAL(p,0,ea_size); /* Extended attributes */
1707 p += 4;
1709 /* Clear the short name buffer. This is
1710 * IMPORTANT as not doing so will trigger
1711 * a Win2k client bug. JRA.
1713 if (!was_8_3 && check_mangled_names) {
1714 char mangled_name[13]; /* mangled 8.3 name. */
1715 if (!name_to_8_3(fname,mangled_name,True,
1716 conn->params)) {
1717 /* Error - mangle failed ! */
1718 memset(mangled_name,'\0',12);
1720 mangled_name[12] = 0;
1721 len = srvstr_push(base_data, flags2,
1722 p+2, mangled_name, 24,
1723 STR_UPPER|STR_UNICODE);
1724 if (len < 24) {
1725 memset(p + 2 + len,'\0',24 - len);
1727 SSVAL(p, 0, len);
1728 } else {
1729 memset(p,'\0',26);
1731 p += 2 + 24;
1732 len = srvstr_push(base_data, flags2, p,
1733 fname, PTR_DIFF(end_data, p),
1734 STR_TERMINATE_ASCII);
1735 SIVAL(q,0,len);
1736 p += len;
1738 len = PTR_DIFF(p, pdata);
1739 pad = (len + (align-1)) & ~(align-1);
1741 * offset to the next entry, the caller
1742 * will overwrite it for the last entry
1743 * that's why we always include the padding
1745 SIVAL(pdata,0,pad);
1747 * set padding to zero
1749 if (do_pad) {
1750 memset(p, 0, pad - len);
1751 p = pdata + pad;
1752 } else {
1753 p = pdata + len;
1755 break;
1757 case SMB_FIND_FILE_DIRECTORY_INFO:
1758 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1759 p += 4;
1760 SIVAL(p,0,reskey); p += 4;
1761 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1762 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1763 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1764 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1765 SOFF_T(p,0,file_size); p += 8;
1766 SOFF_T(p,0,allocation_size); p += 8;
1767 SIVAL(p,0,mode); p += 4;
1768 len = srvstr_push(base_data, flags2,
1769 p + 4, fname, PTR_DIFF(end_data, p+4),
1770 STR_TERMINATE_ASCII);
1771 SIVAL(p,0,len);
1772 p += 4 + len;
1774 len = PTR_DIFF(p, pdata);
1775 pad = (len + (align-1)) & ~(align-1);
1777 * offset to the next entry, the caller
1778 * will overwrite it for the last entry
1779 * that's why we always include the padding
1781 SIVAL(pdata,0,pad);
1783 * set padding to zero
1785 if (do_pad) {
1786 memset(p, 0, pad - len);
1787 p = pdata + pad;
1788 } else {
1789 p = pdata + len;
1791 break;
1793 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1794 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1795 p += 4;
1796 SIVAL(p,0,reskey); p += 4;
1797 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1798 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1799 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1800 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1801 SOFF_T(p,0,file_size); p += 8;
1802 SOFF_T(p,0,allocation_size); p += 8;
1803 SIVAL(p,0,mode); p += 4;
1804 q = p; p += 4; /* q is placeholder for name length. */
1806 unsigned int ea_size = estimate_ea_size(conn, NULL,
1807 smb_fname->base_name);
1808 SIVAL(p,0,ea_size); /* Extended attributes */
1809 p +=4;
1811 len = srvstr_push(base_data, flags2, p,
1812 fname, PTR_DIFF(end_data, p),
1813 STR_TERMINATE_ASCII);
1814 SIVAL(q, 0, len);
1815 p += len;
1817 len = PTR_DIFF(p, pdata);
1818 pad = (len + (align-1)) & ~(align-1);
1820 * offset to the next entry, the caller
1821 * will overwrite it for the last entry
1822 * that's why we always include the padding
1824 SIVAL(pdata,0,pad);
1826 * set padding to zero
1828 if (do_pad) {
1829 memset(p, 0, pad - len);
1830 p = pdata + pad;
1831 } else {
1832 p = pdata + len;
1834 break;
1836 case SMB_FIND_FILE_NAMES_INFO:
1837 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1838 p += 4;
1839 SIVAL(p,0,reskey); p += 4;
1840 p += 4;
1841 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1842 acl on a dir (tridge) */
1843 len = srvstr_push(base_data, flags2, p,
1844 fname, PTR_DIFF(end_data, p),
1845 STR_TERMINATE_ASCII);
1846 SIVAL(p, -4, len);
1847 p += len;
1849 len = PTR_DIFF(p, pdata);
1850 pad = (len + (align-1)) & ~(align-1);
1852 * offset to the next entry, the caller
1853 * will overwrite it for the last entry
1854 * that's why we always include the padding
1856 SIVAL(pdata,0,pad);
1858 * set padding to zero
1860 if (do_pad) {
1861 memset(p, 0, pad - len);
1862 p = pdata + pad;
1863 } else {
1864 p = pdata + len;
1866 break;
1868 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1869 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1870 p += 4;
1871 SIVAL(p,0,reskey); p += 4;
1872 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1873 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1874 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1875 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1876 SOFF_T(p,0,file_size); p += 8;
1877 SOFF_T(p,0,allocation_size); p += 8;
1878 SIVAL(p,0,mode); p += 4;
1879 q = p; p += 4; /* q is placeholder for name length. */
1881 unsigned int ea_size = estimate_ea_size(conn, NULL,
1882 smb_fname->base_name);
1883 SIVAL(p,0,ea_size); /* Extended attributes */
1884 p +=4;
1886 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1887 SBVAL(p,0,file_index); p += 8;
1888 len = srvstr_push(base_data, flags2, p,
1889 fname, PTR_DIFF(end_data, p),
1890 STR_TERMINATE_ASCII);
1891 SIVAL(q, 0, len);
1892 p += len;
1894 len = PTR_DIFF(p, pdata);
1895 pad = (len + (align-1)) & ~(align-1);
1897 * offset to the next entry, the caller
1898 * will overwrite it for the last entry
1899 * that's why we always include the padding
1901 SIVAL(pdata,0,pad);
1903 * set padding to zero
1905 if (do_pad) {
1906 memset(p, 0, pad - len);
1907 p = pdata + pad;
1908 } else {
1909 p = pdata + len;
1911 break;
1913 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1914 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1915 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1916 p += 4;
1917 SIVAL(p,0,reskey); p += 4;
1918 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1919 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1920 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1921 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1922 SOFF_T(p,0,file_size); p += 8;
1923 SOFF_T(p,0,allocation_size); p += 8;
1924 SIVAL(p,0,mode); p += 4;
1925 q = p; p += 4; /* q is placeholder for name length */
1927 unsigned int ea_size = estimate_ea_size(conn, NULL,
1928 smb_fname->base_name);
1929 SIVAL(p,0,ea_size); /* Extended attributes */
1930 p +=4;
1932 /* Clear the short name buffer. This is
1933 * IMPORTANT as not doing so will trigger
1934 * a Win2k client bug. JRA.
1936 if (!was_8_3 && check_mangled_names) {
1937 char mangled_name[13]; /* mangled 8.3 name. */
1938 if (!name_to_8_3(fname,mangled_name,True,
1939 conn->params)) {
1940 /* Error - mangle failed ! */
1941 memset(mangled_name,'\0',12);
1943 mangled_name[12] = 0;
1944 len = srvstr_push(base_data, flags2,
1945 p+2, mangled_name, 24,
1946 STR_UPPER|STR_UNICODE);
1947 SSVAL(p, 0, len);
1948 if (len < 24) {
1949 memset(p + 2 + len,'\0',24 - len);
1951 SSVAL(p, 0, len);
1952 } else {
1953 memset(p,'\0',26);
1955 p += 26;
1956 SSVAL(p,0,0); p += 2; /* Reserved ? */
1957 SBVAL(p,0,file_index); p += 8;
1958 len = srvstr_push(base_data, flags2, p,
1959 fname, PTR_DIFF(end_data, p),
1960 STR_TERMINATE_ASCII);
1961 SIVAL(q,0,len);
1962 p += len;
1964 len = PTR_DIFF(p, pdata);
1965 pad = (len + (align-1)) & ~(align-1);
1967 * offset to the next entry, the caller
1968 * will overwrite it for the last entry
1969 * that's why we always include the padding
1971 SIVAL(pdata,0,pad);
1973 * set padding to zero
1975 if (do_pad) {
1976 memset(p, 0, pad - len);
1977 p = pdata + pad;
1978 } else {
1979 p = pdata + len;
1981 break;
1983 /* CIFS UNIX Extension. */
1985 case SMB_FIND_FILE_UNIX:
1986 case SMB_FIND_FILE_UNIX_INFO2:
1987 p+= 4;
1988 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1990 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1992 if (info_level == SMB_FIND_FILE_UNIX) {
1993 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1994 p = store_file_unix_basic(conn, p,
1995 NULL, &smb_fname->st);
1996 len = srvstr_push(base_data, flags2, p,
1997 fname, PTR_DIFF(end_data, p),
1998 STR_TERMINATE);
1999 } else {
2000 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2001 p = store_file_unix_basic_info2(conn, p,
2002 NULL, &smb_fname->st);
2003 nameptr = p;
2004 p += 4;
2005 len = srvstr_push(base_data, flags2, p, fname,
2006 PTR_DIFF(end_data, p), 0);
2007 SIVAL(nameptr, 0, len);
2010 p += len;
2012 len = PTR_DIFF(p, pdata);
2013 pad = (len + (align-1)) & ~(align-1);
2015 * offset to the next entry, the caller
2016 * will overwrite it for the last entry
2017 * that's why we always include the padding
2019 SIVAL(pdata,0,pad);
2021 * set padding to zero
2023 if (do_pad) {
2024 memset(p, 0, pad - len);
2025 p = pdata + pad;
2026 } else {
2027 p = pdata + len;
2029 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2031 break;
2033 default:
2034 return false;
2037 if (PTR_DIFF(p,pdata) > space_remaining) {
2038 *out_of_space = true;
2039 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2040 return false; /* Not finished - just out of space */
2043 /* Setup the last entry pointer, as an offset from base_data */
2044 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2045 /* Advance the data pointer to the next slot */
2046 *ppdata = p;
2048 return true;
2051 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2052 connection_struct *conn,
2053 struct dptr_struct *dirptr,
2054 uint16 flags2,
2055 const char *path_mask,
2056 uint32 dirtype,
2057 int info_level,
2058 int requires_resume_key,
2059 bool dont_descend,
2060 bool ask_sharemode,
2061 uint8_t align,
2062 bool do_pad,
2063 char **ppdata,
2064 char *base_data,
2065 char *end_data,
2066 int space_remaining,
2067 bool *out_of_space,
2068 bool *got_exact_match,
2069 int *_last_entry_off,
2070 struct ea_list *name_list)
2072 const char *p;
2073 const char *mask = NULL;
2074 long prev_dirpos = 0;
2075 uint32_t mode = 0;
2076 char *fname = NULL;
2077 struct smb_filename *smb_fname = NULL;
2078 struct smbd_dirptr_lanman2_state state;
2079 bool ok;
2080 uint64_t last_entry_off = 0;
2082 ZERO_STRUCT(state);
2083 state.conn = conn;
2084 state.info_level = info_level;
2085 state.check_mangled_names = lp_manglednames(conn->params);
2086 state.has_wild = dptr_has_wild(dirptr);
2087 state.got_exact_match = false;
2089 *out_of_space = false;
2090 *got_exact_match = false;
2092 p = strrchr_m(path_mask,'/');
2093 if(p != NULL) {
2094 if(p[1] == '\0') {
2095 mask = "*.*";
2096 } else {
2097 mask = p+1;
2099 } else {
2100 mask = path_mask;
2103 ok = smbd_dirptr_get_entry(ctx,
2104 dirptr,
2105 mask,
2106 dirtype,
2107 dont_descend,
2108 ask_sharemode,
2109 smbd_dirptr_lanman2_match_fn,
2110 smbd_dirptr_lanman2_mode_fn,
2111 &state,
2112 &fname,
2113 &smb_fname,
2114 &mode,
2115 &prev_dirpos);
2116 if (!ok) {
2117 return false;
2120 *got_exact_match = state.got_exact_match;
2122 ok = smbd_marshall_dir_entry(ctx,
2123 conn,
2124 flags2,
2125 info_level,
2126 name_list,
2127 state.check_mangled_names,
2128 requires_resume_key,
2129 mode,
2130 fname,
2131 smb_fname,
2132 space_remaining,
2133 align,
2134 do_pad,
2135 base_data,
2136 ppdata,
2137 end_data,
2138 out_of_space,
2139 &last_entry_off);
2140 TALLOC_FREE(fname);
2141 TALLOC_FREE(smb_fname);
2142 if (*out_of_space) {
2143 dptr_SeekDir(dirptr, prev_dirpos);
2144 return false;
2146 if (!ok) {
2147 return false;
2150 *_last_entry_off = last_entry_off;
2151 return true;
2154 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2155 connection_struct *conn,
2156 struct dptr_struct *dirptr,
2157 uint16 flags2,
2158 const char *path_mask,
2159 uint32 dirtype,
2160 int info_level,
2161 bool requires_resume_key,
2162 bool dont_descend,
2163 bool ask_sharemode,
2164 char **ppdata,
2165 char *base_data,
2166 char *end_data,
2167 int space_remaining,
2168 bool *out_of_space,
2169 bool *got_exact_match,
2170 int *last_entry_off,
2171 struct ea_list *name_list)
2173 uint8_t align = 4;
2174 const bool do_pad = true;
2176 if (info_level >= 1 && info_level <= 3) {
2177 /* No alignment on earlier info levels. */
2178 align = 1;
2181 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2182 path_mask, dirtype, info_level,
2183 requires_resume_key, dont_descend, ask_sharemode,
2184 align, do_pad,
2185 ppdata, base_data, end_data,
2186 space_remaining,
2187 out_of_space, got_exact_match,
2188 last_entry_off, name_list);
2191 /****************************************************************************
2192 Reply to a TRANS2_FINDFIRST.
2193 ****************************************************************************/
2195 static void call_trans2findfirst(connection_struct *conn,
2196 struct smb_request *req,
2197 char **pparams, int total_params,
2198 char **ppdata, int total_data,
2199 unsigned int max_data_bytes)
2201 /* We must be careful here that we don't return more than the
2202 allowed number of data bytes. If this means returning fewer than
2203 maxentries then so be it. We assume that the redirector has
2204 enough room for the fixed number of parameter bytes it has
2205 requested. */
2206 struct smb_filename *smb_dname = NULL;
2207 char *params = *pparams;
2208 char *pdata = *ppdata;
2209 char *data_end;
2210 uint32 dirtype;
2211 int maxentries;
2212 uint16 findfirst_flags;
2213 bool close_after_first;
2214 bool close_if_end;
2215 bool requires_resume_key;
2216 int info_level;
2217 char *directory = NULL;
2218 char *mask = NULL;
2219 char *p;
2220 int last_entry_off=0;
2221 int dptr_num = -1;
2222 int numentries = 0;
2223 int i;
2224 bool finished = False;
2225 bool dont_descend = False;
2226 bool out_of_space = False;
2227 int space_remaining;
2228 bool mask_contains_wcard = False;
2229 struct ea_list *ea_list = NULL;
2230 NTSTATUS ntstatus = NT_STATUS_OK;
2231 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2232 TALLOC_CTX *ctx = talloc_tos();
2233 struct dptr_struct *dirptr = NULL;
2234 struct smbd_server_connection *sconn = smbd_server_conn;
2236 if (total_params < 13) {
2237 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2238 goto out;
2241 dirtype = SVAL(params,0);
2242 maxentries = SVAL(params,2);
2243 findfirst_flags = SVAL(params,4);
2244 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2245 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2246 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2247 info_level = SVAL(params,6);
2249 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2250 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2251 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2252 info_level, max_data_bytes));
2254 if (!maxentries) {
2255 /* W2K3 seems to treat zero as 1. */
2256 maxentries = 1;
2259 switch (info_level) {
2260 case SMB_FIND_INFO_STANDARD:
2261 case SMB_FIND_EA_SIZE:
2262 case SMB_FIND_EA_LIST:
2263 case SMB_FIND_FILE_DIRECTORY_INFO:
2264 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2265 case SMB_FIND_FILE_NAMES_INFO:
2266 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2267 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2268 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2269 break;
2270 case SMB_FIND_FILE_UNIX:
2271 case SMB_FIND_FILE_UNIX_INFO2:
2272 /* Always use filesystem for UNIX mtime query. */
2273 ask_sharemode = false;
2274 if (!lp_unix_extensions()) {
2275 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2276 goto out;
2278 break;
2279 default:
2280 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2281 goto out;
2284 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2285 params+12, total_params - 12,
2286 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2287 if (!NT_STATUS_IS_OK(ntstatus)) {
2288 reply_nterror(req, ntstatus);
2289 goto out;
2292 ntstatus = filename_convert(ctx, conn,
2293 req->flags2 & FLAGS2_DFS_PATHNAMES,
2294 directory,
2295 (UCF_SAVE_LCOMP |
2296 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2297 &mask_contains_wcard,
2298 &smb_dname);
2299 if (!NT_STATUS_IS_OK(ntstatus)) {
2300 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2301 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2302 ERRSRV, ERRbadpath);
2303 goto out;
2305 reply_nterror(req, ntstatus);
2306 goto out;
2309 mask = smb_dname->original_lcomp;
2311 directory = smb_dname->base_name;
2313 p = strrchr_m(directory,'/');
2314 if(p == NULL) {
2315 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2316 if((directory[0] == '.') && (directory[1] == '\0')) {
2317 mask = talloc_strdup(ctx,"*");
2318 if (!mask) {
2319 reply_nterror(req, NT_STATUS_NO_MEMORY);
2320 goto out;
2322 mask_contains_wcard = True;
2324 directory = talloc_strdup(talloc_tos(), "./");
2325 if (!directory) {
2326 reply_nterror(req, NT_STATUS_NO_MEMORY);
2327 goto out;
2329 } else {
2330 *p = 0;
2333 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2335 if (info_level == SMB_FIND_EA_LIST) {
2336 uint32 ea_size;
2338 if (total_data < 4) {
2339 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2340 goto out;
2343 ea_size = IVAL(pdata,0);
2344 if (ea_size != total_data) {
2345 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2346 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2347 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2348 goto out;
2351 if (!lp_ea_support(SNUM(conn))) {
2352 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2353 goto out;
2356 /* Pull out the list of names. */
2357 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2358 if (!ea_list) {
2359 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2360 goto out;
2364 *ppdata = (char *)SMB_REALLOC(
2365 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2366 if(*ppdata == NULL ) {
2367 reply_nterror(req, NT_STATUS_NO_MEMORY);
2368 goto out;
2370 pdata = *ppdata;
2371 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2373 /* Realloc the params space */
2374 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2375 if (*pparams == NULL) {
2376 reply_nterror(req, NT_STATUS_NO_MEMORY);
2377 goto out;
2379 params = *pparams;
2381 /* Save the wildcard match and attribs we are using on this directory -
2382 needed as lanman2 assumes these are being saved between calls */
2384 ntstatus = dptr_create(conn,
2385 directory,
2386 False,
2387 True,
2388 req->smbpid,
2389 mask,
2390 mask_contains_wcard,
2391 dirtype,
2392 &dirptr);
2394 if (!NT_STATUS_IS_OK(ntstatus)) {
2395 reply_nterror(req, ntstatus);
2396 goto out;
2399 dptr_num = dptr_dnum(dirptr);
2400 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2402 /* Initialize per TRANS2_FIND_FIRST operation data */
2403 dptr_init_search_op(dirptr);
2405 /* We don't need to check for VOL here as this is returned by
2406 a different TRANS2 call. */
2408 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2409 directory,lp_dontdescend(SNUM(conn))));
2410 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2411 dont_descend = True;
2413 p = pdata;
2414 space_remaining = max_data_bytes;
2415 out_of_space = False;
2417 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2418 bool got_exact_match = False;
2420 /* this is a heuristic to avoid seeking the dirptr except when
2421 absolutely necessary. It allows for a filename of about 40 chars */
2422 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2423 out_of_space = True;
2424 finished = False;
2425 } else {
2426 finished = !get_lanman2_dir_entry(ctx,
2427 conn,
2428 dirptr,
2429 req->flags2,
2430 mask,dirtype,info_level,
2431 requires_resume_key,dont_descend,
2432 ask_sharemode,
2433 &p,pdata,data_end,
2434 space_remaining, &out_of_space,
2435 &got_exact_match,
2436 &last_entry_off, ea_list);
2439 if (finished && out_of_space)
2440 finished = False;
2442 if (!finished && !out_of_space)
2443 numentries++;
2446 * As an optimisation if we know we aren't looking
2447 * for a wildcard name (ie. the name matches the wildcard exactly)
2448 * then we can finish on any (first) match.
2449 * This speeds up large directory searches. JRA.
2452 if(got_exact_match)
2453 finished = True;
2455 /* Ensure space_remaining never goes -ve. */
2456 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2457 space_remaining = 0;
2458 out_of_space = true;
2459 } else {
2460 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2464 /* Check if we can close the dirptr */
2465 if(close_after_first || (finished && close_if_end)) {
2466 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2467 dptr_close(sconn, &dptr_num);
2471 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2472 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2473 * the protocol level is less than NT1. Tested with smbclient. JRA.
2474 * This should fix the OS/2 client bug #2335.
2477 if(numentries == 0) {
2478 dptr_close(sconn, &dptr_num);
2479 if (get_Protocol() < PROTOCOL_NT1) {
2480 reply_force_doserror(req, ERRDOS, ERRnofiles);
2481 goto out;
2482 } else {
2483 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2484 ERRDOS, ERRbadfile);
2485 goto out;
2489 /* At this point pdata points to numentries directory entries. */
2491 /* Set up the return parameter block */
2492 SSVAL(params,0,dptr_num);
2493 SSVAL(params,2,numentries);
2494 SSVAL(params,4,finished);
2495 SSVAL(params,6,0); /* Never an EA error */
2496 SSVAL(params,8,last_entry_off);
2498 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2499 max_data_bytes);
2501 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2502 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2503 if (!directory) {
2504 reply_nterror(req, NT_STATUS_NO_MEMORY);
2508 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2509 smb_fn_name(req->cmd),
2510 mask, directory, dirtype, numentries ) );
2513 * Force a name mangle here to ensure that the
2514 * mask as an 8.3 name is top of the mangled cache.
2515 * The reasons for this are subtle. Don't remove
2516 * this code unless you know what you are doing
2517 * (see PR#13758). JRA.
2520 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2521 char mangled_name[13];
2522 name_to_8_3(mask, mangled_name, True, conn->params);
2524 out:
2525 TALLOC_FREE(smb_dname);
2526 return;
2529 /****************************************************************************
2530 Reply to a TRANS2_FINDNEXT.
2531 ****************************************************************************/
2533 static void call_trans2findnext(connection_struct *conn,
2534 struct smb_request *req,
2535 char **pparams, int total_params,
2536 char **ppdata, int total_data,
2537 unsigned int max_data_bytes)
2539 /* We must be careful here that we don't return more than the
2540 allowed number of data bytes. If this means returning fewer than
2541 maxentries then so be it. We assume that the redirector has
2542 enough room for the fixed number of parameter bytes it has
2543 requested. */
2544 char *params = *pparams;
2545 char *pdata = *ppdata;
2546 char *data_end;
2547 int dptr_num;
2548 int maxentries;
2549 uint16 info_level;
2550 uint32 resume_key;
2551 uint16 findnext_flags;
2552 bool close_after_request;
2553 bool close_if_end;
2554 bool requires_resume_key;
2555 bool continue_bit;
2556 bool mask_contains_wcard = False;
2557 char *resume_name = NULL;
2558 const char *mask = NULL;
2559 const char *directory = NULL;
2560 char *p = NULL;
2561 uint16 dirtype;
2562 int numentries = 0;
2563 int i, last_entry_off=0;
2564 bool finished = False;
2565 bool dont_descend = False;
2566 bool out_of_space = False;
2567 int space_remaining;
2568 struct ea_list *ea_list = NULL;
2569 NTSTATUS ntstatus = NT_STATUS_OK;
2570 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2571 TALLOC_CTX *ctx = talloc_tos();
2572 struct dptr_struct *dirptr;
2573 struct smbd_server_connection *sconn = smbd_server_conn;
2575 if (total_params < 13) {
2576 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2577 return;
2580 dptr_num = SVAL(params,0);
2581 maxentries = SVAL(params,2);
2582 info_level = SVAL(params,4);
2583 resume_key = IVAL(params,6);
2584 findnext_flags = SVAL(params,10);
2585 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2586 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2587 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2588 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2590 if (!continue_bit) {
2591 /* We only need resume_name if continue_bit is zero. */
2592 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2593 params+12,
2594 total_params - 12, STR_TERMINATE, &ntstatus,
2595 &mask_contains_wcard);
2596 if (!NT_STATUS_IS_OK(ntstatus)) {
2597 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2598 complain (it thinks we're asking for the directory above the shared
2599 path or an invalid name). Catch this as the resume name is only compared, never used in
2600 a file access. JRA. */
2601 srvstr_pull_talloc(ctx, params, req->flags2,
2602 &resume_name, params+12,
2603 total_params - 12,
2604 STR_TERMINATE);
2606 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2607 reply_nterror(req, ntstatus);
2608 return;
2613 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2614 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2615 resume_key = %d resume name = %s continue=%d level = %d\n",
2616 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2617 requires_resume_key, resume_key,
2618 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2620 if (!maxentries) {
2621 /* W2K3 seems to treat zero as 1. */
2622 maxentries = 1;
2625 switch (info_level) {
2626 case SMB_FIND_INFO_STANDARD:
2627 case SMB_FIND_EA_SIZE:
2628 case SMB_FIND_EA_LIST:
2629 case SMB_FIND_FILE_DIRECTORY_INFO:
2630 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2631 case SMB_FIND_FILE_NAMES_INFO:
2632 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2633 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2634 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2635 break;
2636 case SMB_FIND_FILE_UNIX:
2637 case SMB_FIND_FILE_UNIX_INFO2:
2638 /* Always use filesystem for UNIX mtime query. */
2639 ask_sharemode = false;
2640 if (!lp_unix_extensions()) {
2641 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2642 return;
2644 break;
2645 default:
2646 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2647 return;
2650 if (info_level == SMB_FIND_EA_LIST) {
2651 uint32 ea_size;
2653 if (total_data < 4) {
2654 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2655 return;
2658 ea_size = IVAL(pdata,0);
2659 if (ea_size != total_data) {
2660 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2661 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2662 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2663 return;
2666 if (!lp_ea_support(SNUM(conn))) {
2667 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2668 return;
2671 /* Pull out the list of names. */
2672 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2673 if (!ea_list) {
2674 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2675 return;
2679 *ppdata = (char *)SMB_REALLOC(
2680 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2681 if(*ppdata == NULL) {
2682 reply_nterror(req, NT_STATUS_NO_MEMORY);
2683 return;
2686 pdata = *ppdata;
2687 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2689 /* Realloc the params space */
2690 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2691 if(*pparams == NULL ) {
2692 reply_nterror(req, NT_STATUS_NO_MEMORY);
2693 return;
2696 params = *pparams;
2698 /* Check that the dptr is valid */
2699 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2700 reply_nterror(req, STATUS_NO_MORE_FILES);
2701 return;
2704 directory = dptr_path(sconn, dptr_num);
2706 /* Get the wildcard mask from the dptr */
2707 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2708 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2709 reply_nterror(req, STATUS_NO_MORE_FILES);
2710 return;
2713 mask = p;
2715 /* Get the attr mask from the dptr */
2716 dirtype = dptr_attr(sconn, dptr_num);
2718 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2719 dptr_num, mask, dirtype,
2720 (long)dirptr,
2721 dptr_TellDir(dirptr)));
2723 /* Initialize per TRANS2_FIND_NEXT operation data */
2724 dptr_init_search_op(dirptr);
2726 /* We don't need to check for VOL here as this is returned by
2727 a different TRANS2 call. */
2729 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2730 directory,lp_dontdescend(SNUM(conn))));
2731 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2732 dont_descend = True;
2734 p = pdata;
2735 space_remaining = max_data_bytes;
2736 out_of_space = False;
2739 * Seek to the correct position. We no longer use the resume key but
2740 * depend on the last file name instead.
2743 if(!continue_bit && resume_name && *resume_name) {
2744 SMB_STRUCT_STAT st;
2746 long current_pos = 0;
2748 * Remember, name_to_8_3 is called by
2749 * get_lanman2_dir_entry(), so the resume name
2750 * could be mangled. Ensure we check the unmangled name.
2753 if (mangle_is_mangled(resume_name, conn->params)) {
2754 char *new_resume_name = NULL;
2755 mangle_lookup_name_from_8_3(ctx,
2756 resume_name,
2757 &new_resume_name,
2758 conn->params);
2759 if (new_resume_name) {
2760 resume_name = new_resume_name;
2765 * Fix for NT redirector problem triggered by resume key indexes
2766 * changing between directory scans. We now return a resume key of 0
2767 * and instead look for the filename to continue from (also given
2768 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2769 * findfirst/findnext (as is usual) then the directory pointer
2770 * should already be at the correct place.
2773 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2774 } /* end if resume_name && !continue_bit */
2776 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2777 bool got_exact_match = False;
2779 /* this is a heuristic to avoid seeking the dirptr except when
2780 absolutely necessary. It allows for a filename of about 40 chars */
2781 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2782 out_of_space = True;
2783 finished = False;
2784 } else {
2785 finished = !get_lanman2_dir_entry(ctx,
2786 conn,
2787 dirptr,
2788 req->flags2,
2789 mask,dirtype,info_level,
2790 requires_resume_key,dont_descend,
2791 ask_sharemode,
2792 &p,pdata,data_end,
2793 space_remaining, &out_of_space,
2794 &got_exact_match,
2795 &last_entry_off, ea_list);
2798 if (finished && out_of_space)
2799 finished = False;
2801 if (!finished && !out_of_space)
2802 numentries++;
2805 * As an optimisation if we know we aren't looking
2806 * for a wildcard name (ie. the name matches the wildcard exactly)
2807 * then we can finish on any (first) match.
2808 * This speeds up large directory searches. JRA.
2811 if(got_exact_match)
2812 finished = True;
2814 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2817 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2818 smb_fn_name(req->cmd),
2819 mask, directory, dirtype, numentries ) );
2821 /* Check if we can close the dirptr */
2822 if(close_after_request || (finished && close_if_end)) {
2823 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2824 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2827 /* Set up the return parameter block */
2828 SSVAL(params,0,numentries);
2829 SSVAL(params,2,finished);
2830 SSVAL(params,4,0); /* Never an EA error */
2831 SSVAL(params,6,last_entry_off);
2833 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2834 max_data_bytes);
2836 return;
2839 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2841 E_md4hash(lp_servicename(SNUM(conn)),objid);
2842 return objid;
2845 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2847 SMB_ASSERT(extended_info != NULL);
2849 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2850 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2851 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2852 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2853 #ifdef SAMBA_VERSION_REVISION
2854 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2855 #endif
2856 extended_info->samba_subversion = 0;
2857 #ifdef SAMBA_VERSION_RC_RELEASE
2858 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2859 #else
2860 #ifdef SAMBA_VERSION_PRE_RELEASE
2861 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2862 #endif
2863 #endif
2864 #ifdef SAMBA_VERSION_VENDOR_PATCH
2865 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2866 #endif
2867 extended_info->samba_gitcommitdate = 0;
2868 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2869 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2870 #endif
2872 memset(extended_info->samba_version_string, 0,
2873 sizeof(extended_info->samba_version_string));
2875 snprintf (extended_info->samba_version_string,
2876 sizeof(extended_info->samba_version_string),
2877 "%s", samba_version_string());
2880 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2881 TALLOC_CTX *mem_ctx,
2882 uint16_t info_level,
2883 uint16_t flags2,
2884 unsigned int max_data_bytes,
2885 char **ppdata,
2886 int *ret_data_len)
2888 char *pdata, *end_data;
2889 int data_len = 0, len;
2890 const char *vname = volume_label(SNUM(conn));
2891 int snum = SNUM(conn);
2892 char *fstype = lp_fstype(SNUM(conn));
2893 uint32 additional_flags = 0;
2894 struct smb_filename smb_fname_dot;
2895 SMB_STRUCT_STAT st;
2897 if (IS_IPC(conn)) {
2898 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2899 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2900 "info level (0x%x) on IPC$.\n",
2901 (unsigned int)info_level));
2902 return NT_STATUS_ACCESS_DENIED;
2906 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2908 ZERO_STRUCT(smb_fname_dot);
2909 smb_fname_dot.base_name = discard_const_p(char, ".");
2911 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2912 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2913 return map_nt_error_from_unix(errno);
2916 st = smb_fname_dot.st;
2918 *ppdata = (char *)SMB_REALLOC(
2919 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2920 if (*ppdata == NULL) {
2921 return NT_STATUS_NO_MEMORY;
2924 pdata = *ppdata;
2925 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2926 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2928 switch (info_level) {
2929 case SMB_INFO_ALLOCATION:
2931 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2932 data_len = 18;
2933 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2934 return map_nt_error_from_unix(errno);
2937 block_size = lp_block_size(snum);
2938 if (bsize < block_size) {
2939 uint64_t factor = block_size/bsize;
2940 bsize = block_size;
2941 dsize /= factor;
2942 dfree /= factor;
2944 if (bsize > block_size) {
2945 uint64_t factor = bsize/block_size;
2946 bsize = block_size;
2947 dsize *= factor;
2948 dfree *= factor;
2950 bytes_per_sector = 512;
2951 sectors_per_unit = bsize/bytes_per_sector;
2953 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2954 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2955 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2957 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2958 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2959 SIVAL(pdata,l1_cUnit,dsize);
2960 SIVAL(pdata,l1_cUnitAvail,dfree);
2961 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2962 break;
2965 case SMB_INFO_VOLUME:
2966 /* Return volume name */
2968 * Add volume serial number - hash of a combination of
2969 * the called hostname and the service name.
2971 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2973 * Win2k3 and previous mess this up by sending a name length
2974 * one byte short. I believe only older clients (OS/2 Win9x) use
2975 * this call so try fixing this by adding a terminating null to
2976 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2978 len = srvstr_push(
2979 pdata, flags2,
2980 pdata+l2_vol_szVolLabel, vname,
2981 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2982 STR_NOALIGN|STR_TERMINATE);
2983 SCVAL(pdata,l2_vol_cch,len);
2984 data_len = l2_vol_szVolLabel + len;
2985 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2986 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2987 len, vname));
2988 break;
2990 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2991 case SMB_FS_ATTRIBUTE_INFORMATION:
2993 additional_flags = 0;
2994 #if defined(HAVE_SYS_QUOTAS)
2995 additional_flags |= FILE_VOLUME_QUOTAS;
2996 #endif
2998 if(lp_nt_acl_support(SNUM(conn))) {
2999 additional_flags |= FILE_PERSISTENT_ACLS;
3002 /* Capabilities are filled in at connection time through STATVFS call */
3003 additional_flags |= conn->fs_capabilities;
3004 additional_flags |= lp_parm_int(conn->params->service,
3005 "share", "fake_fscaps",
3008 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3009 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3010 additional_flags); /* FS ATTRIBUTES */
3012 SIVAL(pdata,4,255); /* Max filename component length */
3013 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3014 and will think we can't do long filenames */
3015 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3016 PTR_DIFF(end_data, pdata+12),
3017 STR_UNICODE);
3018 SIVAL(pdata,8,len);
3019 data_len = 12 + len;
3020 break;
3022 case SMB_QUERY_FS_LABEL_INFO:
3023 case SMB_FS_LABEL_INFORMATION:
3024 len = srvstr_push(pdata, flags2, pdata+4, vname,
3025 PTR_DIFF(end_data, pdata+4), 0);
3026 data_len = 4 + len;
3027 SIVAL(pdata,0,len);
3028 break;
3030 case SMB_QUERY_FS_VOLUME_INFO:
3031 case SMB_FS_VOLUME_INFORMATION:
3034 * Add volume serial number - hash of a combination of
3035 * the called hostname and the service name.
3037 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3038 (str_checksum(get_local_machine_name())<<16));
3040 /* Max label len is 32 characters. */
3041 len = srvstr_push(pdata, flags2, pdata+18, vname,
3042 PTR_DIFF(end_data, pdata+18),
3043 STR_UNICODE);
3044 SIVAL(pdata,12,len);
3045 data_len = 18+len;
3047 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3048 (int)strlen(vname),vname, lp_servicename(snum)));
3049 break;
3051 case SMB_QUERY_FS_SIZE_INFO:
3052 case SMB_FS_SIZE_INFORMATION:
3054 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3055 data_len = 24;
3056 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3057 return map_nt_error_from_unix(errno);
3059 block_size = lp_block_size(snum);
3060 if (bsize < block_size) {
3061 uint64_t factor = block_size/bsize;
3062 bsize = block_size;
3063 dsize /= factor;
3064 dfree /= factor;
3066 if (bsize > block_size) {
3067 uint64_t factor = bsize/block_size;
3068 bsize = block_size;
3069 dsize *= factor;
3070 dfree *= factor;
3072 bytes_per_sector = 512;
3073 sectors_per_unit = bsize/bytes_per_sector;
3074 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3075 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3076 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3077 SBIG_UINT(pdata,0,dsize);
3078 SBIG_UINT(pdata,8,dfree);
3079 SIVAL(pdata,16,sectors_per_unit);
3080 SIVAL(pdata,20,bytes_per_sector);
3081 break;
3084 case SMB_FS_FULL_SIZE_INFORMATION:
3086 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3087 data_len = 32;
3088 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3089 return map_nt_error_from_unix(errno);
3091 block_size = lp_block_size(snum);
3092 if (bsize < block_size) {
3093 uint64_t factor = block_size/bsize;
3094 bsize = block_size;
3095 dsize /= factor;
3096 dfree /= factor;
3098 if (bsize > block_size) {
3099 uint64_t factor = bsize/block_size;
3100 bsize = block_size;
3101 dsize *= factor;
3102 dfree *= factor;
3104 bytes_per_sector = 512;
3105 sectors_per_unit = bsize/bytes_per_sector;
3106 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3107 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3108 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3109 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3110 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3111 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3112 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3113 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3114 break;
3117 case SMB_QUERY_FS_DEVICE_INFO:
3118 case SMB_FS_DEVICE_INFORMATION:
3119 data_len = 8;
3120 SIVAL(pdata,0,0); /* dev type */
3121 SIVAL(pdata,4,0); /* characteristics */
3122 break;
3124 #ifdef HAVE_SYS_QUOTAS
3125 case SMB_FS_QUOTA_INFORMATION:
3127 * what we have to send --metze:
3129 * Unknown1: 24 NULL bytes
3130 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3131 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3132 * Quota Flags: 2 byte :
3133 * Unknown3: 6 NULL bytes
3135 * 48 bytes total
3137 * details for Quota Flags:
3139 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3140 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3141 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3142 * 0x0001 Enable Quotas: enable quota for this fs
3146 /* we need to fake up a fsp here,
3147 * because its not send in this call
3149 files_struct fsp;
3150 SMB_NTQUOTA_STRUCT quotas;
3152 ZERO_STRUCT(fsp);
3153 ZERO_STRUCT(quotas);
3155 fsp.conn = conn;
3156 fsp.fnum = -1;
3158 /* access check */
3159 if (conn->server_info->utok.uid != sec_initial_uid()) {
3160 DEBUG(0,("set_user_quota: access_denied "
3161 "service [%s] user [%s]\n",
3162 lp_servicename(SNUM(conn)),
3163 conn->server_info->unix_name));
3164 return NT_STATUS_ACCESS_DENIED;
3167 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3168 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3169 return map_nt_error_from_unix(errno);
3172 data_len = 48;
3174 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3175 lp_servicename(SNUM(conn))));
3177 /* Unknown1 24 NULL bytes*/
3178 SBIG_UINT(pdata,0,(uint64_t)0);
3179 SBIG_UINT(pdata,8,(uint64_t)0);
3180 SBIG_UINT(pdata,16,(uint64_t)0);
3182 /* Default Soft Quota 8 bytes */
3183 SBIG_UINT(pdata,24,quotas.softlim);
3185 /* Default Hard Quota 8 bytes */
3186 SBIG_UINT(pdata,32,quotas.hardlim);
3188 /* Quota flag 2 bytes */
3189 SSVAL(pdata,40,quotas.qflags);
3191 /* Unknown3 6 NULL bytes */
3192 SSVAL(pdata,42,0);
3193 SIVAL(pdata,44,0);
3195 break;
3197 #endif /* HAVE_SYS_QUOTAS */
3198 case SMB_FS_OBJECTID_INFORMATION:
3200 unsigned char objid[16];
3201 struct smb_extended_info extended_info;
3202 memcpy(pdata,create_volume_objectid(conn, objid),16);
3203 samba_extended_info_version (&extended_info);
3204 SIVAL(pdata,16,extended_info.samba_magic);
3205 SIVAL(pdata,20,extended_info.samba_version);
3206 SIVAL(pdata,24,extended_info.samba_subversion);
3207 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3208 memcpy(pdata+36,extended_info.samba_version_string,28);
3209 data_len = 64;
3210 break;
3214 * Query the version and capabilities of the CIFS UNIX extensions
3215 * in use.
3218 case SMB_QUERY_CIFS_UNIX_INFO:
3220 bool large_write = lp_min_receive_file_size() &&
3221 !srv_is_signing_active(smbd_server_conn);
3222 bool large_read = !srv_is_signing_active(smbd_server_conn);
3223 int encrypt_caps = 0;
3225 if (!lp_unix_extensions()) {
3226 return NT_STATUS_INVALID_LEVEL;
3229 switch (conn->encrypt_level) {
3230 case 0:
3231 encrypt_caps = 0;
3232 break;
3233 case 1:
3234 case Auto:
3235 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3236 break;
3237 case Required:
3238 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3239 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3240 large_write = false;
3241 large_read = false;
3242 break;
3245 data_len = 12;
3246 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3247 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3249 /* We have POSIX ACLs, pathname, encryption,
3250 * large read/write, and locking capability. */
3252 SBIG_UINT(pdata,4,((uint64_t)(
3253 CIFS_UNIX_POSIX_ACLS_CAP|
3254 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3255 CIFS_UNIX_FCNTL_LOCKS_CAP|
3256 CIFS_UNIX_EXTATTR_CAP|
3257 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3258 encrypt_caps|
3259 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3260 (large_write ?
3261 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3262 break;
3265 case SMB_QUERY_POSIX_FS_INFO:
3267 int rc;
3268 vfs_statvfs_struct svfs;
3270 if (!lp_unix_extensions()) {
3271 return NT_STATUS_INVALID_LEVEL;
3274 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3276 if (!rc) {
3277 data_len = 56;
3278 SIVAL(pdata,0,svfs.OptimalTransferSize);
3279 SIVAL(pdata,4,svfs.BlockSize);
3280 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3281 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3282 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3283 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3284 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3285 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3286 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3287 #ifdef EOPNOTSUPP
3288 } else if (rc == EOPNOTSUPP) {
3289 return NT_STATUS_INVALID_LEVEL;
3290 #endif /* EOPNOTSUPP */
3291 } else {
3292 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3293 return NT_STATUS_DOS(ERRSRV, ERRerror);
3295 break;
3298 case SMB_QUERY_POSIX_WHOAMI:
3300 uint32_t flags = 0;
3301 uint32_t sid_bytes;
3302 int i;
3304 if (!lp_unix_extensions()) {
3305 return NT_STATUS_INVALID_LEVEL;
3308 if (max_data_bytes < 40) {
3309 return NT_STATUS_BUFFER_TOO_SMALL;
3312 /* We ARE guest if global_sid_Builtin_Guests is
3313 * in our list of SIDs.
3315 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3316 conn->server_info->ptok)) {
3317 flags |= SMB_WHOAMI_GUEST;
3320 /* We are NOT guest if global_sid_Authenticated_Users
3321 * is in our list of SIDs.
3323 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3324 conn->server_info->ptok)) {
3325 flags &= ~SMB_WHOAMI_GUEST;
3328 /* NOTE: 8 bytes for UID/GID, irrespective of native
3329 * platform size. This matches
3330 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3332 data_len = 4 /* flags */
3333 + 4 /* flag mask */
3334 + 8 /* uid */
3335 + 8 /* gid */
3336 + 4 /* ngroups */
3337 + 4 /* num_sids */
3338 + 4 /* SID bytes */
3339 + 4 /* pad/reserved */
3340 + (conn->server_info->utok.ngroups * 8)
3341 /* groups list */
3342 + (conn->server_info->ptok->num_sids *
3343 SID_MAX_SIZE)
3344 /* SID list */;
3346 SIVAL(pdata, 0, flags);
3347 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3348 SBIG_UINT(pdata, 8,
3349 (uint64_t)conn->server_info->utok.uid);
3350 SBIG_UINT(pdata, 16,
3351 (uint64_t)conn->server_info->utok.gid);
3354 if (data_len >= max_data_bytes) {
3355 /* Potential overflow, skip the GIDs and SIDs. */
3357 SIVAL(pdata, 24, 0); /* num_groups */
3358 SIVAL(pdata, 28, 0); /* num_sids */
3359 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3360 SIVAL(pdata, 36, 0); /* reserved */
3362 data_len = 40;
3363 break;
3366 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3367 SIVAL(pdata, 28, conn->server_info->num_sids);
3369 /* We walk the SID list twice, but this call is fairly
3370 * infrequent, and I don't expect that it's performance
3371 * sensitive -- jpeach
3373 for (i = 0, sid_bytes = 0;
3374 i < conn->server_info->ptok->num_sids; ++i) {
3375 sid_bytes += ndr_size_dom_sid(
3376 &conn->server_info->ptok->user_sids[i],
3377 NULL,
3381 /* SID list byte count */
3382 SIVAL(pdata, 32, sid_bytes);
3384 /* 4 bytes pad/reserved - must be zero */
3385 SIVAL(pdata, 36, 0);
3386 data_len = 40;
3388 /* GID list */
3389 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3390 SBIG_UINT(pdata, data_len,
3391 (uint64_t)conn->server_info->utok.groups[i]);
3392 data_len += 8;
3395 /* SID list */
3396 for (i = 0;
3397 i < conn->server_info->ptok->num_sids; ++i) {
3398 int sid_len = ndr_size_dom_sid(
3399 &conn->server_info->ptok->user_sids[i],
3400 NULL,
3403 sid_linearize(pdata + data_len, sid_len,
3404 &conn->server_info->ptok->user_sids[i]);
3405 data_len += sid_len;
3408 break;
3411 case SMB_MAC_QUERY_FS_INFO:
3413 * Thursby MAC extension... ONLY on NTFS filesystems
3414 * once we do streams then we don't need this
3416 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3417 data_len = 88;
3418 SIVAL(pdata,84,0x100); /* Don't support mac... */
3419 break;
3421 /* drop through */
3422 default:
3423 return NT_STATUS_INVALID_LEVEL;
3426 *ret_data_len = data_len;
3427 return NT_STATUS_OK;
3430 /****************************************************************************
3431 Reply to a TRANS2_QFSINFO (query filesystem info).
3432 ****************************************************************************/
3434 static void call_trans2qfsinfo(connection_struct *conn,
3435 struct smb_request *req,
3436 char **pparams, int total_params,
3437 char **ppdata, int total_data,
3438 unsigned int max_data_bytes)
3440 char *params = *pparams;
3441 uint16_t info_level;
3442 int data_len = 0;
3443 NTSTATUS status;
3445 if (total_params < 2) {
3446 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3447 return;
3450 info_level = SVAL(params,0);
3452 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3453 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3454 DEBUG(0,("call_trans2qfsinfo: encryption required "
3455 "and info level 0x%x sent.\n",
3456 (unsigned int)info_level));
3457 exit_server_cleanly("encryption required "
3458 "on connection");
3459 return;
3463 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3465 status = smbd_do_qfsinfo(conn, req,
3466 info_level,
3467 req->flags2,
3468 max_data_bytes,
3469 ppdata, &data_len);
3470 if (!NT_STATUS_IS_OK(status)) {
3471 reply_nterror(req, status);
3472 return;
3475 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3476 max_data_bytes);
3478 DEBUG( 4, ( "%s info_level = %d\n",
3479 smb_fn_name(req->cmd), info_level) );
3481 return;
3484 /****************************************************************************
3485 Reply to a TRANS2_SETFSINFO (set filesystem info).
3486 ****************************************************************************/
3488 static void call_trans2setfsinfo(connection_struct *conn,
3489 struct smb_request *req,
3490 char **pparams, int total_params,
3491 char **ppdata, int total_data,
3492 unsigned int max_data_bytes)
3494 char *pdata = *ppdata;
3495 char *params = *pparams;
3496 uint16 info_level;
3498 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3500 /* */
3501 if (total_params < 4) {
3502 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3503 total_params));
3504 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3505 return;
3508 info_level = SVAL(params,2);
3510 if (IS_IPC(conn)) {
3511 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3512 info_level != SMB_SET_CIFS_UNIX_INFO) {
3513 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3514 "info level (0x%x) on IPC$.\n",
3515 (unsigned int)info_level));
3516 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3517 return;
3521 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3522 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3523 DEBUG(0,("call_trans2setfsinfo: encryption required "
3524 "and info level 0x%x sent.\n",
3525 (unsigned int)info_level));
3526 exit_server_cleanly("encryption required "
3527 "on connection");
3528 return;
3532 switch(info_level) {
3533 case SMB_SET_CIFS_UNIX_INFO:
3535 uint16 client_unix_major;
3536 uint16 client_unix_minor;
3537 uint32 client_unix_cap_low;
3538 uint32 client_unix_cap_high;
3540 if (!lp_unix_extensions()) {
3541 reply_nterror(req,
3542 NT_STATUS_INVALID_LEVEL);
3543 return;
3546 /* There should be 12 bytes of capabilities set. */
3547 if (total_data < 8) {
3548 reply_nterror(
3549 req,
3550 NT_STATUS_INVALID_PARAMETER);
3551 return;
3553 client_unix_major = SVAL(pdata,0);
3554 client_unix_minor = SVAL(pdata,2);
3555 client_unix_cap_low = IVAL(pdata,4);
3556 client_unix_cap_high = IVAL(pdata,8);
3557 /* Just print these values for now. */
3558 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3559 cap_low = 0x%x, cap_high = 0x%x\n",
3560 (unsigned int)client_unix_major,
3561 (unsigned int)client_unix_minor,
3562 (unsigned int)client_unix_cap_low,
3563 (unsigned int)client_unix_cap_high ));
3565 /* Here is where we must switch to posix pathname processing... */
3566 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3567 lp_set_posix_pathnames();
3568 mangle_change_to_posix();
3571 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3572 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3573 /* Client that knows how to do posix locks,
3574 * but not posix open/mkdir operations. Set a
3575 * default type for read/write checks. */
3577 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3580 break;
3583 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3585 NTSTATUS status;
3586 size_t param_len = 0;
3587 size_t data_len = total_data;
3589 if (!lp_unix_extensions()) {
3590 reply_nterror(
3591 req,
3592 NT_STATUS_INVALID_LEVEL);
3593 return;
3596 if (lp_smb_encrypt(SNUM(conn)) == false) {
3597 reply_nterror(
3598 req,
3599 NT_STATUS_NOT_SUPPORTED);
3600 return;
3603 DEBUG( 4,("call_trans2setfsinfo: "
3604 "request transport encryption.\n"));
3606 status = srv_request_encryption_setup(conn,
3607 (unsigned char **)ppdata,
3608 &data_len,
3609 (unsigned char **)pparams,
3610 &param_len);
3612 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3613 !NT_STATUS_IS_OK(status)) {
3614 reply_nterror(req, status);
3615 return;
3618 send_trans2_replies(conn, req,
3619 *pparams,
3620 param_len,
3621 *ppdata,
3622 data_len,
3623 max_data_bytes);
3625 if (NT_STATUS_IS_OK(status)) {
3626 /* Server-side transport
3627 * encryption is now *on*. */
3628 status = srv_encryption_start(conn);
3629 if (!NT_STATUS_IS_OK(status)) {
3630 exit_server_cleanly(
3631 "Failure in setting "
3632 "up encrypted transport");
3635 return;
3638 case SMB_FS_QUOTA_INFORMATION:
3640 files_struct *fsp = NULL;
3641 SMB_NTQUOTA_STRUCT quotas;
3643 ZERO_STRUCT(quotas);
3645 /* access check */
3646 if ((conn->server_info->utok.uid != sec_initial_uid())
3647 ||!CAN_WRITE(conn)) {
3648 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3649 lp_servicename(SNUM(conn)),
3650 conn->server_info->unix_name));
3651 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3652 return;
3655 /* note: normaly there're 48 bytes,
3656 * but we didn't use the last 6 bytes for now
3657 * --metze
3659 fsp = file_fsp(req, SVAL(params,0));
3661 if (!check_fsp_ntquota_handle(conn, req,
3662 fsp)) {
3663 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3664 reply_nterror(
3665 req, NT_STATUS_INVALID_HANDLE);
3666 return;
3669 if (total_data < 42) {
3670 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3671 total_data));
3672 reply_nterror(
3673 req,
3674 NT_STATUS_INVALID_PARAMETER);
3675 return;
3678 /* unknown_1 24 NULL bytes in pdata*/
3680 /* the soft quotas 8 bytes (uint64_t)*/
3681 quotas.softlim = (uint64_t)IVAL(pdata,24);
3682 #ifdef LARGE_SMB_OFF_T
3683 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3684 #else /* LARGE_SMB_OFF_T */
3685 if ((IVAL(pdata,28) != 0)&&
3686 ((quotas.softlim != 0xFFFFFFFF)||
3687 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3688 /* more than 32 bits? */
3689 reply_nterror(
3690 req,
3691 NT_STATUS_INVALID_PARAMETER);
3692 return;
3694 #endif /* LARGE_SMB_OFF_T */
3696 /* the hard quotas 8 bytes (uint64_t)*/
3697 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3698 #ifdef LARGE_SMB_OFF_T
3699 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3700 #else /* LARGE_SMB_OFF_T */
3701 if ((IVAL(pdata,36) != 0)&&
3702 ((quotas.hardlim != 0xFFFFFFFF)||
3703 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3704 /* more than 32 bits? */
3705 reply_nterror(
3706 req,
3707 NT_STATUS_INVALID_PARAMETER);
3708 return;
3710 #endif /* LARGE_SMB_OFF_T */
3712 /* quota_flags 2 bytes **/
3713 quotas.qflags = SVAL(pdata,40);
3715 /* unknown_2 6 NULL bytes follow*/
3717 /* now set the quotas */
3718 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3719 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3720 reply_nterror(req, map_nt_error_from_unix(errno));
3721 return;
3724 break;
3726 default:
3727 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3728 info_level));
3729 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3730 return;
3731 break;
3735 * sending this reply works fine,
3736 * but I'm not sure it's the same
3737 * like windows do...
3738 * --metze
3740 reply_outbuf(req, 10, 0);
3743 #if defined(HAVE_POSIX_ACLS)
3744 /****************************************************************************
3745 Utility function to count the number of entries in a POSIX acl.
3746 ****************************************************************************/
3748 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3750 unsigned int ace_count = 0;
3751 int entry_id = SMB_ACL_FIRST_ENTRY;
3752 SMB_ACL_ENTRY_T entry;
3754 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3755 /* get_next... */
3756 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3757 entry_id = SMB_ACL_NEXT_ENTRY;
3759 ace_count++;
3761 return ace_count;
3764 /****************************************************************************
3765 Utility function to marshall a POSIX acl into wire format.
3766 ****************************************************************************/
3768 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3770 int entry_id = SMB_ACL_FIRST_ENTRY;
3771 SMB_ACL_ENTRY_T entry;
3773 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3774 SMB_ACL_TAG_T tagtype;
3775 SMB_ACL_PERMSET_T permset;
3776 unsigned char perms = 0;
3777 unsigned int own_grp;
3779 /* get_next... */
3780 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3781 entry_id = SMB_ACL_NEXT_ENTRY;
3784 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3785 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3786 return False;
3789 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3790 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3791 return False;
3794 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3795 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3796 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3798 SCVAL(pdata,1,perms);
3800 switch (tagtype) {
3801 case SMB_ACL_USER_OBJ:
3802 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3803 own_grp = (unsigned int)pst->st_ex_uid;
3804 SIVAL(pdata,2,own_grp);
3805 SIVAL(pdata,6,0);
3806 break;
3807 case SMB_ACL_USER:
3809 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3810 if (!puid) {
3811 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3812 return False;
3814 own_grp = (unsigned int)*puid;
3815 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3816 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3817 SIVAL(pdata,2,own_grp);
3818 SIVAL(pdata,6,0);
3819 break;
3821 case SMB_ACL_GROUP_OBJ:
3822 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3823 own_grp = (unsigned int)pst->st_ex_gid;
3824 SIVAL(pdata,2,own_grp);
3825 SIVAL(pdata,6,0);
3826 break;
3827 case SMB_ACL_GROUP:
3829 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3830 if (!pgid) {
3831 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3832 return False;
3834 own_grp = (unsigned int)*pgid;
3835 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3836 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3837 SIVAL(pdata,2,own_grp);
3838 SIVAL(pdata,6,0);
3839 break;
3841 case SMB_ACL_MASK:
3842 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3843 SIVAL(pdata,2,0xFFFFFFFF);
3844 SIVAL(pdata,6,0xFFFFFFFF);
3845 break;
3846 case SMB_ACL_OTHER:
3847 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3848 SIVAL(pdata,2,0xFFFFFFFF);
3849 SIVAL(pdata,6,0xFFFFFFFF);
3850 break;
3851 default:
3852 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3853 return False;
3855 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3858 return True;
3860 #endif
3862 /****************************************************************************
3863 Store the FILE_UNIX_BASIC info.
3864 ****************************************************************************/
3866 static char *store_file_unix_basic(connection_struct *conn,
3867 char *pdata,
3868 files_struct *fsp,
3869 const SMB_STRUCT_STAT *psbuf)
3871 uint64_t file_index = get_FileIndex(conn, psbuf);
3873 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3874 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3876 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3877 pdata += 8;
3879 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3880 pdata += 8;
3882 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3883 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3884 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3885 pdata += 24;
3887 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3888 SIVAL(pdata,4,0);
3889 pdata += 8;
3891 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3892 SIVAL(pdata,4,0);
3893 pdata += 8;
3895 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3896 pdata += 4;
3898 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3899 SIVAL(pdata,4,0);
3900 pdata += 8;
3902 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3903 SIVAL(pdata,4,0);
3904 pdata += 8;
3906 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3907 pdata += 8;
3909 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3910 SIVAL(pdata,4,0);
3911 pdata += 8;
3913 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3914 SIVAL(pdata,4,0);
3915 pdata += 8;
3917 return pdata;
3920 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3921 * the chflags(2) (or equivalent) flags.
3923 * XXX: this really should be behind the VFS interface. To do this, we would
3924 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3925 * Each VFS module could then implement its own mapping as appropriate for the
3926 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3928 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3929 info2_flags_map[] =
3931 #ifdef UF_NODUMP
3932 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3933 #endif
3935 #ifdef UF_IMMUTABLE
3936 { UF_IMMUTABLE, EXT_IMMUTABLE },
3937 #endif
3939 #ifdef UF_APPEND
3940 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3941 #endif
3943 #ifdef UF_HIDDEN
3944 { UF_HIDDEN, EXT_HIDDEN },
3945 #endif
3947 /* Do not remove. We need to guarantee that this array has at least one
3948 * entry to build on HP-UX.
3950 { 0, 0 }
3954 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3955 uint32 *smb_fflags, uint32 *smb_fmask)
3957 int i;
3959 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3960 *smb_fmask |= info2_flags_map[i].smb_fflag;
3961 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3962 *smb_fflags |= info2_flags_map[i].smb_fflag;
3967 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3968 const uint32 smb_fflags,
3969 const uint32 smb_fmask,
3970 int *stat_fflags)
3972 uint32 max_fmask = 0;
3973 int i;
3975 *stat_fflags = psbuf->st_ex_flags;
3977 /* For each flags requested in smb_fmask, check the state of the
3978 * corresponding flag in smb_fflags and set or clear the matching
3979 * stat flag.
3982 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3983 max_fmask |= info2_flags_map[i].smb_fflag;
3984 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3985 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3986 *stat_fflags |= info2_flags_map[i].stat_fflag;
3987 } else {
3988 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3993 /* If smb_fmask is asking to set any bits that are not supported by
3994 * our flag mappings, we should fail.
3996 if ((smb_fmask & max_fmask) != smb_fmask) {
3997 return False;
4000 return True;
4004 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4005 * of file flags and birth (create) time.
4007 static char *store_file_unix_basic_info2(connection_struct *conn,
4008 char *pdata,
4009 files_struct *fsp,
4010 const SMB_STRUCT_STAT *psbuf)
4012 uint32 file_flags = 0;
4013 uint32 flags_mask = 0;
4015 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4017 /* Create (birth) time 64 bit */
4018 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4019 pdata += 8;
4021 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4022 SIVAL(pdata, 0, file_flags); /* flags */
4023 SIVAL(pdata, 4, flags_mask); /* mask */
4024 pdata += 8;
4026 return pdata;
4029 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4030 const struct stream_struct *streams,
4031 char *data,
4032 unsigned int max_data_bytes,
4033 unsigned int *data_size)
4035 unsigned int i;
4036 unsigned int ofs = 0;
4038 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4039 unsigned int next_offset;
4040 size_t namelen;
4041 smb_ucs2_t *namebuf;
4043 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4044 streams[i].name, &namelen) ||
4045 namelen <= 2)
4047 return NT_STATUS_INVALID_PARAMETER;
4051 * name_buf is now null-terminated, we need to marshall as not
4052 * terminated
4055 namelen -= 2;
4057 SIVAL(data, ofs+4, namelen);
4058 SOFF_T(data, ofs+8, streams[i].size);
4059 SOFF_T(data, ofs+16, streams[i].alloc_size);
4060 memcpy(data+ofs+24, namebuf, namelen);
4061 TALLOC_FREE(namebuf);
4063 next_offset = ofs + 24 + namelen;
4065 if (i == num_streams-1) {
4066 SIVAL(data, ofs, 0);
4068 else {
4069 unsigned int align = ndr_align_size(next_offset, 8);
4071 memset(data+next_offset, 0, align);
4072 next_offset += align;
4074 SIVAL(data, ofs, next_offset - ofs);
4075 ofs = next_offset;
4078 ofs = next_offset;
4081 *data_size = ofs;
4083 return NT_STATUS_OK;
4086 /****************************************************************************
4087 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4088 ****************************************************************************/
4090 static void call_trans2qpipeinfo(connection_struct *conn,
4091 struct smb_request *req,
4092 unsigned int tran_call,
4093 char **pparams, int total_params,
4094 char **ppdata, int total_data,
4095 unsigned int max_data_bytes)
4097 char *params = *pparams;
4098 char *pdata = *ppdata;
4099 unsigned int data_size = 0;
4100 unsigned int param_size = 2;
4101 uint16 info_level;
4102 files_struct *fsp;
4104 if (!params) {
4105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4106 return;
4109 if (total_params < 4) {
4110 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4111 return;
4114 fsp = file_fsp(req, SVAL(params,0));
4115 if (!fsp_is_np(fsp)) {
4116 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4117 return;
4120 info_level = SVAL(params,2);
4122 *pparams = (char *)SMB_REALLOC(*pparams,2);
4123 if (*pparams == NULL) {
4124 reply_nterror(req, NT_STATUS_NO_MEMORY);
4125 return;
4127 params = *pparams;
4128 SSVAL(params,0,0);
4129 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4130 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4131 if (*ppdata == NULL ) {
4132 reply_nterror(req, NT_STATUS_NO_MEMORY);
4133 return;
4135 pdata = *ppdata;
4137 switch (info_level) {
4138 case SMB_FILE_STANDARD_INFORMATION:
4139 memset(pdata,0,24);
4140 SOFF_T(pdata,0,4096LL);
4141 SIVAL(pdata,16,1);
4142 SIVAL(pdata,20,1);
4143 data_size = 24;
4144 break;
4146 default:
4147 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4148 return;
4151 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4152 max_data_bytes);
4154 return;
4157 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4158 TALLOC_CTX *mem_ctx,
4159 uint16_t info_level,
4160 files_struct *fsp,
4161 struct smb_filename *smb_fname,
4162 bool delete_pending,
4163 struct timespec write_time_ts,
4164 bool ms_dfs_link,
4165 struct ea_list *ea_list,
4166 int lock_data_count,
4167 char *lock_data,
4168 uint16_t flags2,
4169 unsigned int max_data_bytes,
4170 char **ppdata,
4171 unsigned int *pdata_size)
4173 char *pdata = *ppdata;
4174 char *dstart, *dend;
4175 unsigned int data_size;
4176 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4177 time_t create_time, mtime, atime, c_time;
4178 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4179 char *p;
4180 char *base_name;
4181 char *dos_fname;
4182 int mode;
4183 int nlink;
4184 NTSTATUS status;
4185 uint64_t file_size = 0;
4186 uint64_t pos = 0;
4187 uint64_t allocation_size = 0;
4188 uint64_t file_index = 0;
4189 uint32_t access_mask = 0;
4191 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4192 return NT_STATUS_INVALID_LEVEL;
4195 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4196 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4197 info_level, max_data_bytes));
4199 if (ms_dfs_link) {
4200 mode = dos_mode_msdfs(conn, smb_fname);
4201 } else {
4202 mode = dos_mode(conn, smb_fname);
4205 nlink = psbuf->st_ex_nlink;
4207 if (nlink && (mode&aDIR)) {
4208 nlink = 1;
4211 if ((nlink > 0) && delete_pending) {
4212 nlink -= 1;
4215 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4216 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4217 if (*ppdata == NULL) {
4218 return NT_STATUS_NO_MEMORY;
4220 pdata = *ppdata;
4221 dstart = pdata;
4222 dend = dstart + data_size - 1;
4224 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4225 update_stat_ex_mtime(psbuf, write_time_ts);
4228 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4229 mtime_ts = psbuf->st_ex_mtime;
4230 atime_ts = psbuf->st_ex_atime;
4231 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4233 if (lp_dos_filetime_resolution(SNUM(conn))) {
4234 dos_filetime_timespec(&create_time_ts);
4235 dos_filetime_timespec(&mtime_ts);
4236 dos_filetime_timespec(&atime_ts);
4237 dos_filetime_timespec(&ctime_ts);
4240 create_time = convert_timespec_to_time_t(create_time_ts);
4241 mtime = convert_timespec_to_time_t(mtime_ts);
4242 atime = convert_timespec_to_time_t(atime_ts);
4243 c_time = convert_timespec_to_time_t(ctime_ts);
4245 p = strrchr_m(smb_fname->base_name,'/');
4246 if (!p)
4247 base_name = smb_fname->base_name;
4248 else
4249 base_name = p+1;
4251 /* NT expects the name to be in an exact form of the *full*
4252 filename. See the trans2 torture test */
4253 if (ISDOT(base_name)) {
4254 dos_fname = talloc_strdup(mem_ctx, "\\");
4255 if (!dos_fname) {
4256 return NT_STATUS_NO_MEMORY;
4258 } else {
4259 dos_fname = talloc_asprintf(mem_ctx,
4260 "\\%s",
4261 smb_fname->base_name);
4262 if (!dos_fname) {
4263 return NT_STATUS_NO_MEMORY;
4265 if (is_ntfs_stream_smb_fname(smb_fname)) {
4266 dos_fname = talloc_asprintf(dos_fname, "%s",
4267 smb_fname->stream_name);
4268 if (!dos_fname) {
4269 return NT_STATUS_NO_MEMORY;
4273 string_replace(dos_fname, '/', '\\');
4276 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4278 if (!fsp) {
4279 /* Do we have this path open ? */
4280 files_struct *fsp1;
4281 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4282 fsp1 = file_find_di_first(fileid);
4283 if (fsp1 && fsp1->initial_allocation_size) {
4284 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4288 if (!(mode & aDIR)) {
4289 file_size = get_file_size_stat(psbuf);
4292 if (fsp) {
4293 pos = fsp->fh->position_information;
4296 if (fsp) {
4297 access_mask = fsp->access_mask;
4298 } else {
4299 /* GENERIC_EXECUTE mapping from Windows */
4300 access_mask = 0x12019F;
4303 /* This should be an index number - looks like
4304 dev/ino to me :-)
4306 I think this causes us to fail the IFSKIT
4307 BasicFileInformationTest. -tpot */
4308 file_index = get_FileIndex(conn, psbuf);
4310 switch (info_level) {
4311 case SMB_INFO_STANDARD:
4312 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4313 data_size = 22;
4314 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4315 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4316 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4317 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4318 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4319 SSVAL(pdata,l1_attrFile,mode);
4320 break;
4322 case SMB_INFO_QUERY_EA_SIZE:
4324 unsigned int ea_size =
4325 estimate_ea_size(conn, fsp,
4326 smb_fname->base_name);
4327 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4328 data_size = 26;
4329 srv_put_dos_date2(pdata,0,create_time);
4330 srv_put_dos_date2(pdata,4,atime);
4331 srv_put_dos_date2(pdata,8,mtime); /* write time */
4332 SIVAL(pdata,12,(uint32)file_size);
4333 SIVAL(pdata,16,(uint32)allocation_size);
4334 SSVAL(pdata,20,mode);
4335 SIVAL(pdata,22,ea_size);
4336 break;
4339 case SMB_INFO_IS_NAME_VALID:
4340 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4341 if (fsp) {
4342 /* os/2 needs this ? really ?*/
4343 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4345 /* This is only reached for qpathinfo */
4346 data_size = 0;
4347 break;
4349 case SMB_INFO_QUERY_EAS_FROM_LIST:
4351 size_t total_ea_len = 0;
4352 struct ea_list *ea_file_list = NULL;
4354 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4356 ea_file_list =
4357 get_ea_list_from_file(mem_ctx, conn, fsp,
4358 smb_fname->base_name,
4359 &total_ea_len);
4360 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4362 if (!ea_list || (total_ea_len > data_size)) {
4363 data_size = 4;
4364 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4365 break;
4368 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4369 break;
4372 case SMB_INFO_QUERY_ALL_EAS:
4374 /* We have data_size bytes to put EA's into. */
4375 size_t total_ea_len = 0;
4377 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4379 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4380 smb_fname->base_name,
4381 &total_ea_len);
4382 if (!ea_list || (total_ea_len > data_size)) {
4383 data_size = 4;
4384 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4385 break;
4388 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4389 break;
4392 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4394 /* This is FileFullEaInformation - 0xF which maps to
4395 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4397 /* We have data_size bytes to put EA's into. */
4398 size_t total_ea_len = 0;
4399 struct ea_list *ea_file_list = NULL;
4401 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4403 /*TODO: add filtering and index handling */
4405 ea_file_list =
4406 get_ea_list_from_file(mem_ctx, conn, fsp,
4407 smb_fname->base_name,
4408 &total_ea_len);
4409 if (!ea_file_list) {
4410 return NT_STATUS_NO_EAS_ON_FILE;
4413 status = fill_ea_chained_buffer(mem_ctx,
4414 pdata,
4415 data_size,
4416 &data_size,
4417 conn, ea_file_list);
4418 if (!NT_STATUS_IS_OK(status)) {
4419 return status;
4421 break;
4424 case SMB_FILE_BASIC_INFORMATION:
4425 case SMB_QUERY_FILE_BASIC_INFO:
4427 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4428 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4429 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4430 } else {
4431 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4432 data_size = 40;
4433 SIVAL(pdata,36,0);
4435 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4436 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4437 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4438 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4439 SIVAL(pdata,32,mode);
4441 DEBUG(5,("SMB_QFBI - "));
4442 DEBUG(5,("create: %s ", ctime(&create_time)));
4443 DEBUG(5,("access: %s ", ctime(&atime)));
4444 DEBUG(5,("write: %s ", ctime(&mtime)));
4445 DEBUG(5,("change: %s ", ctime(&c_time)));
4446 DEBUG(5,("mode: %x\n", mode));
4447 break;
4449 case SMB_FILE_STANDARD_INFORMATION:
4450 case SMB_QUERY_FILE_STANDARD_INFO:
4452 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4453 data_size = 24;
4454 SOFF_T(pdata,0,allocation_size);
4455 SOFF_T(pdata,8,file_size);
4456 SIVAL(pdata,16,nlink);
4457 SCVAL(pdata,20,delete_pending?1:0);
4458 SCVAL(pdata,21,(mode&aDIR)?1:0);
4459 SSVAL(pdata,22,0); /* Padding. */
4460 break;
4462 case SMB_FILE_EA_INFORMATION:
4463 case SMB_QUERY_FILE_EA_INFO:
4465 unsigned int ea_size =
4466 estimate_ea_size(conn, fsp, smb_fname->base_name);
4467 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4468 data_size = 4;
4469 SIVAL(pdata,0,ea_size);
4470 break;
4473 /* Get the 8.3 name - used if NT SMB was negotiated. */
4474 case SMB_QUERY_FILE_ALT_NAME_INFO:
4475 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4477 int len;
4478 char mangled_name[13];
4479 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4480 if (!name_to_8_3(base_name,mangled_name,
4481 True,conn->params)) {
4482 return NT_STATUS_NO_MEMORY;
4484 len = srvstr_push(dstart, flags2,
4485 pdata+4, mangled_name,
4486 PTR_DIFF(dend, pdata+4),
4487 STR_UNICODE);
4488 data_size = 4 + len;
4489 SIVAL(pdata,0,len);
4490 break;
4493 case SMB_QUERY_FILE_NAME_INFO:
4495 int len;
4497 this must be *exactly* right for ACLs on mapped drives to work
4499 len = srvstr_push(dstart, flags2,
4500 pdata+4, dos_fname,
4501 PTR_DIFF(dend, pdata+4),
4502 STR_UNICODE);
4503 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4504 data_size = 4 + len;
4505 SIVAL(pdata,0,len);
4506 break;
4509 case SMB_FILE_ALLOCATION_INFORMATION:
4510 case SMB_QUERY_FILE_ALLOCATION_INFO:
4511 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4512 data_size = 8;
4513 SOFF_T(pdata,0,allocation_size);
4514 break;
4516 case SMB_FILE_END_OF_FILE_INFORMATION:
4517 case SMB_QUERY_FILE_END_OF_FILEINFO:
4518 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4519 data_size = 8;
4520 SOFF_T(pdata,0,file_size);
4521 break;
4523 case SMB_QUERY_FILE_ALL_INFO:
4524 case SMB_FILE_ALL_INFORMATION:
4526 int len;
4527 unsigned int ea_size =
4528 estimate_ea_size(conn, fsp, smb_fname->base_name);
4529 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4530 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4531 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4532 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4533 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4534 SIVAL(pdata,32,mode);
4535 SIVAL(pdata,36,0); /* padding. */
4536 pdata += 40;
4537 SOFF_T(pdata,0,allocation_size);
4538 SOFF_T(pdata,8,file_size);
4539 SIVAL(pdata,16,nlink);
4540 SCVAL(pdata,20,delete_pending);
4541 SCVAL(pdata,21,(mode&aDIR)?1:0);
4542 SSVAL(pdata,22,0);
4543 pdata += 24;
4544 SIVAL(pdata,0,ea_size);
4545 pdata += 4; /* EA info */
4546 len = srvstr_push(dstart, flags2,
4547 pdata+4, dos_fname,
4548 PTR_DIFF(dend, pdata+4),
4549 STR_UNICODE);
4550 SIVAL(pdata,0,len);
4551 pdata += 4 + len;
4552 data_size = PTR_DIFF(pdata,(*ppdata));
4553 break;
4556 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4558 int len;
4559 unsigned int ea_size =
4560 estimate_ea_size(conn, fsp, smb_fname->base_name);
4561 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4562 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4563 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4564 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4565 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4566 SIVAL(pdata, 0x20, mode);
4567 SIVAL(pdata, 0x24, 0); /* padding. */
4568 SBVAL(pdata, 0x28, allocation_size);
4569 SBVAL(pdata, 0x30, file_size);
4570 SIVAL(pdata, 0x38, nlink);
4571 SCVAL(pdata, 0x3C, delete_pending);
4572 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4573 SSVAL(pdata, 0x3E, 0); /* padding */
4574 SBVAL(pdata, 0x40, file_index);
4575 SIVAL(pdata, 0x48, ea_size);
4576 SIVAL(pdata, 0x4C, access_mask);
4577 SBVAL(pdata, 0x50, pos);
4578 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4579 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4581 pdata += 0x60;
4583 len = srvstr_push(dstart, flags2,
4584 pdata+4, dos_fname,
4585 PTR_DIFF(dend, pdata+4),
4586 STR_UNICODE);
4587 SIVAL(pdata,0,len);
4588 pdata += 4 + len;
4589 data_size = PTR_DIFF(pdata,(*ppdata));
4590 break;
4592 case SMB_FILE_INTERNAL_INFORMATION:
4594 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4595 SBVAL(pdata, 0, file_index);
4596 data_size = 8;
4597 break;
4599 case SMB_FILE_ACCESS_INFORMATION:
4600 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4601 SIVAL(pdata, 0, access_mask);
4602 data_size = 4;
4603 break;
4605 case SMB_FILE_NAME_INFORMATION:
4606 /* Pathname with leading '\'. */
4608 size_t byte_len;
4609 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4610 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4611 SIVAL(pdata,0,byte_len);
4612 data_size = 4 + byte_len;
4613 break;
4616 case SMB_FILE_DISPOSITION_INFORMATION:
4617 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4618 data_size = 1;
4619 SCVAL(pdata,0,delete_pending);
4620 break;
4622 case SMB_FILE_POSITION_INFORMATION:
4623 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4624 data_size = 8;
4625 SOFF_T(pdata,0,pos);
4626 break;
4628 case SMB_FILE_MODE_INFORMATION:
4629 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4630 SIVAL(pdata,0,mode);
4631 data_size = 4;
4632 break;
4634 case SMB_FILE_ALIGNMENT_INFORMATION:
4635 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4636 SIVAL(pdata,0,0); /* No alignment needed. */
4637 data_size = 4;
4638 break;
4641 * NT4 server just returns "invalid query" to this - if we try
4642 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4643 * want this. JRA.
4645 /* The first statement above is false - verified using Thursby
4646 * client against NT4 -- gcolley.
4648 case SMB_QUERY_FILE_STREAM_INFO:
4649 case SMB_FILE_STREAM_INFORMATION: {
4650 unsigned int num_streams;
4651 struct stream_struct *streams;
4653 DEBUG(10,("smbd_do_qfilepathinfo: "
4654 "SMB_FILE_STREAM_INFORMATION\n"));
4656 if (is_ntfs_stream_smb_fname(smb_fname)) {
4657 return NT_STATUS_INVALID_PARAMETER;
4660 status = SMB_VFS_STREAMINFO(
4661 conn, fsp, smb_fname->base_name, talloc_tos(),
4662 &num_streams, &streams);
4664 if (!NT_STATUS_IS_OK(status)) {
4665 DEBUG(10, ("could not get stream info: %s\n",
4666 nt_errstr(status)));
4667 return status;
4670 status = marshall_stream_info(num_streams, streams,
4671 pdata, max_data_bytes,
4672 &data_size);
4674 if (!NT_STATUS_IS_OK(status)) {
4675 DEBUG(10, ("marshall_stream_info failed: %s\n",
4676 nt_errstr(status)));
4677 return status;
4680 TALLOC_FREE(streams);
4682 break;
4684 case SMB_QUERY_COMPRESSION_INFO:
4685 case SMB_FILE_COMPRESSION_INFORMATION:
4686 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4687 SOFF_T(pdata,0,file_size);
4688 SIVAL(pdata,8,0); /* ??? */
4689 SIVAL(pdata,12,0); /* ??? */
4690 data_size = 16;
4691 break;
4693 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4694 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4695 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4696 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4697 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4698 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4699 SOFF_T(pdata,32,allocation_size);
4700 SOFF_T(pdata,40,file_size);
4701 SIVAL(pdata,48,mode);
4702 SIVAL(pdata,52,0); /* ??? */
4703 data_size = 56;
4704 break;
4706 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4707 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4708 SIVAL(pdata,0,mode);
4709 SIVAL(pdata,4,0);
4710 data_size = 8;
4711 break;
4714 * CIFS UNIX Extensions.
4717 case SMB_QUERY_FILE_UNIX_BASIC:
4719 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4720 data_size = PTR_DIFF(pdata,(*ppdata));
4723 int i;
4724 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4726 for (i=0; i<100; i++)
4727 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4728 DEBUG(4,("\n"));
4731 break;
4733 case SMB_QUERY_FILE_UNIX_INFO2:
4735 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4736 data_size = PTR_DIFF(pdata,(*ppdata));
4739 int i;
4740 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4742 for (i=0; i<100; i++)
4743 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4744 DEBUG(4,("\n"));
4747 break;
4749 case SMB_QUERY_FILE_UNIX_LINK:
4751 int len;
4752 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4754 if (!buffer) {
4755 return NT_STATUS_NO_MEMORY;
4758 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4759 #ifdef S_ISLNK
4760 if(!S_ISLNK(psbuf->st_ex_mode)) {
4761 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4763 #else
4764 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4765 #endif
4766 len = SMB_VFS_READLINK(conn,
4767 smb_fname->base_name,
4768 buffer, PATH_MAX);
4769 if (len == -1) {
4770 return map_nt_error_from_unix(errno);
4772 buffer[len] = 0;
4773 len = srvstr_push(dstart, flags2,
4774 pdata, buffer,
4775 PTR_DIFF(dend, pdata),
4776 STR_TERMINATE);
4777 pdata += len;
4778 data_size = PTR_DIFF(pdata,(*ppdata));
4780 break;
4783 #if defined(HAVE_POSIX_ACLS)
4784 case SMB_QUERY_POSIX_ACL:
4786 SMB_ACL_T file_acl = NULL;
4787 SMB_ACL_T def_acl = NULL;
4788 uint16 num_file_acls = 0;
4789 uint16 num_def_acls = 0;
4791 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4792 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4793 } else {
4794 file_acl =
4795 SMB_VFS_SYS_ACL_GET_FILE(conn,
4796 smb_fname->base_name,
4797 SMB_ACL_TYPE_ACCESS);
4800 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4801 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4802 "not implemented on "
4803 "filesystem containing %s\n",
4804 smb_fname->base_name));
4805 return NT_STATUS_NOT_IMPLEMENTED;
4808 if (S_ISDIR(psbuf->st_ex_mode)) {
4809 if (fsp && fsp->is_directory) {
4810 def_acl =
4811 SMB_VFS_SYS_ACL_GET_FILE(
4812 conn,
4813 fsp->fsp_name->base_name,
4814 SMB_ACL_TYPE_DEFAULT);
4815 } else {
4816 def_acl =
4817 SMB_VFS_SYS_ACL_GET_FILE(
4818 conn,
4819 smb_fname->base_name,
4820 SMB_ACL_TYPE_DEFAULT);
4822 def_acl = free_empty_sys_acl(conn, def_acl);
4825 num_file_acls = count_acl_entries(conn, file_acl);
4826 num_def_acls = count_acl_entries(conn, def_acl);
4828 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4829 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4830 data_size,
4831 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4832 SMB_POSIX_ACL_HEADER_SIZE) ));
4833 if (file_acl) {
4834 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4836 if (def_acl) {
4837 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4839 return NT_STATUS_BUFFER_TOO_SMALL;
4842 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4843 SSVAL(pdata,2,num_file_acls);
4844 SSVAL(pdata,4,num_def_acls);
4845 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4846 if (file_acl) {
4847 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4849 if (def_acl) {
4850 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4852 return NT_STATUS_INTERNAL_ERROR;
4854 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4855 if (file_acl) {
4856 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4858 if (def_acl) {
4859 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4861 return NT_STATUS_INTERNAL_ERROR;
4864 if (file_acl) {
4865 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4867 if (def_acl) {
4868 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4870 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4871 break;
4873 #endif
4876 case SMB_QUERY_POSIX_LOCK:
4878 uint64_t count;
4879 uint64_t offset;
4880 uint32 lock_pid;
4881 enum brl_type lock_type;
4883 /* We need an open file with a real fd for this. */
4884 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4885 return NT_STATUS_INVALID_LEVEL;
4888 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4889 return NT_STATUS_INVALID_PARAMETER;
4892 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4893 case POSIX_LOCK_TYPE_READ:
4894 lock_type = READ_LOCK;
4895 break;
4896 case POSIX_LOCK_TYPE_WRITE:
4897 lock_type = WRITE_LOCK;
4898 break;
4899 case POSIX_LOCK_TYPE_UNLOCK:
4900 default:
4901 /* There's no point in asking for an unlock... */
4902 return NT_STATUS_INVALID_PARAMETER;
4905 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4906 #if defined(HAVE_LONGLONG)
4907 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4908 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4909 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4910 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4911 #else /* HAVE_LONGLONG */
4912 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4913 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4914 #endif /* HAVE_LONGLONG */
4916 status = query_lock(fsp,
4917 &lock_pid,
4918 &count,
4919 &offset,
4920 &lock_type,
4921 POSIX_LOCK);
4923 if (ERROR_WAS_LOCK_DENIED(status)) {
4924 /* Here we need to report who has it locked... */
4925 data_size = POSIX_LOCK_DATA_SIZE;
4927 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4928 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4929 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4930 #if defined(HAVE_LONGLONG)
4931 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4932 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4933 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4934 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4935 #else /* HAVE_LONGLONG */
4936 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4937 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4938 #endif /* HAVE_LONGLONG */
4940 } else if (NT_STATUS_IS_OK(status)) {
4941 /* For success we just return a copy of what we sent
4942 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4943 data_size = POSIX_LOCK_DATA_SIZE;
4944 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4945 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4946 } else {
4947 return status;
4949 break;
4952 default:
4953 return NT_STATUS_INVALID_LEVEL;
4956 *pdata_size = data_size;
4957 return NT_STATUS_OK;
4960 /****************************************************************************
4961 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4962 file name or file id).
4963 ****************************************************************************/
4965 static void call_trans2qfilepathinfo(connection_struct *conn,
4966 struct smb_request *req,
4967 unsigned int tran_call,
4968 char **pparams, int total_params,
4969 char **ppdata, int total_data,
4970 unsigned int max_data_bytes)
4972 char *params = *pparams;
4973 char *pdata = *ppdata;
4974 uint16 info_level;
4975 unsigned int data_size = 0;
4976 unsigned int param_size = 2;
4977 struct smb_filename *smb_fname = NULL;
4978 bool delete_pending = False;
4979 struct timespec write_time_ts;
4980 files_struct *fsp = NULL;
4981 struct file_id fileid;
4982 struct ea_list *ea_list = NULL;
4983 int lock_data_count = 0;
4984 char *lock_data = NULL;
4985 bool ms_dfs_link = false;
4986 NTSTATUS status = NT_STATUS_OK;
4988 if (!params) {
4989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4990 return;
4993 ZERO_STRUCT(write_time_ts);
4995 if (tran_call == TRANSACT2_QFILEINFO) {
4996 if (total_params < 4) {
4997 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4998 return;
5001 if (IS_IPC(conn)) {
5002 call_trans2qpipeinfo(conn, req, tran_call,
5003 pparams, total_params,
5004 ppdata, total_data,
5005 max_data_bytes);
5006 return;
5009 fsp = file_fsp(req, SVAL(params,0));
5010 info_level = SVAL(params,2);
5012 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5014 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5015 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5016 return;
5019 /* Initial check for valid fsp ptr. */
5020 if (!check_fsp_open(conn, req, fsp)) {
5021 return;
5024 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5025 &smb_fname);
5026 if (!NT_STATUS_IS_OK(status)) {
5027 reply_nterror(req, status);
5028 return;
5031 if(fsp->fake_file_handle) {
5033 * This is actually for the QUOTA_FAKE_FILE --metze
5036 /* We know this name is ok, it's already passed the checks. */
5038 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5040 * This is actually a QFILEINFO on a directory
5041 * handle (returned from an NT SMB). NT5.0 seems
5042 * to do this call. JRA.
5045 if (INFO_LEVEL_IS_UNIX(info_level)) {
5046 /* Always do lstat for UNIX calls. */
5047 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5048 DEBUG(3,("call_trans2qfilepathinfo: "
5049 "SMB_VFS_LSTAT of %s failed "
5050 "(%s)\n",
5051 smb_fname_str_dbg(smb_fname),
5052 strerror(errno)));
5053 reply_nterror(req,
5054 map_nt_error_from_unix(errno));
5055 return;
5057 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5058 DEBUG(3,("call_trans2qfilepathinfo: "
5059 "SMB_VFS_STAT of %s failed (%s)\n",
5060 smb_fname_str_dbg(smb_fname),
5061 strerror(errno)));
5062 reply_nterror(req,
5063 map_nt_error_from_unix(errno));
5064 return;
5067 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5068 get_file_infos(fileid, &delete_pending, &write_time_ts);
5069 } else {
5071 * Original code - this is an open file.
5073 if (!check_fsp(conn, req, fsp)) {
5074 return;
5077 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5078 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5079 fsp->fnum, strerror(errno)));
5080 reply_nterror(req,
5081 map_nt_error_from_unix(errno));
5082 return;
5084 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5085 get_file_infos(fileid, &delete_pending, &write_time_ts);
5088 } else {
5089 char *fname = NULL;
5091 /* qpathinfo */
5092 if (total_params < 7) {
5093 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5094 return;
5097 info_level = SVAL(params,0);
5099 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5101 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5102 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5103 return;
5106 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5107 total_params - 6,
5108 STR_TERMINATE, &status);
5109 if (!NT_STATUS_IS_OK(status)) {
5110 reply_nterror(req, status);
5111 return;
5114 status = filename_convert(req,
5115 conn,
5116 req->flags2 & FLAGS2_DFS_PATHNAMES,
5117 fname,
5119 NULL,
5120 &smb_fname);
5121 if (!NT_STATUS_IS_OK(status)) {
5122 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5123 reply_botherror(req,
5124 NT_STATUS_PATH_NOT_COVERED,
5125 ERRSRV, ERRbadpath);
5126 return;
5128 reply_nterror(req, status);
5129 return;
5132 /* If this is a stream, check if there is a delete_pending. */
5133 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5134 && is_ntfs_stream_smb_fname(smb_fname)) {
5135 struct smb_filename *smb_fname_base = NULL;
5137 /* Create an smb_filename with stream_name == NULL. */
5138 status =
5139 create_synthetic_smb_fname(talloc_tos(),
5140 smb_fname->base_name,
5141 NULL, NULL,
5142 &smb_fname_base);
5143 if (!NT_STATUS_IS_OK(status)) {
5144 reply_nterror(req, status);
5145 return;
5148 if (INFO_LEVEL_IS_UNIX(info_level)) {
5149 /* Always do lstat for UNIX calls. */
5150 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5151 DEBUG(3,("call_trans2qfilepathinfo: "
5152 "SMB_VFS_LSTAT of %s failed "
5153 "(%s)\n",
5154 smb_fname_str_dbg(smb_fname_base),
5155 strerror(errno)));
5156 TALLOC_FREE(smb_fname_base);
5157 reply_nterror(req,
5158 map_nt_error_from_unix(errno));
5159 return;
5161 } else {
5162 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5163 DEBUG(3,("call_trans2qfilepathinfo: "
5164 "fileinfo of %s failed "
5165 "(%s)\n",
5166 smb_fname_str_dbg(smb_fname_base),
5167 strerror(errno)));
5168 TALLOC_FREE(smb_fname_base);
5169 reply_nterror(req,
5170 map_nt_error_from_unix(errno));
5171 return;
5175 fileid = vfs_file_id_from_sbuf(conn,
5176 &smb_fname_base->st);
5177 TALLOC_FREE(smb_fname_base);
5178 get_file_infos(fileid, &delete_pending, NULL);
5179 if (delete_pending) {
5180 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5181 return;
5185 if (INFO_LEVEL_IS_UNIX(info_level)) {
5186 /* Always do lstat for UNIX calls. */
5187 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5188 DEBUG(3,("call_trans2qfilepathinfo: "
5189 "SMB_VFS_LSTAT of %s failed (%s)\n",
5190 smb_fname_str_dbg(smb_fname),
5191 strerror(errno)));
5192 reply_nterror(req,
5193 map_nt_error_from_unix(errno));
5194 return;
5197 } else if (!VALID_STAT(smb_fname->st) &&
5198 SMB_VFS_STAT(conn, smb_fname) &&
5199 (info_level != SMB_INFO_IS_NAME_VALID)) {
5200 ms_dfs_link = check_msdfs_link(conn,
5201 smb_fname->base_name,
5202 &smb_fname->st);
5204 if (!ms_dfs_link) {
5205 DEBUG(3,("call_trans2qfilepathinfo: "
5206 "SMB_VFS_STAT of %s failed (%s)\n",
5207 smb_fname_str_dbg(smb_fname),
5208 strerror(errno)));
5209 reply_nterror(req,
5210 map_nt_error_from_unix(errno));
5211 return;
5215 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5216 get_file_infos(fileid, &delete_pending, &write_time_ts);
5217 if (delete_pending) {
5218 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5219 return;
5223 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5224 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5225 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5227 /* Pull out any data sent here before we realloc. */
5228 switch (info_level) {
5229 case SMB_INFO_QUERY_EAS_FROM_LIST:
5231 /* Pull any EA list from the data portion. */
5232 uint32 ea_size;
5234 if (total_data < 4) {
5235 reply_nterror(
5236 req, NT_STATUS_INVALID_PARAMETER);
5237 return;
5239 ea_size = IVAL(pdata,0);
5241 if (total_data > 0 && ea_size != total_data) {
5242 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5243 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5244 reply_nterror(
5245 req, NT_STATUS_INVALID_PARAMETER);
5246 return;
5249 if (!lp_ea_support(SNUM(conn))) {
5250 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5251 return;
5254 /* Pull out the list of names. */
5255 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5256 if (!ea_list) {
5257 reply_nterror(
5258 req, NT_STATUS_INVALID_PARAMETER);
5259 return;
5261 break;
5264 case SMB_QUERY_POSIX_LOCK:
5266 if (fsp == NULL || fsp->fh->fd == -1) {
5267 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5268 return;
5271 if (total_data != POSIX_LOCK_DATA_SIZE) {
5272 reply_nterror(
5273 req, NT_STATUS_INVALID_PARAMETER);
5274 return;
5277 /* Copy the lock range data. */
5278 lock_data = (char *)TALLOC_MEMDUP(
5279 req, pdata, total_data);
5280 if (!lock_data) {
5281 reply_nterror(req, NT_STATUS_NO_MEMORY);
5282 return;
5284 lock_data_count = total_data;
5286 default:
5287 break;
5290 *pparams = (char *)SMB_REALLOC(*pparams,2);
5291 if (*pparams == NULL) {
5292 reply_nterror(req, NT_STATUS_NO_MEMORY);
5293 return;
5295 params = *pparams;
5296 SSVAL(params,0,0);
5299 * draft-leach-cifs-v1-spec-02.txt
5300 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5301 * says:
5303 * The requested information is placed in the Data portion of the
5304 * transaction response. For the information levels greater than 0x100,
5305 * the transaction response has 1 parameter word which should be
5306 * ignored by the client.
5308 * However Windows only follows this rule for the IS_NAME_VALID call.
5310 switch (info_level) {
5311 case SMB_INFO_IS_NAME_VALID:
5312 param_size = 0;
5313 break;
5316 if ((info_level & 0xFF00) == 0xFF00) {
5318 * We use levels that start with 0xFF00
5319 * internally to represent SMB2 specific levels
5321 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5322 return;
5325 status = smbd_do_qfilepathinfo(conn, req, info_level,
5326 fsp, smb_fname,
5327 delete_pending, write_time_ts,
5328 ms_dfs_link, ea_list,
5329 lock_data_count, lock_data,
5330 req->flags2, max_data_bytes,
5331 ppdata, &data_size);
5332 if (!NT_STATUS_IS_OK(status)) {
5333 reply_nterror(req, status);
5334 return;
5337 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5338 max_data_bytes);
5340 return;
5343 /****************************************************************************
5344 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5345 code.
5346 ****************************************************************************/
5348 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5349 connection_struct *conn,
5350 const struct smb_filename *smb_fname_old,
5351 const struct smb_filename *smb_fname_new)
5353 NTSTATUS status = NT_STATUS_OK;
5355 /* source must already exist. */
5356 if (!VALID_STAT(smb_fname_old->st)) {
5357 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5360 /* Disallow if newname already exists. */
5361 if (VALID_STAT(smb_fname_new->st)) {
5362 return NT_STATUS_OBJECT_NAME_COLLISION;
5365 /* No links from a directory. */
5366 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5367 return NT_STATUS_FILE_IS_A_DIRECTORY;
5370 /* Setting a hardlink to/from a stream isn't currently supported. */
5371 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5372 is_ntfs_stream_smb_fname(smb_fname_new)) {
5373 return NT_STATUS_INVALID_PARAMETER;
5376 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5377 smb_fname_old->base_name, smb_fname_new->base_name));
5379 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5380 smb_fname_new->base_name) != 0) {
5381 status = map_nt_error_from_unix(errno);
5382 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5383 nt_errstr(status), smb_fname_old->base_name,
5384 smb_fname_new->base_name));
5386 return status;
5389 /****************************************************************************
5390 Deal with setting the time from any of the setfilepathinfo functions.
5391 ****************************************************************************/
5393 NTSTATUS smb_set_file_time(connection_struct *conn,
5394 files_struct *fsp,
5395 const struct smb_filename *smb_fname,
5396 struct smb_file_time *ft,
5397 bool setting_write_time)
5399 struct smb_filename smb_fname_base;
5400 uint32 action =
5401 FILE_NOTIFY_CHANGE_LAST_ACCESS
5402 |FILE_NOTIFY_CHANGE_LAST_WRITE
5403 |FILE_NOTIFY_CHANGE_CREATION;
5405 if (!VALID_STAT(smb_fname->st)) {
5406 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5409 /* get some defaults (no modifications) if any info is zero or -1. */
5410 if (null_timespec(ft->create_time)) {
5411 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5414 if (null_timespec(ft->atime)) {
5415 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5418 if (null_timespec(ft->mtime)) {
5419 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5422 if (!setting_write_time) {
5423 /* ft->mtime comes from change time, not write time. */
5424 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5427 /* Ensure the resolution is the correct for
5428 * what we can store on this filesystem. */
5430 round_timespec(conn->ts_res, &ft->create_time);
5431 round_timespec(conn->ts_res, &ft->ctime);
5432 round_timespec(conn->ts_res, &ft->atime);
5433 round_timespec(conn->ts_res, &ft->mtime);
5435 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5436 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5437 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5438 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5439 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5440 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5441 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5442 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5444 if (setting_write_time) {
5446 * This was a Windows setfileinfo on an open file.
5447 * NT does this a lot. We also need to
5448 * set the time here, as it can be read by
5449 * FindFirst/FindNext and with the patch for bug #2045
5450 * in smbd/fileio.c it ensures that this timestamp is
5451 * kept sticky even after a write. We save the request
5452 * away and will set it on file close and after a write. JRA.
5455 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5456 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5458 if (fsp != NULL) {
5459 if (fsp->base_fsp) {
5460 set_sticky_write_time_fsp(fsp->base_fsp,
5461 ft->mtime);
5462 } else {
5463 set_sticky_write_time_fsp(fsp, ft->mtime);
5465 } else {
5466 set_sticky_write_time_path(
5467 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5468 ft->mtime);
5472 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5474 /* Always call ntimes on the base, even if a stream was passed in. */
5475 smb_fname_base = *smb_fname;
5476 smb_fname_base.stream_name = NULL;
5478 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5479 return map_nt_error_from_unix(errno);
5482 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5483 smb_fname->base_name);
5484 return NT_STATUS_OK;
5487 /****************************************************************************
5488 Deal with setting the dosmode from any of the setfilepathinfo functions.
5489 ****************************************************************************/
5491 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5492 const struct smb_filename *smb_fname,
5493 uint32 dosmode)
5495 struct smb_filename *smb_fname_base = NULL;
5496 NTSTATUS status;
5498 if (!VALID_STAT(smb_fname->st)) {
5499 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5502 /* Always operate on the base_name, even if a stream was passed in. */
5503 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5504 NULL, &smb_fname->st,
5505 &smb_fname_base);
5506 if (!NT_STATUS_IS_OK(status)) {
5507 return status;
5510 if (dosmode) {
5511 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5512 dosmode |= aDIR;
5513 } else {
5514 dosmode &= ~aDIR;
5518 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5520 /* check the mode isn't different, before changing it */
5521 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5522 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5523 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5524 (unsigned int)dosmode));
5526 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5527 false)) {
5528 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5529 "%s failed (%s)\n",
5530 smb_fname_str_dbg(smb_fname_base),
5531 strerror(errno)));
5532 status = map_nt_error_from_unix(errno);
5533 goto out;
5536 status = NT_STATUS_OK;
5537 out:
5538 TALLOC_FREE(smb_fname_base);
5539 return status;
5542 /****************************************************************************
5543 Deal with setting the size from any of the setfilepathinfo functions.
5544 ****************************************************************************/
5546 static NTSTATUS smb_set_file_size(connection_struct *conn,
5547 struct smb_request *req,
5548 files_struct *fsp,
5549 const struct smb_filename *smb_fname,
5550 const SMB_STRUCT_STAT *psbuf,
5551 SMB_OFF_T size,
5552 bool fail_after_createfile)
5554 NTSTATUS status = NT_STATUS_OK;
5555 struct smb_filename *smb_fname_tmp = NULL;
5556 files_struct *new_fsp = NULL;
5558 if (!VALID_STAT(*psbuf)) {
5559 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5562 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5564 if (size == get_file_size_stat(psbuf)) {
5565 return NT_STATUS_OK;
5568 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5569 smb_fname_str_dbg(smb_fname), (double)size));
5571 if (fsp && fsp->fh->fd != -1) {
5572 /* Handle based call. */
5573 if (vfs_set_filelen(fsp, size) == -1) {
5574 return map_nt_error_from_unix(errno);
5576 trigger_write_time_update_immediate(fsp);
5577 return NT_STATUS_OK;
5580 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5581 if (!NT_STATUS_IS_OK(status)) {
5582 return status;
5585 smb_fname_tmp->st = *psbuf;
5587 status = SMB_VFS_CREATE_FILE(
5588 conn, /* conn */
5589 req, /* req */
5590 0, /* root_dir_fid */
5591 smb_fname_tmp, /* fname */
5592 FILE_WRITE_ATTRIBUTES, /* access_mask */
5593 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5594 FILE_SHARE_DELETE),
5595 FILE_OPEN, /* create_disposition*/
5596 0, /* create_options */
5597 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5598 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5599 0, /* allocation_size */
5600 NULL, /* sd */
5601 NULL, /* ea_list */
5602 &new_fsp, /* result */
5603 NULL); /* pinfo */
5605 TALLOC_FREE(smb_fname_tmp);
5607 if (!NT_STATUS_IS_OK(status)) {
5608 /* NB. We check for open_was_deferred in the caller. */
5609 return status;
5612 /* See RAW-SFILEINFO-END-OF-FILE */
5613 if (fail_after_createfile) {
5614 close_file(req, new_fsp,NORMAL_CLOSE);
5615 return NT_STATUS_INVALID_LEVEL;
5618 if (vfs_set_filelen(new_fsp, size) == -1) {
5619 status = map_nt_error_from_unix(errno);
5620 close_file(req, new_fsp,NORMAL_CLOSE);
5621 return status;
5624 trigger_write_time_update_immediate(new_fsp);
5625 close_file(req, new_fsp,NORMAL_CLOSE);
5626 return NT_STATUS_OK;
5629 /****************************************************************************
5630 Deal with SMB_INFO_SET_EA.
5631 ****************************************************************************/
5633 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5634 const char *pdata,
5635 int total_data,
5636 files_struct *fsp,
5637 const struct smb_filename *smb_fname)
5639 struct ea_list *ea_list = NULL;
5640 TALLOC_CTX *ctx = NULL;
5641 NTSTATUS status = NT_STATUS_OK;
5643 if (total_data < 10) {
5645 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5646 length. They seem to have no effect. Bug #3212. JRA */
5648 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5649 /* We're done. We only get EA info in this call. */
5650 return NT_STATUS_OK;
5653 return NT_STATUS_INVALID_PARAMETER;
5656 if (IVAL(pdata,0) > total_data) {
5657 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5658 IVAL(pdata,0), (unsigned int)total_data));
5659 return NT_STATUS_INVALID_PARAMETER;
5662 ctx = talloc_tos();
5663 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5664 if (!ea_list) {
5665 return NT_STATUS_INVALID_PARAMETER;
5667 status = set_ea(conn, fsp, smb_fname, ea_list);
5669 return status;
5672 /****************************************************************************
5673 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5674 ****************************************************************************/
5676 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5677 const char *pdata,
5678 int total_data,
5679 files_struct *fsp)
5681 struct ea_list *ea_list = NULL;
5682 NTSTATUS status;
5684 if (!fsp) {
5685 return NT_STATUS_INVALID_HANDLE;
5688 if (!lp_ea_support(SNUM(conn))) {
5689 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5690 "EA's not supported.\n",
5691 (unsigned int)total_data));
5692 return NT_STATUS_EAS_NOT_SUPPORTED;
5695 if (total_data < 10) {
5696 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5697 "too small.\n",
5698 (unsigned int)total_data));
5699 return NT_STATUS_INVALID_PARAMETER;
5702 ea_list = read_nttrans_ea_list(talloc_tos(),
5703 pdata,
5704 total_data);
5706 if (!ea_list) {
5707 return NT_STATUS_INVALID_PARAMETER;
5709 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5711 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5712 smb_fname_str_dbg(fsp->fsp_name),
5713 nt_errstr(status) ));
5715 return status;
5719 /****************************************************************************
5720 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5721 ****************************************************************************/
5723 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5724 const char *pdata,
5725 int total_data,
5726 files_struct *fsp,
5727 struct smb_filename *smb_fname)
5729 NTSTATUS status = NT_STATUS_OK;
5730 bool delete_on_close;
5731 uint32 dosmode = 0;
5733 if (total_data < 1) {
5734 return NT_STATUS_INVALID_PARAMETER;
5737 if (fsp == NULL) {
5738 return NT_STATUS_INVALID_HANDLE;
5741 delete_on_close = (CVAL(pdata,0) ? True : False);
5742 dosmode = dos_mode(conn, smb_fname);
5744 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5745 "delete_on_close = %u\n",
5746 smb_fname_str_dbg(smb_fname),
5747 (unsigned int)dosmode,
5748 (unsigned int)delete_on_close ));
5750 if (delete_on_close) {
5751 status = can_set_delete_on_close(fsp, dosmode);
5752 if (!NT_STATUS_IS_OK(status)) {
5753 return status;
5757 /* The set is across all open files on this dev/inode pair. */
5758 if (!set_delete_on_close(fsp, delete_on_close,
5759 &conn->server_info->utok)) {
5760 return NT_STATUS_ACCESS_DENIED;
5762 return NT_STATUS_OK;
5765 /****************************************************************************
5766 Deal with SMB_FILE_POSITION_INFORMATION.
5767 ****************************************************************************/
5769 static NTSTATUS smb_file_position_information(connection_struct *conn,
5770 const char *pdata,
5771 int total_data,
5772 files_struct *fsp)
5774 uint64_t position_information;
5776 if (total_data < 8) {
5777 return NT_STATUS_INVALID_PARAMETER;
5780 if (fsp == NULL) {
5781 /* Ignore on pathname based set. */
5782 return NT_STATUS_OK;
5785 position_information = (uint64_t)IVAL(pdata,0);
5786 #ifdef LARGE_SMB_OFF_T
5787 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5788 #else /* LARGE_SMB_OFF_T */
5789 if (IVAL(pdata,4) != 0) {
5790 /* more than 32 bits? */
5791 return NT_STATUS_INVALID_PARAMETER;
5793 #endif /* LARGE_SMB_OFF_T */
5795 DEBUG(10,("smb_file_position_information: Set file position "
5796 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5797 (double)position_information));
5798 fsp->fh->position_information = position_information;
5799 return NT_STATUS_OK;
5802 /****************************************************************************
5803 Deal with SMB_FILE_MODE_INFORMATION.
5804 ****************************************************************************/
5806 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5807 const char *pdata,
5808 int total_data)
5810 uint32 mode;
5812 if (total_data < 4) {
5813 return NT_STATUS_INVALID_PARAMETER;
5815 mode = IVAL(pdata,0);
5816 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5817 return NT_STATUS_INVALID_PARAMETER;
5819 return NT_STATUS_OK;
5822 /****************************************************************************
5823 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5824 ****************************************************************************/
5826 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5827 struct smb_request *req,
5828 const char *pdata,
5829 int total_data,
5830 const struct smb_filename *smb_fname)
5832 char *link_target = NULL;
5833 const char *newname = smb_fname->base_name;
5834 TALLOC_CTX *ctx = talloc_tos();
5836 /* Set a symbolic link. */
5837 /* Don't allow this if follow links is false. */
5839 if (total_data == 0) {
5840 return NT_STATUS_INVALID_PARAMETER;
5843 if (!lp_symlinks(SNUM(conn))) {
5844 return NT_STATUS_ACCESS_DENIED;
5847 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5848 total_data, STR_TERMINATE);
5850 if (!link_target) {
5851 return NT_STATUS_INVALID_PARAMETER;
5854 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5855 newname, link_target ));
5857 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5858 return map_nt_error_from_unix(errno);
5861 return NT_STATUS_OK;
5864 /****************************************************************************
5865 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5866 ****************************************************************************/
5868 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5869 struct smb_request *req,
5870 const char *pdata, int total_data,
5871 const struct smb_filename *smb_fname_new)
5873 char *oldname = NULL;
5874 struct smb_filename *smb_fname_old = NULL;
5875 TALLOC_CTX *ctx = talloc_tos();
5876 NTSTATUS status = NT_STATUS_OK;
5878 /* Set a hard link. */
5879 if (total_data == 0) {
5880 return NT_STATUS_INVALID_PARAMETER;
5883 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5884 total_data, STR_TERMINATE, &status);
5885 if (!NT_STATUS_IS_OK(status)) {
5886 return status;
5889 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5890 smb_fname_str_dbg(smb_fname_new), oldname));
5892 status = filename_convert(ctx,
5893 conn,
5894 req->flags2 & FLAGS2_DFS_PATHNAMES,
5895 oldname,
5897 NULL,
5898 &smb_fname_old);
5899 if (!NT_STATUS_IS_OK(status)) {
5900 return status;
5903 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5906 /****************************************************************************
5907 Deal with SMB_FILE_RENAME_INFORMATION.
5908 ****************************************************************************/
5910 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5911 struct smb_request *req,
5912 const char *pdata,
5913 int total_data,
5914 files_struct *fsp,
5915 struct smb_filename *smb_fname_src)
5917 bool overwrite;
5918 uint32 root_fid;
5919 uint32 len;
5920 char *newname = NULL;
5921 struct smb_filename *smb_fname_dst = NULL;
5922 bool dest_has_wcard = False;
5923 NTSTATUS status = NT_STATUS_OK;
5924 char *p;
5925 TALLOC_CTX *ctx = talloc_tos();
5927 if (total_data < 13) {
5928 return NT_STATUS_INVALID_PARAMETER;
5931 overwrite = (CVAL(pdata,0) ? True : False);
5932 root_fid = IVAL(pdata,4);
5933 len = IVAL(pdata,8);
5935 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5936 return NT_STATUS_INVALID_PARAMETER;
5939 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5940 len, 0, &status,
5941 &dest_has_wcard);
5942 if (!NT_STATUS_IS_OK(status)) {
5943 return status;
5946 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5947 newname));
5949 status = resolve_dfspath_wcard(ctx, conn,
5950 req->flags2 & FLAGS2_DFS_PATHNAMES,
5951 newname,
5952 true,
5953 &newname,
5954 &dest_has_wcard);
5955 if (!NT_STATUS_IS_OK(status)) {
5956 return status;
5959 /* Check the new name has no '/' characters. */
5960 if (strchr_m(newname, '/')) {
5961 return NT_STATUS_NOT_SUPPORTED;
5964 if (fsp && fsp->base_fsp) {
5965 /* newname must be a stream name. */
5966 if (newname[0] != ':') {
5967 return NT_STATUS_NOT_SUPPORTED;
5970 /* Create an smb_fname to call rename_internals_fsp() with. */
5971 status = create_synthetic_smb_fname(talloc_tos(),
5972 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5973 &smb_fname_dst);
5974 if (!NT_STATUS_IS_OK(status)) {
5975 goto out;
5979 * Set the original last component, since
5980 * rename_internals_fsp() requires it.
5982 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5983 newname);
5984 if (smb_fname_dst->original_lcomp == NULL) {
5985 status = NT_STATUS_NO_MEMORY;
5986 goto out;
5989 } else {
5991 * Build up an smb_fname_dst based on the filename passed in.
5992 * We basically just strip off the last component, and put on
5993 * the newname instead.
5995 char *base_name = NULL;
5997 /* newname must *not* be a stream name. */
5998 if (newname[0] == ':') {
5999 return NT_STATUS_NOT_SUPPORTED;
6003 * Strip off the last component (filename) of the path passed
6004 * in.
6006 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6007 if (!base_name) {
6008 return NT_STATUS_NO_MEMORY;
6010 p = strrchr_m(base_name, '/');
6011 if (p) {
6012 p[1] = '\0';
6013 } else {
6014 base_name = talloc_strdup(ctx, "./");
6015 if (!base_name) {
6016 return NT_STATUS_NO_MEMORY;
6019 /* Append the new name. */
6020 base_name = talloc_asprintf_append(base_name,
6021 "%s",
6022 newname);
6023 if (!base_name) {
6024 return NT_STATUS_NO_MEMORY;
6027 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6028 (UCF_SAVE_LCOMP |
6029 (dest_has_wcard ?
6030 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6031 0)));
6033 /* If an error we expect this to be
6034 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6036 if (!NT_STATUS_IS_OK(status)) {
6037 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6038 status)) {
6039 goto out;
6041 /* Create an smb_fname to call rename_internals_fsp() */
6042 status = create_synthetic_smb_fname(ctx,
6043 base_name, NULL,
6044 NULL,
6045 &smb_fname_dst);
6046 if (!NT_STATUS_IS_OK(status)) {
6047 goto out;
6052 if (fsp) {
6053 DEBUG(10,("smb_file_rename_information: "
6054 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6055 fsp->fnum, fsp_str_dbg(fsp),
6056 smb_fname_str_dbg(smb_fname_dst)));
6057 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6058 overwrite);
6059 } else {
6060 DEBUG(10,("smb_file_rename_information: "
6061 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6062 smb_fname_str_dbg(smb_fname_src),
6063 smb_fname_str_dbg(smb_fname_dst)));
6064 status = rename_internals(ctx, conn, req, smb_fname_src,
6065 smb_fname_dst, 0, overwrite, false,
6066 dest_has_wcard,
6067 FILE_WRITE_ATTRIBUTES);
6069 out:
6070 TALLOC_FREE(smb_fname_dst);
6071 return status;
6074 /****************************************************************************
6075 Deal with SMB_SET_POSIX_ACL.
6076 ****************************************************************************/
6078 #if defined(HAVE_POSIX_ACLS)
6079 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6080 const char *pdata,
6081 int total_data,
6082 files_struct *fsp,
6083 const struct smb_filename *smb_fname)
6085 uint16 posix_acl_version;
6086 uint16 num_file_acls;
6087 uint16 num_def_acls;
6088 bool valid_file_acls = True;
6089 bool valid_def_acls = True;
6091 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6092 return NT_STATUS_INVALID_PARAMETER;
6094 posix_acl_version = SVAL(pdata,0);
6095 num_file_acls = SVAL(pdata,2);
6096 num_def_acls = SVAL(pdata,4);
6098 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6099 valid_file_acls = False;
6100 num_file_acls = 0;
6103 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6104 valid_def_acls = False;
6105 num_def_acls = 0;
6108 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6109 return NT_STATUS_INVALID_PARAMETER;
6112 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6113 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6114 return NT_STATUS_INVALID_PARAMETER;
6117 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6118 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6119 (unsigned int)num_file_acls,
6120 (unsigned int)num_def_acls));
6122 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6123 smb_fname->base_name, num_file_acls,
6124 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6125 return map_nt_error_from_unix(errno);
6128 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6129 smb_fname->base_name, &smb_fname->st, num_def_acls,
6130 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6131 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6132 return map_nt_error_from_unix(errno);
6134 return NT_STATUS_OK;
6136 #endif
6138 /****************************************************************************
6139 Deal with SMB_SET_POSIX_LOCK.
6140 ****************************************************************************/
6142 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6143 struct smb_request *req,
6144 const char *pdata,
6145 int total_data,
6146 files_struct *fsp)
6148 uint64_t count;
6149 uint64_t offset;
6150 uint32 lock_pid;
6151 bool blocking_lock = False;
6152 enum brl_type lock_type;
6154 NTSTATUS status = NT_STATUS_OK;
6156 if (fsp == NULL || fsp->fh->fd == -1) {
6157 return NT_STATUS_INVALID_HANDLE;
6160 if (total_data != POSIX_LOCK_DATA_SIZE) {
6161 return NT_STATUS_INVALID_PARAMETER;
6164 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6165 case POSIX_LOCK_TYPE_READ:
6166 lock_type = READ_LOCK;
6167 break;
6168 case POSIX_LOCK_TYPE_WRITE:
6169 /* Return the right POSIX-mappable error code for files opened read-only. */
6170 if (!fsp->can_write) {
6171 return NT_STATUS_INVALID_HANDLE;
6173 lock_type = WRITE_LOCK;
6174 break;
6175 case POSIX_LOCK_TYPE_UNLOCK:
6176 lock_type = UNLOCK_LOCK;
6177 break;
6178 default:
6179 return NT_STATUS_INVALID_PARAMETER;
6182 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6183 blocking_lock = False;
6184 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6185 blocking_lock = True;
6186 } else {
6187 return NT_STATUS_INVALID_PARAMETER;
6190 if (!lp_blocking_locks(SNUM(conn))) {
6191 blocking_lock = False;
6194 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6195 #if defined(HAVE_LONGLONG)
6196 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6197 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6198 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6199 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6200 #else /* HAVE_LONGLONG */
6201 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6202 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6203 #endif /* HAVE_LONGLONG */
6205 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6206 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6207 fsp_str_dbg(fsp),
6208 (unsigned int)lock_type,
6209 (unsigned int)lock_pid,
6210 (double)count,
6211 (double)offset ));
6213 if (lock_type == UNLOCK_LOCK) {
6214 status = do_unlock(smbd_messaging_context(),
6215 fsp,
6216 lock_pid,
6217 count,
6218 offset,
6219 POSIX_LOCK);
6220 } else {
6221 uint32 block_smbpid;
6223 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6224 fsp,
6225 lock_pid,
6226 count,
6227 offset,
6228 lock_type,
6229 POSIX_LOCK,
6230 blocking_lock,
6231 &status,
6232 &block_smbpid,
6233 NULL);
6235 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6237 * A blocking lock was requested. Package up
6238 * this smb into a queued request and push it
6239 * onto the blocking lock queue.
6241 if(push_blocking_lock_request(br_lck,
6242 req,
6243 fsp,
6244 -1, /* infinite timeout. */
6246 lock_pid,
6247 lock_type,
6248 POSIX_LOCK,
6249 offset,
6250 count,
6251 block_smbpid)) {
6252 TALLOC_FREE(br_lck);
6253 return status;
6256 TALLOC_FREE(br_lck);
6259 return status;
6262 /****************************************************************************
6263 Deal with SMB_SET_FILE_BASIC_INFO.
6264 ****************************************************************************/
6266 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6267 const char *pdata,
6268 int total_data,
6269 files_struct *fsp,
6270 const struct smb_filename *smb_fname)
6272 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6273 struct smb_file_time ft;
6274 uint32 dosmode = 0;
6275 NTSTATUS status = NT_STATUS_OK;
6277 ZERO_STRUCT(ft);
6279 if (total_data < 36) {
6280 return NT_STATUS_INVALID_PARAMETER;
6283 /* Set the attributes */
6284 dosmode = IVAL(pdata,32);
6285 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6286 if (!NT_STATUS_IS_OK(status)) {
6287 return status;
6290 /* create time */
6291 ft.create_time = interpret_long_date(pdata);
6293 /* access time */
6294 ft.atime = interpret_long_date(pdata+8);
6296 /* write time. */
6297 ft.mtime = interpret_long_date(pdata+16);
6299 /* change time. */
6300 ft.ctime = interpret_long_date(pdata+24);
6302 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6303 smb_fname_str_dbg(smb_fname)));
6305 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6306 true);
6309 /****************************************************************************
6310 Deal with SMB_INFO_STANDARD.
6311 ****************************************************************************/
6313 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6314 const char *pdata,
6315 int total_data,
6316 files_struct *fsp,
6317 const struct smb_filename *smb_fname)
6319 struct smb_file_time ft;
6321 ZERO_STRUCT(ft);
6323 if (total_data < 12) {
6324 return NT_STATUS_INVALID_PARAMETER;
6327 /* create time */
6328 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6329 /* access time */
6330 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6331 /* write time */
6332 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6334 DEBUG(10,("smb_set_info_standard: file %s\n",
6335 smb_fname_str_dbg(smb_fname)));
6337 return smb_set_file_time(conn,
6338 fsp,
6339 smb_fname,
6340 &ft,
6341 true);
6344 /****************************************************************************
6345 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6346 ****************************************************************************/
6348 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6349 struct smb_request *req,
6350 const char *pdata,
6351 int total_data,
6352 files_struct *fsp,
6353 struct smb_filename *smb_fname)
6355 uint64_t allocation_size = 0;
6356 NTSTATUS status = NT_STATUS_OK;
6357 files_struct *new_fsp = NULL;
6359 if (!VALID_STAT(smb_fname->st)) {
6360 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6363 if (total_data < 8) {
6364 return NT_STATUS_INVALID_PARAMETER;
6367 allocation_size = (uint64_t)IVAL(pdata,0);
6368 #ifdef LARGE_SMB_OFF_T
6369 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6370 #else /* LARGE_SMB_OFF_T */
6371 if (IVAL(pdata,4) != 0) {
6372 /* more than 32 bits? */
6373 return NT_STATUS_INVALID_PARAMETER;
6375 #endif /* LARGE_SMB_OFF_T */
6377 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6378 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6379 (double)allocation_size));
6381 if (allocation_size) {
6382 allocation_size = smb_roundup(conn, allocation_size);
6385 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6386 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6387 (double)allocation_size));
6389 if (fsp && fsp->fh->fd != -1) {
6390 /* Open file handle. */
6391 /* Only change if needed. */
6392 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6393 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6394 return map_nt_error_from_unix(errno);
6397 /* But always update the time. */
6399 * This is equivalent to a write. Ensure it's seen immediately
6400 * if there are no pending writes.
6402 trigger_write_time_update_immediate(fsp);
6403 return NT_STATUS_OK;
6406 /* Pathname or stat or directory file. */
6407 status = SMB_VFS_CREATE_FILE(
6408 conn, /* conn */
6409 req, /* req */
6410 0, /* root_dir_fid */
6411 smb_fname, /* fname */
6412 FILE_WRITE_DATA, /* access_mask */
6413 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6414 FILE_SHARE_DELETE),
6415 FILE_OPEN, /* create_disposition*/
6416 0, /* create_options */
6417 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6418 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6419 0, /* allocation_size */
6420 NULL, /* sd */
6421 NULL, /* ea_list */
6422 &new_fsp, /* result */
6423 NULL); /* pinfo */
6425 if (!NT_STATUS_IS_OK(status)) {
6426 /* NB. We check for open_was_deferred in the caller. */
6427 return status;
6430 /* Only change if needed. */
6431 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6432 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6433 status = map_nt_error_from_unix(errno);
6434 close_file(req, new_fsp, NORMAL_CLOSE);
6435 return status;
6439 /* Changing the allocation size should set the last mod time. */
6441 * This is equivalent to a write. Ensure it's seen immediately
6442 * if there are no pending writes.
6444 trigger_write_time_update_immediate(new_fsp);
6446 close_file(req, new_fsp, NORMAL_CLOSE);
6447 return NT_STATUS_OK;
6450 /****************************************************************************
6451 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6452 ****************************************************************************/
6454 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6455 struct smb_request *req,
6456 const char *pdata,
6457 int total_data,
6458 files_struct *fsp,
6459 const struct smb_filename *smb_fname,
6460 bool fail_after_createfile)
6462 SMB_OFF_T size;
6464 if (total_data < 8) {
6465 return NT_STATUS_INVALID_PARAMETER;
6468 size = IVAL(pdata,0);
6469 #ifdef LARGE_SMB_OFF_T
6470 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6471 #else /* LARGE_SMB_OFF_T */
6472 if (IVAL(pdata,4) != 0) {
6473 /* more than 32 bits? */
6474 return NT_STATUS_INVALID_PARAMETER;
6476 #endif /* LARGE_SMB_OFF_T */
6477 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6478 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6479 (double)size));
6481 return smb_set_file_size(conn, req,
6482 fsp,
6483 smb_fname,
6484 &smb_fname->st,
6485 size,
6486 fail_after_createfile);
6489 /****************************************************************************
6490 Allow a UNIX info mknod.
6491 ****************************************************************************/
6493 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6494 const char *pdata,
6495 int total_data,
6496 const struct smb_filename *smb_fname)
6498 uint32 file_type = IVAL(pdata,56);
6499 #if defined(HAVE_MAKEDEV)
6500 uint32 dev_major = IVAL(pdata,60);
6501 uint32 dev_minor = IVAL(pdata,68);
6502 #endif
6503 SMB_DEV_T dev = (SMB_DEV_T)0;
6504 uint32 raw_unixmode = IVAL(pdata,84);
6505 NTSTATUS status;
6506 mode_t unixmode;
6508 if (total_data < 100) {
6509 return NT_STATUS_INVALID_PARAMETER;
6512 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6513 PERM_NEW_FILE, &unixmode);
6514 if (!NT_STATUS_IS_OK(status)) {
6515 return status;
6518 #if defined(HAVE_MAKEDEV)
6519 dev = makedev(dev_major, dev_minor);
6520 #endif
6522 switch (file_type) {
6523 #if defined(S_IFIFO)
6524 case UNIX_TYPE_FIFO:
6525 unixmode |= S_IFIFO;
6526 break;
6527 #endif
6528 #if defined(S_IFSOCK)
6529 case UNIX_TYPE_SOCKET:
6530 unixmode |= S_IFSOCK;
6531 break;
6532 #endif
6533 #if defined(S_IFCHR)
6534 case UNIX_TYPE_CHARDEV:
6535 unixmode |= S_IFCHR;
6536 break;
6537 #endif
6538 #if defined(S_IFBLK)
6539 case UNIX_TYPE_BLKDEV:
6540 unixmode |= S_IFBLK;
6541 break;
6542 #endif
6543 default:
6544 return NT_STATUS_INVALID_PARAMETER;
6547 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6548 "%.0f mode 0%o for file %s\n", (double)dev,
6549 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6551 /* Ok - do the mknod. */
6552 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6553 return map_nt_error_from_unix(errno);
6556 /* If any of the other "set" calls fail we
6557 * don't want to end up with a half-constructed mknod.
6560 if (lp_inherit_perms(SNUM(conn))) {
6561 char *parent;
6562 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6563 &parent, NULL)) {
6564 return NT_STATUS_NO_MEMORY;
6566 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6567 unixmode);
6568 TALLOC_FREE(parent);
6571 return NT_STATUS_OK;
6574 /****************************************************************************
6575 Deal with SMB_SET_FILE_UNIX_BASIC.
6576 ****************************************************************************/
6578 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6579 struct smb_request *req,
6580 const char *pdata,
6581 int total_data,
6582 files_struct *fsp,
6583 const struct smb_filename *smb_fname)
6585 struct smb_file_time ft;
6586 uint32 raw_unixmode;
6587 mode_t unixmode;
6588 SMB_OFF_T size = 0;
6589 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6590 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6591 NTSTATUS status = NT_STATUS_OK;
6592 bool delete_on_fail = False;
6593 enum perm_type ptype;
6594 files_struct *all_fsps = NULL;
6595 bool modify_mtime = true;
6596 struct file_id id;
6597 struct smb_filename *smb_fname_tmp = NULL;
6598 SMB_STRUCT_STAT sbuf;
6600 ZERO_STRUCT(ft);
6602 if (total_data < 100) {
6603 return NT_STATUS_INVALID_PARAMETER;
6606 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6607 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6608 size=IVAL(pdata,0); /* first 8 Bytes are size */
6609 #ifdef LARGE_SMB_OFF_T
6610 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6611 #else /* LARGE_SMB_OFF_T */
6612 if (IVAL(pdata,4) != 0) {
6613 /* more than 32 bits? */
6614 return NT_STATUS_INVALID_PARAMETER;
6616 #endif /* LARGE_SMB_OFF_T */
6619 ft.atime = interpret_long_date(pdata+24); /* access_time */
6620 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6621 set_owner = (uid_t)IVAL(pdata,40);
6622 set_grp = (gid_t)IVAL(pdata,48);
6623 raw_unixmode = IVAL(pdata,84);
6625 if (VALID_STAT(smb_fname->st)) {
6626 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6627 ptype = PERM_EXISTING_DIR;
6628 } else {
6629 ptype = PERM_EXISTING_FILE;
6631 } else {
6632 ptype = PERM_NEW_FILE;
6635 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6636 ptype, &unixmode);
6637 if (!NT_STATUS_IS_OK(status)) {
6638 return status;
6641 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6642 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6643 smb_fname_str_dbg(smb_fname), (double)size,
6644 (unsigned int)set_owner, (unsigned int)set_grp,
6645 (int)raw_unixmode));
6647 sbuf = smb_fname->st;
6649 if (!VALID_STAT(sbuf)) {
6651 * The only valid use of this is to create character and block
6652 * devices, and named pipes. This is deprecated (IMHO) and
6653 * a new info level should be used for mknod. JRA.
6656 status = smb_unix_mknod(conn,
6657 pdata,
6658 total_data,
6659 smb_fname);
6660 if (!NT_STATUS_IS_OK(status)) {
6661 return status;
6664 status = copy_smb_filename(talloc_tos(), smb_fname,
6665 &smb_fname_tmp);
6666 if (!NT_STATUS_IS_OK(status)) {
6667 return status;
6670 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6671 status = map_nt_error_from_unix(errno);
6672 TALLOC_FREE(smb_fname_tmp);
6673 SMB_VFS_UNLINK(conn, smb_fname);
6674 return status;
6677 sbuf = smb_fname_tmp->st;
6678 smb_fname = smb_fname_tmp;
6680 /* Ensure we don't try and change anything else. */
6681 raw_unixmode = SMB_MODE_NO_CHANGE;
6682 size = get_file_size_stat(&sbuf);
6683 ft.atime = sbuf.st_ex_atime;
6684 ft.mtime = sbuf.st_ex_mtime;
6686 * We continue here as we might want to change the
6687 * owner uid/gid.
6689 delete_on_fail = True;
6692 #if 1
6693 /* Horrible backwards compatibility hack as an old server bug
6694 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6695 * */
6697 if (!size) {
6698 size = get_file_size_stat(&sbuf);
6700 #endif
6703 * Deal with the UNIX specific mode set.
6706 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6707 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6708 "setting mode 0%o for file %s\n",
6709 (unsigned int)unixmode,
6710 smb_fname_str_dbg(smb_fname)));
6711 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6712 return map_nt_error_from_unix(errno);
6717 * Deal with the UNIX specific uid set.
6720 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6721 (sbuf.st_ex_uid != set_owner)) {
6722 int ret;
6724 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6725 "changing owner %u for path %s\n",
6726 (unsigned int)set_owner,
6727 smb_fname_str_dbg(smb_fname)));
6729 if (S_ISLNK(sbuf.st_ex_mode)) {
6730 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6731 set_owner, (gid_t)-1);
6732 } else {
6733 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6734 set_owner, (gid_t)-1);
6737 if (ret != 0) {
6738 status = map_nt_error_from_unix(errno);
6739 if (delete_on_fail) {
6740 SMB_VFS_UNLINK(conn, smb_fname);
6742 return status;
6747 * Deal with the UNIX specific gid set.
6750 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6751 (sbuf.st_ex_gid != set_grp)) {
6752 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6753 "changing group %u for file %s\n",
6754 (unsigned int)set_owner,
6755 smb_fname_str_dbg(smb_fname)));
6756 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6757 set_grp) != 0) {
6758 status = map_nt_error_from_unix(errno);
6759 if (delete_on_fail) {
6760 SMB_VFS_UNLINK(conn, smb_fname);
6762 return status;
6766 /* Deal with any size changes. */
6768 status = smb_set_file_size(conn, req,
6769 fsp,
6770 smb_fname,
6771 &sbuf,
6772 size,
6773 false);
6774 if (!NT_STATUS_IS_OK(status)) {
6775 return status;
6778 /* Deal with any time changes. */
6779 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6780 /* No change, don't cancel anything. */
6781 return status;
6784 id = vfs_file_id_from_sbuf(conn, &sbuf);
6785 for(all_fsps = file_find_di_first(id); all_fsps;
6786 all_fsps = file_find_di_next(all_fsps)) {
6788 * We're setting the time explicitly for UNIX.
6789 * Cancel any pending changes over all handles.
6791 all_fsps->update_write_time_on_close = false;
6792 TALLOC_FREE(all_fsps->update_write_time_event);
6796 * Override the "setting_write_time"
6797 * parameter here as it almost does what
6798 * we need. Just remember if we modified
6799 * mtime and send the notify ourselves.
6801 if (null_timespec(ft.mtime)) {
6802 modify_mtime = false;
6805 status = smb_set_file_time(conn,
6806 fsp,
6807 smb_fname,
6808 &ft,
6809 false);
6810 if (modify_mtime) {
6811 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6812 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6814 return status;
6817 /****************************************************************************
6818 Deal with SMB_SET_FILE_UNIX_INFO2.
6819 ****************************************************************************/
6821 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6822 struct smb_request *req,
6823 const char *pdata,
6824 int total_data,
6825 files_struct *fsp,
6826 const struct smb_filename *smb_fname)
6828 NTSTATUS status;
6829 uint32 smb_fflags;
6830 uint32 smb_fmask;
6832 if (total_data < 116) {
6833 return NT_STATUS_INVALID_PARAMETER;
6836 /* Start by setting all the fields that are common between UNIX_BASIC
6837 * and UNIX_INFO2.
6839 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6840 fsp, smb_fname);
6841 if (!NT_STATUS_IS_OK(status)) {
6842 return status;
6845 smb_fflags = IVAL(pdata, 108);
6846 smb_fmask = IVAL(pdata, 112);
6848 /* NB: We should only attempt to alter the file flags if the client
6849 * sends a non-zero mask.
6851 if (smb_fmask != 0) {
6852 int stat_fflags = 0;
6854 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6855 smb_fmask, &stat_fflags)) {
6856 /* Client asked to alter a flag we don't understand. */
6857 return NT_STATUS_INVALID_PARAMETER;
6860 if (fsp && fsp->fh->fd != -1) {
6861 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6862 return NT_STATUS_NOT_SUPPORTED;
6863 } else {
6864 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6865 stat_fflags) != 0) {
6866 return map_nt_error_from_unix(errno);
6871 /* XXX: need to add support for changing the create_time here. You
6872 * can do this for paths on Darwin with setattrlist(2). The right way
6873 * to hook this up is probably by extending the VFS utimes interface.
6876 return NT_STATUS_OK;
6879 /****************************************************************************
6880 Create a directory with POSIX semantics.
6881 ****************************************************************************/
6883 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6884 struct smb_request *req,
6885 char **ppdata,
6886 int total_data,
6887 struct smb_filename *smb_fname,
6888 int *pdata_return_size)
6890 NTSTATUS status = NT_STATUS_OK;
6891 uint32 raw_unixmode = 0;
6892 uint32 mod_unixmode = 0;
6893 mode_t unixmode = (mode_t)0;
6894 files_struct *fsp = NULL;
6895 uint16 info_level_return = 0;
6896 int info;
6897 char *pdata = *ppdata;
6899 if (total_data < 18) {
6900 return NT_STATUS_INVALID_PARAMETER;
6903 raw_unixmode = IVAL(pdata,8);
6904 /* Next 4 bytes are not yet defined. */
6906 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6907 PERM_NEW_DIR, &unixmode);
6908 if (!NT_STATUS_IS_OK(status)) {
6909 return status;
6912 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6914 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6915 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6917 status = SMB_VFS_CREATE_FILE(
6918 conn, /* conn */
6919 req, /* req */
6920 0, /* root_dir_fid */
6921 smb_fname, /* fname */
6922 FILE_READ_ATTRIBUTES, /* access_mask */
6923 FILE_SHARE_NONE, /* share_access */
6924 FILE_CREATE, /* create_disposition*/
6925 FILE_DIRECTORY_FILE, /* create_options */
6926 mod_unixmode, /* file_attributes */
6927 0, /* oplock_request */
6928 0, /* allocation_size */
6929 NULL, /* sd */
6930 NULL, /* ea_list */
6931 &fsp, /* result */
6932 &info); /* pinfo */
6934 if (NT_STATUS_IS_OK(status)) {
6935 close_file(req, fsp, NORMAL_CLOSE);
6938 info_level_return = SVAL(pdata,16);
6940 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6941 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6942 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6943 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6944 } else {
6945 *pdata_return_size = 12;
6948 /* Realloc the data size */
6949 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6950 if (*ppdata == NULL) {
6951 *pdata_return_size = 0;
6952 return NT_STATUS_NO_MEMORY;
6954 pdata = *ppdata;
6956 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6957 SSVAL(pdata,2,0); /* No fnum. */
6958 SIVAL(pdata,4,info); /* Was directory created. */
6960 switch (info_level_return) {
6961 case SMB_QUERY_FILE_UNIX_BASIC:
6962 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6963 SSVAL(pdata,10,0); /* Padding. */
6964 store_file_unix_basic(conn, pdata + 12, fsp,
6965 &smb_fname->st);
6966 break;
6967 case SMB_QUERY_FILE_UNIX_INFO2:
6968 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6969 SSVAL(pdata,10,0); /* Padding. */
6970 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6971 &smb_fname->st);
6972 break;
6973 default:
6974 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6975 SSVAL(pdata,10,0); /* Padding. */
6976 break;
6979 return status;
6982 /****************************************************************************
6983 Open/Create a file with POSIX semantics.
6984 ****************************************************************************/
6986 static NTSTATUS smb_posix_open(connection_struct *conn,
6987 struct smb_request *req,
6988 char **ppdata,
6989 int total_data,
6990 struct smb_filename *smb_fname,
6991 int *pdata_return_size)
6993 bool extended_oplock_granted = False;
6994 char *pdata = *ppdata;
6995 uint32 flags = 0;
6996 uint32 wire_open_mode = 0;
6997 uint32 raw_unixmode = 0;
6998 uint32 mod_unixmode = 0;
6999 uint32 create_disp = 0;
7000 uint32 access_mask = 0;
7001 uint32 create_options = 0;
7002 NTSTATUS status = NT_STATUS_OK;
7003 mode_t unixmode = (mode_t)0;
7004 files_struct *fsp = NULL;
7005 int oplock_request = 0;
7006 int info = 0;
7007 uint16 info_level_return = 0;
7009 if (total_data < 18) {
7010 return NT_STATUS_INVALID_PARAMETER;
7013 flags = IVAL(pdata,0);
7014 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7015 if (oplock_request) {
7016 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7019 wire_open_mode = IVAL(pdata,4);
7021 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7022 return smb_posix_mkdir(conn, req,
7023 ppdata,
7024 total_data,
7025 smb_fname,
7026 pdata_return_size);
7029 switch (wire_open_mode & SMB_ACCMODE) {
7030 case SMB_O_RDONLY:
7031 access_mask = FILE_READ_DATA;
7032 break;
7033 case SMB_O_WRONLY:
7034 access_mask = FILE_WRITE_DATA;
7035 break;
7036 case SMB_O_RDWR:
7037 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7038 break;
7039 default:
7040 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7041 (unsigned int)wire_open_mode ));
7042 return NT_STATUS_INVALID_PARAMETER;
7045 wire_open_mode &= ~SMB_ACCMODE;
7047 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7048 create_disp = FILE_CREATE;
7049 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7050 create_disp = FILE_OVERWRITE_IF;
7051 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7052 create_disp = FILE_OPEN_IF;
7053 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7054 create_disp = FILE_OPEN;
7055 } else {
7056 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7057 (unsigned int)wire_open_mode ));
7058 return NT_STATUS_INVALID_PARAMETER;
7061 raw_unixmode = IVAL(pdata,8);
7062 /* Next 4 bytes are not yet defined. */
7064 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7065 (VALID_STAT(smb_fname->st) ?
7066 PERM_EXISTING_FILE : PERM_NEW_FILE),
7067 &unixmode);
7069 if (!NT_STATUS_IS_OK(status)) {
7070 return status;
7073 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7075 if (wire_open_mode & SMB_O_SYNC) {
7076 create_options |= FILE_WRITE_THROUGH;
7078 if (wire_open_mode & SMB_O_APPEND) {
7079 access_mask |= FILE_APPEND_DATA;
7081 if (wire_open_mode & SMB_O_DIRECT) {
7082 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7085 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7086 smb_fname_str_dbg(smb_fname),
7087 (unsigned int)wire_open_mode,
7088 (unsigned int)unixmode ));
7090 status = SMB_VFS_CREATE_FILE(
7091 conn, /* conn */
7092 req, /* req */
7093 0, /* root_dir_fid */
7094 smb_fname, /* fname */
7095 access_mask, /* access_mask */
7096 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7097 FILE_SHARE_DELETE),
7098 create_disp, /* create_disposition*/
7099 FILE_NON_DIRECTORY_FILE, /* create_options */
7100 mod_unixmode, /* file_attributes */
7101 oplock_request, /* oplock_request */
7102 0, /* allocation_size */
7103 NULL, /* sd */
7104 NULL, /* ea_list */
7105 &fsp, /* result */
7106 &info); /* pinfo */
7108 if (!NT_STATUS_IS_OK(status)) {
7109 return status;
7112 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7113 extended_oplock_granted = True;
7116 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7117 extended_oplock_granted = True;
7120 info_level_return = SVAL(pdata,16);
7122 /* Allocate the correct return size. */
7124 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7125 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7126 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7127 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7128 } else {
7129 *pdata_return_size = 12;
7132 /* Realloc the data size */
7133 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7134 if (*ppdata == NULL) {
7135 close_file(req, fsp, ERROR_CLOSE);
7136 *pdata_return_size = 0;
7137 return NT_STATUS_NO_MEMORY;
7139 pdata = *ppdata;
7141 if (extended_oplock_granted) {
7142 if (flags & REQUEST_BATCH_OPLOCK) {
7143 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7144 } else {
7145 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7147 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7148 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7149 } else {
7150 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7153 SSVAL(pdata,2,fsp->fnum);
7154 SIVAL(pdata,4,info); /* Was file created etc. */
7156 switch (info_level_return) {
7157 case SMB_QUERY_FILE_UNIX_BASIC:
7158 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7159 SSVAL(pdata,10,0); /* padding. */
7160 store_file_unix_basic(conn, pdata + 12, fsp,
7161 &smb_fname->st);
7162 break;
7163 case SMB_QUERY_FILE_UNIX_INFO2:
7164 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7165 SSVAL(pdata,10,0); /* padding. */
7166 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7167 &smb_fname->st);
7168 break;
7169 default:
7170 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7171 SSVAL(pdata,10,0); /* padding. */
7172 break;
7174 return NT_STATUS_OK;
7177 /****************************************************************************
7178 Delete a file with POSIX semantics.
7179 ****************************************************************************/
7181 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7182 struct smb_request *req,
7183 const char *pdata,
7184 int total_data,
7185 struct smb_filename *smb_fname)
7187 NTSTATUS status = NT_STATUS_OK;
7188 files_struct *fsp = NULL;
7189 uint16 flags = 0;
7190 char del = 1;
7191 int info = 0;
7192 int create_options = 0;
7193 int i;
7194 struct share_mode_lock *lck = NULL;
7196 if (total_data < 2) {
7197 return NT_STATUS_INVALID_PARAMETER;
7200 flags = SVAL(pdata,0);
7202 if (!VALID_STAT(smb_fname->st)) {
7203 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7206 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7207 !VALID_STAT_OF_DIR(smb_fname->st)) {
7208 return NT_STATUS_NOT_A_DIRECTORY;
7211 DEBUG(10,("smb_posix_unlink: %s %s\n",
7212 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7213 smb_fname_str_dbg(smb_fname)));
7215 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7216 create_options |= FILE_DIRECTORY_FILE;
7219 status = SMB_VFS_CREATE_FILE(
7220 conn, /* conn */
7221 req, /* req */
7222 0, /* root_dir_fid */
7223 smb_fname, /* fname */
7224 DELETE_ACCESS, /* access_mask */
7225 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7226 FILE_SHARE_DELETE),
7227 FILE_OPEN, /* create_disposition*/
7228 create_options, /* create_options */
7229 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7230 0, /* oplock_request */
7231 0, /* allocation_size */
7232 NULL, /* sd */
7233 NULL, /* ea_list */
7234 &fsp, /* result */
7235 &info); /* pinfo */
7237 if (!NT_STATUS_IS_OK(status)) {
7238 return status;
7242 * Don't lie to client. If we can't really delete due to
7243 * non-POSIX opens return SHARING_VIOLATION.
7246 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7247 NULL);
7248 if (lck == NULL) {
7249 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7250 "lock for file %s\n", fsp_str_dbg(fsp)));
7251 close_file(req, fsp, NORMAL_CLOSE);
7252 return NT_STATUS_INVALID_PARAMETER;
7256 * See if others still have the file open. If this is the case, then
7257 * don't delete. If all opens are POSIX delete we can set the delete
7258 * on close disposition.
7260 for (i=0; i<lck->num_share_modes; i++) {
7261 struct share_mode_entry *e = &lck->share_modes[i];
7262 if (is_valid_share_mode_entry(e)) {
7263 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7264 continue;
7266 /* Fail with sharing violation. */
7267 close_file(req, fsp, NORMAL_CLOSE);
7268 TALLOC_FREE(lck);
7269 return NT_STATUS_SHARING_VIOLATION;
7274 * Set the delete on close.
7276 status = smb_set_file_disposition_info(conn,
7277 &del,
7279 fsp,
7280 smb_fname);
7282 if (!NT_STATUS_IS_OK(status)) {
7283 close_file(req, fsp, NORMAL_CLOSE);
7284 TALLOC_FREE(lck);
7285 return status;
7287 TALLOC_FREE(lck);
7288 return close_file(req, fsp, NORMAL_CLOSE);
7291 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7292 struct smb_request *req,
7293 TALLOC_CTX *mem_ctx,
7294 uint16_t info_level,
7295 files_struct *fsp,
7296 struct smb_filename *smb_fname,
7297 char **ppdata, int total_data,
7298 int *ret_data_size)
7300 char *pdata = *ppdata;
7301 NTSTATUS status = NT_STATUS_OK;
7302 int data_return_size = 0;
7304 *ret_data_size = 0;
7306 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7307 return NT_STATUS_INVALID_LEVEL;
7310 if (!CAN_WRITE(conn)) {
7311 /* Allow POSIX opens. The open path will deny
7312 * any non-readonly opens. */
7313 if (info_level != SMB_POSIX_PATH_OPEN) {
7314 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7318 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7319 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7320 fsp ? fsp->fnum : -1, info_level, total_data));
7322 switch (info_level) {
7324 case SMB_INFO_STANDARD:
7326 status = smb_set_info_standard(conn,
7327 pdata,
7328 total_data,
7329 fsp,
7330 smb_fname);
7331 break;
7334 case SMB_INFO_SET_EA:
7336 status = smb_info_set_ea(conn,
7337 pdata,
7338 total_data,
7339 fsp,
7340 smb_fname);
7341 break;
7344 case SMB_SET_FILE_BASIC_INFO:
7345 case SMB_FILE_BASIC_INFORMATION:
7347 status = smb_set_file_basic_info(conn,
7348 pdata,
7349 total_data,
7350 fsp,
7351 smb_fname);
7352 break;
7355 case SMB_FILE_ALLOCATION_INFORMATION:
7356 case SMB_SET_FILE_ALLOCATION_INFO:
7358 status = smb_set_file_allocation_info(conn, req,
7359 pdata,
7360 total_data,
7361 fsp,
7362 smb_fname);
7363 break;
7366 case SMB_FILE_END_OF_FILE_INFORMATION:
7367 case SMB_SET_FILE_END_OF_FILE_INFO:
7370 * XP/Win7 both fail after the createfile with
7371 * SMB_SET_FILE_END_OF_FILE_INFO but not
7372 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7373 * The level is known here, so pass it down
7374 * appropriately.
7376 bool should_fail =
7377 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7379 status = smb_set_file_end_of_file_info(conn, req,
7380 pdata,
7381 total_data,
7382 fsp,
7383 smb_fname,
7384 should_fail);
7385 break;
7388 case SMB_FILE_DISPOSITION_INFORMATION:
7389 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7391 #if 0
7392 /* JRA - We used to just ignore this on a path ?
7393 * Shouldn't this be invalid level on a pathname
7394 * based call ?
7396 if (tran_call != TRANSACT2_SETFILEINFO) {
7397 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7399 #endif
7400 status = smb_set_file_disposition_info(conn,
7401 pdata,
7402 total_data,
7403 fsp,
7404 smb_fname);
7405 break;
7408 case SMB_FILE_POSITION_INFORMATION:
7410 status = smb_file_position_information(conn,
7411 pdata,
7412 total_data,
7413 fsp);
7414 break;
7417 case SMB_FILE_FULL_EA_INFORMATION:
7419 status = smb_set_file_full_ea_info(conn,
7420 pdata,
7421 total_data,
7422 fsp);
7423 break;
7426 /* From tridge Samba4 :
7427 * MODE_INFORMATION in setfileinfo (I have no
7428 * idea what "mode information" on a file is - it takes a value of 0,
7429 * 2, 4 or 6. What could it be?).
7432 case SMB_FILE_MODE_INFORMATION:
7434 status = smb_file_mode_information(conn,
7435 pdata,
7436 total_data);
7437 break;
7441 * CIFS UNIX extensions.
7444 case SMB_SET_FILE_UNIX_BASIC:
7446 status = smb_set_file_unix_basic(conn, req,
7447 pdata,
7448 total_data,
7449 fsp,
7450 smb_fname);
7451 break;
7454 case SMB_SET_FILE_UNIX_INFO2:
7456 status = smb_set_file_unix_info2(conn, req,
7457 pdata,
7458 total_data,
7459 fsp,
7460 smb_fname);
7461 break;
7464 case SMB_SET_FILE_UNIX_LINK:
7466 if (fsp) {
7467 /* We must have a pathname for this. */
7468 return NT_STATUS_INVALID_LEVEL;
7470 status = smb_set_file_unix_link(conn, req, pdata,
7471 total_data, smb_fname);
7472 break;
7475 case SMB_SET_FILE_UNIX_HLINK:
7477 if (fsp) {
7478 /* We must have a pathname for this. */
7479 return NT_STATUS_INVALID_LEVEL;
7481 status = smb_set_file_unix_hlink(conn, req,
7482 pdata, total_data,
7483 smb_fname);
7484 break;
7487 case SMB_FILE_RENAME_INFORMATION:
7489 status = smb_file_rename_information(conn, req,
7490 pdata, total_data,
7491 fsp, smb_fname);
7492 break;
7495 #if defined(HAVE_POSIX_ACLS)
7496 case SMB_SET_POSIX_ACL:
7498 status = smb_set_posix_acl(conn,
7499 pdata,
7500 total_data,
7501 fsp,
7502 smb_fname);
7503 break;
7505 #endif
7507 case SMB_SET_POSIX_LOCK:
7509 if (!fsp) {
7510 return NT_STATUS_INVALID_LEVEL;
7512 status = smb_set_posix_lock(conn, req,
7513 pdata, total_data, fsp);
7514 break;
7517 case SMB_POSIX_PATH_OPEN:
7519 if (fsp) {
7520 /* We must have a pathname for this. */
7521 return NT_STATUS_INVALID_LEVEL;
7524 status = smb_posix_open(conn, req,
7525 ppdata,
7526 total_data,
7527 smb_fname,
7528 &data_return_size);
7529 break;
7532 case SMB_POSIX_PATH_UNLINK:
7534 if (fsp) {
7535 /* We must have a pathname for this. */
7536 return NT_STATUS_INVALID_LEVEL;
7539 status = smb_posix_unlink(conn, req,
7540 pdata,
7541 total_data,
7542 smb_fname);
7543 break;
7546 default:
7547 return NT_STATUS_INVALID_LEVEL;
7550 if (!NT_STATUS_IS_OK(status)) {
7551 return status;
7554 *ret_data_size = data_return_size;
7555 return NT_STATUS_OK;
7558 /****************************************************************************
7559 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7560 ****************************************************************************/
7562 static void call_trans2setfilepathinfo(connection_struct *conn,
7563 struct smb_request *req,
7564 unsigned int tran_call,
7565 char **pparams, int total_params,
7566 char **ppdata, int total_data,
7567 unsigned int max_data_bytes)
7569 char *params = *pparams;
7570 char *pdata = *ppdata;
7571 uint16 info_level;
7572 struct smb_filename *smb_fname = NULL;
7573 files_struct *fsp = NULL;
7574 NTSTATUS status = NT_STATUS_OK;
7575 int data_return_size = 0;
7577 if (!params) {
7578 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7579 return;
7582 if (tran_call == TRANSACT2_SETFILEINFO) {
7583 if (total_params < 4) {
7584 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7585 return;
7588 fsp = file_fsp(req, SVAL(params,0));
7589 /* Basic check for non-null fsp. */
7590 if (!check_fsp_open(conn, req, fsp)) {
7591 return;
7593 info_level = SVAL(params,2);
7595 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7596 &smb_fname);
7597 if (!NT_STATUS_IS_OK(status)) {
7598 reply_nterror(req, status);
7599 return;
7602 if(fsp->is_directory || fsp->fh->fd == -1) {
7604 * This is actually a SETFILEINFO on a directory
7605 * handle (returned from an NT SMB). NT5.0 seems
7606 * to do this call. JRA.
7608 if (INFO_LEVEL_IS_UNIX(info_level)) {
7609 /* Always do lstat for UNIX calls. */
7610 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7611 DEBUG(3,("call_trans2setfilepathinfo: "
7612 "SMB_VFS_LSTAT of %s failed "
7613 "(%s)\n",
7614 smb_fname_str_dbg(smb_fname),
7615 strerror(errno)));
7616 reply_nterror(req, map_nt_error_from_unix(errno));
7617 return;
7619 } else {
7620 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7621 DEBUG(3,("call_trans2setfilepathinfo: "
7622 "fileinfo of %s failed (%s)\n",
7623 smb_fname_str_dbg(smb_fname),
7624 strerror(errno)));
7625 reply_nterror(req, map_nt_error_from_unix(errno));
7626 return;
7629 } else if (fsp->print_file) {
7631 * Doing a DELETE_ON_CLOSE should cancel a print job.
7633 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7634 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7636 DEBUG(3,("call_trans2setfilepathinfo: "
7637 "Cancelling print job (%s)\n",
7638 fsp_str_dbg(fsp)));
7640 SSVAL(params,0,0);
7641 send_trans2_replies(conn, req, params, 2,
7642 *ppdata, 0,
7643 max_data_bytes);
7644 return;
7645 } else {
7646 reply_nterror(req,
7647 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7648 return;
7650 } else {
7652 * Original code - this is an open file.
7654 if (!check_fsp(conn, req, fsp)) {
7655 return;
7658 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7659 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7660 "of fnum %d failed (%s)\n", fsp->fnum,
7661 strerror(errno)));
7662 reply_nterror(req, map_nt_error_from_unix(errno));
7663 return;
7666 } else {
7667 char *fname = NULL;
7669 /* set path info */
7670 if (total_params < 7) {
7671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7672 return;
7675 info_level = SVAL(params,0);
7676 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7677 total_params - 6, STR_TERMINATE,
7678 &status);
7679 if (!NT_STATUS_IS_OK(status)) {
7680 reply_nterror(req, status);
7681 return;
7684 status = filename_convert(req, conn,
7685 req->flags2 & FLAGS2_DFS_PATHNAMES,
7686 fname,
7688 NULL,
7689 &smb_fname);
7690 if (!NT_STATUS_IS_OK(status)) {
7691 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7692 reply_botherror(req,
7693 NT_STATUS_PATH_NOT_COVERED,
7694 ERRSRV, ERRbadpath);
7695 return;
7697 reply_nterror(req, status);
7698 return;
7701 if (INFO_LEVEL_IS_UNIX(info_level)) {
7703 * For CIFS UNIX extensions the target name may not exist.
7706 /* Always do lstat for UNIX calls. */
7707 SMB_VFS_LSTAT(conn, smb_fname);
7709 } else if (!VALID_STAT(smb_fname->st) &&
7710 SMB_VFS_STAT(conn, smb_fname)) {
7711 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7712 "%s failed (%s)\n",
7713 smb_fname_str_dbg(smb_fname),
7714 strerror(errno)));
7715 reply_nterror(req, map_nt_error_from_unix(errno));
7716 return;
7720 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7721 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7722 fsp ? fsp->fnum : -1, info_level,total_data));
7724 /* Realloc the parameter size */
7725 *pparams = (char *)SMB_REALLOC(*pparams,2);
7726 if (*pparams == NULL) {
7727 reply_nterror(req, NT_STATUS_NO_MEMORY);
7728 return;
7730 params = *pparams;
7732 SSVAL(params,0,0);
7734 status = smbd_do_setfilepathinfo(conn, req, req,
7735 info_level,
7736 fsp,
7737 smb_fname,
7738 ppdata, total_data,
7739 &data_return_size);
7740 if (!NT_STATUS_IS_OK(status)) {
7741 if (open_was_deferred(req->mid)) {
7742 /* We have re-scheduled this call. */
7743 return;
7745 if (blocking_lock_was_deferred(req->mid)) {
7746 /* We have re-scheduled this call. */
7747 return;
7749 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7750 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7751 ERRSRV, ERRbadpath);
7752 return;
7754 if (info_level == SMB_POSIX_PATH_OPEN) {
7755 reply_openerror(req, status);
7756 return;
7759 reply_nterror(req, status);
7760 return;
7763 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7764 max_data_bytes);
7766 return;
7769 /****************************************************************************
7770 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7771 ****************************************************************************/
7773 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7774 char **pparams, int total_params,
7775 char **ppdata, int total_data,
7776 unsigned int max_data_bytes)
7778 struct smb_filename *smb_dname = NULL;
7779 char *params = *pparams;
7780 char *pdata = *ppdata;
7781 char *directory = NULL;
7782 NTSTATUS status = NT_STATUS_OK;
7783 struct ea_list *ea_list = NULL;
7784 TALLOC_CTX *ctx = talloc_tos();
7786 if (!CAN_WRITE(conn)) {
7787 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7788 return;
7791 if (total_params < 5) {
7792 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7793 return;
7796 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7797 total_params - 4, STR_TERMINATE,
7798 &status);
7799 if (!NT_STATUS_IS_OK(status)) {
7800 reply_nterror(req, status);
7801 return;
7804 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7806 status = filename_convert(ctx,
7807 conn,
7808 req->flags2 & FLAGS2_DFS_PATHNAMES,
7809 directory,
7811 NULL,
7812 &smb_dname);
7814 if (!NT_STATUS_IS_OK(status)) {
7815 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7816 reply_botherror(req,
7817 NT_STATUS_PATH_NOT_COVERED,
7818 ERRSRV, ERRbadpath);
7819 return;
7821 reply_nterror(req, status);
7822 return;
7826 * OS/2 workplace shell seems to send SET_EA requests of "null"
7827 * length (4 bytes containing IVAL 4).
7828 * They seem to have no effect. Bug #3212. JRA.
7831 if (total_data && (total_data != 4)) {
7832 /* Any data in this call is an EA list. */
7833 if (total_data < 10) {
7834 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7835 goto out;
7838 if (IVAL(pdata,0) > total_data) {
7839 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7840 IVAL(pdata,0), (unsigned int)total_data));
7841 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7842 goto out;
7845 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7846 total_data - 4);
7847 if (!ea_list) {
7848 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7849 goto out;
7852 if (!lp_ea_support(SNUM(conn))) {
7853 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7854 goto out;
7857 /* If total_data == 4 Windows doesn't care what values
7858 * are placed in that field, it just ignores them.
7859 * The System i QNTC IBM SMB client puts bad values here,
7860 * so ignore them. */
7862 status = create_directory(conn, req, smb_dname);
7864 if (!NT_STATUS_IS_OK(status)) {
7865 reply_nterror(req, status);
7866 goto out;
7869 /* Try and set any given EA. */
7870 if (ea_list) {
7871 status = set_ea(conn, NULL, smb_dname, ea_list);
7872 if (!NT_STATUS_IS_OK(status)) {
7873 reply_nterror(req, status);
7874 goto out;
7878 /* Realloc the parameter and data sizes */
7879 *pparams = (char *)SMB_REALLOC(*pparams,2);
7880 if(*pparams == NULL) {
7881 reply_nterror(req, NT_STATUS_NO_MEMORY);
7882 goto out;
7884 params = *pparams;
7886 SSVAL(params,0,0);
7888 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7890 out:
7891 TALLOC_FREE(smb_dname);
7892 return;
7895 /****************************************************************************
7896 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7897 We don't actually do this - we just send a null response.
7898 ****************************************************************************/
7900 static void call_trans2findnotifyfirst(connection_struct *conn,
7901 struct smb_request *req,
7902 char **pparams, int total_params,
7903 char **ppdata, int total_data,
7904 unsigned int max_data_bytes)
7906 char *params = *pparams;
7907 uint16 info_level;
7909 if (total_params < 6) {
7910 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7911 return;
7914 info_level = SVAL(params,4);
7915 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7917 switch (info_level) {
7918 case 1:
7919 case 2:
7920 break;
7921 default:
7922 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7923 return;
7926 /* Realloc the parameter and data sizes */
7927 *pparams = (char *)SMB_REALLOC(*pparams,6);
7928 if (*pparams == NULL) {
7929 reply_nterror(req, NT_STATUS_NO_MEMORY);
7930 return;
7932 params = *pparams;
7934 SSVAL(params,0,fnf_handle);
7935 SSVAL(params,2,0); /* No changes */
7936 SSVAL(params,4,0); /* No EA errors */
7938 fnf_handle++;
7940 if(fnf_handle == 0)
7941 fnf_handle = 257;
7943 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7945 return;
7948 /****************************************************************************
7949 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7950 changes). Currently this does nothing.
7951 ****************************************************************************/
7953 static void call_trans2findnotifynext(connection_struct *conn,
7954 struct smb_request *req,
7955 char **pparams, int total_params,
7956 char **ppdata, int total_data,
7957 unsigned int max_data_bytes)
7959 char *params = *pparams;
7961 DEBUG(3,("call_trans2findnotifynext\n"));
7963 /* Realloc the parameter and data sizes */
7964 *pparams = (char *)SMB_REALLOC(*pparams,4);
7965 if (*pparams == NULL) {
7966 reply_nterror(req, NT_STATUS_NO_MEMORY);
7967 return;
7969 params = *pparams;
7971 SSVAL(params,0,0); /* No changes */
7972 SSVAL(params,2,0); /* No EA errors */
7974 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7976 return;
7979 /****************************************************************************
7980 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7981 ****************************************************************************/
7983 static void call_trans2getdfsreferral(connection_struct *conn,
7984 struct smb_request *req,
7985 char **pparams, int total_params,
7986 char **ppdata, int total_data,
7987 unsigned int max_data_bytes)
7989 char *params = *pparams;
7990 char *pathname = NULL;
7991 int reply_size = 0;
7992 int max_referral_level;
7993 NTSTATUS status = NT_STATUS_OK;
7994 TALLOC_CTX *ctx = talloc_tos();
7996 DEBUG(10,("call_trans2getdfsreferral\n"));
7998 if (total_params < 3) {
7999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8000 return;
8003 max_referral_level = SVAL(params,0);
8005 if(!lp_host_msdfs()) {
8006 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8007 return;
8010 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8011 total_params - 2, STR_TERMINATE);
8012 if (!pathname) {
8013 reply_nterror(req, NT_STATUS_NOT_FOUND);
8014 return;
8016 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8017 ppdata,&status)) < 0) {
8018 reply_nterror(req, status);
8019 return;
8022 SSVAL(req->inbuf, smb_flg2,
8023 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8024 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8026 return;
8029 #define LMCAT_SPL 0x53
8030 #define LMFUNC_GETJOBID 0x60
8032 /****************************************************************************
8033 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8034 ****************************************************************************/
8036 static void call_trans2ioctl(connection_struct *conn,
8037 struct smb_request *req,
8038 char **pparams, int total_params,
8039 char **ppdata, int total_data,
8040 unsigned int max_data_bytes)
8042 char *pdata = *ppdata;
8043 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8045 /* check for an invalid fid before proceeding */
8047 if (!fsp) {
8048 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8049 return;
8052 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8053 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8054 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8055 if (*ppdata == NULL) {
8056 reply_nterror(req, NT_STATUS_NO_MEMORY);
8057 return;
8059 pdata = *ppdata;
8061 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8062 CAN ACCEPT THIS IN UNICODE. JRA. */
8064 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8065 srvstr_push(pdata, req->flags2, pdata + 2,
8066 global_myname(), 15,
8067 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8068 srvstr_push(pdata, req->flags2, pdata+18,
8069 lp_servicename(SNUM(conn)), 13,
8070 STR_ASCII|STR_TERMINATE); /* Service name */
8071 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8072 max_data_bytes);
8073 return;
8076 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8077 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8080 /****************************************************************************
8081 Reply to a SMBfindclose (stop trans2 directory search).
8082 ****************************************************************************/
8084 void reply_findclose(struct smb_request *req)
8086 int dptr_num;
8087 struct smbd_server_connection *sconn = smbd_server_conn;
8089 START_PROFILE(SMBfindclose);
8091 if (req->wct < 1) {
8092 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8093 END_PROFILE(SMBfindclose);
8094 return;
8097 dptr_num = SVALS(req->vwv+0, 0);
8099 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8101 dptr_close(sconn, &dptr_num);
8103 reply_outbuf(req, 0, 0);
8105 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8107 END_PROFILE(SMBfindclose);
8108 return;
8111 /****************************************************************************
8112 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8113 ****************************************************************************/
8115 void reply_findnclose(struct smb_request *req)
8117 int dptr_num;
8119 START_PROFILE(SMBfindnclose);
8121 if (req->wct < 1) {
8122 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8123 END_PROFILE(SMBfindnclose);
8124 return;
8127 dptr_num = SVAL(req->vwv+0, 0);
8129 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8131 /* We never give out valid handles for a
8132 findnotifyfirst - so any dptr_num is ok here.
8133 Just ignore it. */
8135 reply_outbuf(req, 0, 0);
8137 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8139 END_PROFILE(SMBfindnclose);
8140 return;
8143 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8144 struct trans_state *state)
8146 if (get_Protocol() >= PROTOCOL_NT1) {
8147 req->flags2 |= 0x40; /* IS_LONG_NAME */
8148 SSVAL(req->inbuf,smb_flg2,req->flags2);
8151 if (conn->encrypt_level == Required && !req->encrypted) {
8152 if (state->call != TRANSACT2_QFSINFO &&
8153 state->call != TRANSACT2_SETFSINFO) {
8154 DEBUG(0,("handle_trans2: encryption required "
8155 "with call 0x%x\n",
8156 (unsigned int)state->call));
8157 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8158 return;
8162 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8164 /* Now we must call the relevant TRANS2 function */
8165 switch(state->call) {
8166 case TRANSACT2_OPEN:
8168 START_PROFILE(Trans2_open);
8169 call_trans2open(conn, req,
8170 &state->param, state->total_param,
8171 &state->data, state->total_data,
8172 state->max_data_return);
8173 END_PROFILE(Trans2_open);
8174 break;
8177 case TRANSACT2_FINDFIRST:
8179 START_PROFILE(Trans2_findfirst);
8180 call_trans2findfirst(conn, req,
8181 &state->param, state->total_param,
8182 &state->data, state->total_data,
8183 state->max_data_return);
8184 END_PROFILE(Trans2_findfirst);
8185 break;
8188 case TRANSACT2_FINDNEXT:
8190 START_PROFILE(Trans2_findnext);
8191 call_trans2findnext(conn, req,
8192 &state->param, state->total_param,
8193 &state->data, state->total_data,
8194 state->max_data_return);
8195 END_PROFILE(Trans2_findnext);
8196 break;
8199 case TRANSACT2_QFSINFO:
8201 START_PROFILE(Trans2_qfsinfo);
8202 call_trans2qfsinfo(conn, req,
8203 &state->param, state->total_param,
8204 &state->data, state->total_data,
8205 state->max_data_return);
8206 END_PROFILE(Trans2_qfsinfo);
8207 break;
8210 case TRANSACT2_SETFSINFO:
8212 START_PROFILE(Trans2_setfsinfo);
8213 call_trans2setfsinfo(conn, req,
8214 &state->param, state->total_param,
8215 &state->data, state->total_data,
8216 state->max_data_return);
8217 END_PROFILE(Trans2_setfsinfo);
8218 break;
8221 case TRANSACT2_QPATHINFO:
8222 case TRANSACT2_QFILEINFO:
8224 START_PROFILE(Trans2_qpathinfo);
8225 call_trans2qfilepathinfo(conn, req, state->call,
8226 &state->param, state->total_param,
8227 &state->data, state->total_data,
8228 state->max_data_return);
8229 END_PROFILE(Trans2_qpathinfo);
8230 break;
8233 case TRANSACT2_SETPATHINFO:
8234 case TRANSACT2_SETFILEINFO:
8236 START_PROFILE(Trans2_setpathinfo);
8237 call_trans2setfilepathinfo(conn, req, state->call,
8238 &state->param, state->total_param,
8239 &state->data, state->total_data,
8240 state->max_data_return);
8241 END_PROFILE(Trans2_setpathinfo);
8242 break;
8245 case TRANSACT2_FINDNOTIFYFIRST:
8247 START_PROFILE(Trans2_findnotifyfirst);
8248 call_trans2findnotifyfirst(conn, req,
8249 &state->param, state->total_param,
8250 &state->data, state->total_data,
8251 state->max_data_return);
8252 END_PROFILE(Trans2_findnotifyfirst);
8253 break;
8256 case TRANSACT2_FINDNOTIFYNEXT:
8258 START_PROFILE(Trans2_findnotifynext);
8259 call_trans2findnotifynext(conn, req,
8260 &state->param, state->total_param,
8261 &state->data, state->total_data,
8262 state->max_data_return);
8263 END_PROFILE(Trans2_findnotifynext);
8264 break;
8267 case TRANSACT2_MKDIR:
8269 START_PROFILE(Trans2_mkdir);
8270 call_trans2mkdir(conn, req,
8271 &state->param, state->total_param,
8272 &state->data, state->total_data,
8273 state->max_data_return);
8274 END_PROFILE(Trans2_mkdir);
8275 break;
8278 case TRANSACT2_GET_DFS_REFERRAL:
8280 START_PROFILE(Trans2_get_dfs_referral);
8281 call_trans2getdfsreferral(conn, req,
8282 &state->param, state->total_param,
8283 &state->data, state->total_data,
8284 state->max_data_return);
8285 END_PROFILE(Trans2_get_dfs_referral);
8286 break;
8289 case TRANSACT2_IOCTL:
8291 START_PROFILE(Trans2_ioctl);
8292 call_trans2ioctl(conn, req,
8293 &state->param, state->total_param,
8294 &state->data, state->total_data,
8295 state->max_data_return);
8296 END_PROFILE(Trans2_ioctl);
8297 break;
8300 default:
8301 /* Error in request */
8302 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8303 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8307 /****************************************************************************
8308 Reply to a SMBtrans2.
8309 ****************************************************************************/
8311 void reply_trans2(struct smb_request *req)
8313 connection_struct *conn = req->conn;
8314 unsigned int dsoff;
8315 unsigned int dscnt;
8316 unsigned int psoff;
8317 unsigned int pscnt;
8318 unsigned int tran_call;
8319 struct trans_state *state;
8320 NTSTATUS result;
8322 START_PROFILE(SMBtrans2);
8324 if (req->wct < 14) {
8325 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8326 END_PROFILE(SMBtrans2);
8327 return;
8330 dsoff = SVAL(req->vwv+12, 0);
8331 dscnt = SVAL(req->vwv+11, 0);
8332 psoff = SVAL(req->vwv+10, 0);
8333 pscnt = SVAL(req->vwv+9, 0);
8334 tran_call = SVAL(req->vwv+14, 0);
8336 result = allow_new_trans(conn->pending_trans, req->mid);
8337 if (!NT_STATUS_IS_OK(result)) {
8338 DEBUG(2, ("Got invalid trans2 request: %s\n",
8339 nt_errstr(result)));
8340 reply_nterror(req, result);
8341 END_PROFILE(SMBtrans2);
8342 return;
8345 if (IS_IPC(conn)) {
8346 switch (tran_call) {
8347 /* List the allowed trans2 calls on IPC$ */
8348 case TRANSACT2_OPEN:
8349 case TRANSACT2_GET_DFS_REFERRAL:
8350 case TRANSACT2_QFILEINFO:
8351 case TRANSACT2_QFSINFO:
8352 case TRANSACT2_SETFSINFO:
8353 break;
8354 default:
8355 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8356 END_PROFILE(SMBtrans2);
8357 return;
8361 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8362 DEBUG(0, ("talloc failed\n"));
8363 reply_nterror(req, NT_STATUS_NO_MEMORY);
8364 END_PROFILE(SMBtrans2);
8365 return;
8368 state->cmd = SMBtrans2;
8370 state->mid = req->mid;
8371 state->vuid = req->vuid;
8372 state->setup_count = SVAL(req->vwv+13, 0);
8373 state->setup = NULL;
8374 state->total_param = SVAL(req->vwv+0, 0);
8375 state->param = NULL;
8376 state->total_data = SVAL(req->vwv+1, 0);
8377 state->data = NULL;
8378 state->max_param_return = SVAL(req->vwv+2, 0);
8379 state->max_data_return = SVAL(req->vwv+3, 0);
8380 state->max_setup_return = SVAL(req->vwv+4, 0);
8381 state->close_on_completion = BITSETW(req->vwv+5, 0);
8382 state->one_way = BITSETW(req->vwv+5, 1);
8384 state->call = tran_call;
8386 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8387 is so as a sanity check */
8388 if (state->setup_count != 1) {
8390 * Need to have rc=0 for ioctl to get job id for OS/2.
8391 * Network printing will fail if function is not successful.
8392 * Similar function in reply.c will be used if protocol
8393 * is LANMAN1.0 instead of LM1.2X002.
8394 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8395 * outbuf doesn't have to be set(only job id is used).
8397 if ( (state->setup_count == 4)
8398 && (tran_call == TRANSACT2_IOCTL)
8399 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8400 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8401 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8402 } else {
8403 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8404 DEBUG(2,("Transaction is %d\n",tran_call));
8405 TALLOC_FREE(state);
8406 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8407 END_PROFILE(SMBtrans2);
8408 return;
8412 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8413 goto bad_param;
8415 if (state->total_data) {
8417 if (trans_oob(state->total_data, 0, dscnt)
8418 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8419 goto bad_param;
8422 /* Can't use talloc here, the core routines do realloc on the
8423 * params and data. */
8424 state->data = (char *)SMB_MALLOC(state->total_data);
8425 if (state->data == NULL) {
8426 DEBUG(0,("reply_trans2: data malloc fail for %u "
8427 "bytes !\n", (unsigned int)state->total_data));
8428 TALLOC_FREE(state);
8429 reply_nterror(req, NT_STATUS_NO_MEMORY);
8430 END_PROFILE(SMBtrans2);
8431 return;
8434 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8437 if (state->total_param) {
8439 if (trans_oob(state->total_param, 0, pscnt)
8440 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8441 goto bad_param;
8444 /* Can't use talloc here, the core routines do realloc on the
8445 * params and data. */
8446 state->param = (char *)SMB_MALLOC(state->total_param);
8447 if (state->param == NULL) {
8448 DEBUG(0,("reply_trans: param malloc fail for %u "
8449 "bytes !\n", (unsigned int)state->total_param));
8450 SAFE_FREE(state->data);
8451 TALLOC_FREE(state);
8452 reply_nterror(req, NT_STATUS_NO_MEMORY);
8453 END_PROFILE(SMBtrans2);
8454 return;
8457 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8460 state->received_data = dscnt;
8461 state->received_param = pscnt;
8463 if ((state->received_param == state->total_param) &&
8464 (state->received_data == state->total_data)) {
8466 handle_trans2(conn, req, state);
8468 SAFE_FREE(state->data);
8469 SAFE_FREE(state->param);
8470 TALLOC_FREE(state);
8471 END_PROFILE(SMBtrans2);
8472 return;
8475 DLIST_ADD(conn->pending_trans, state);
8477 /* We need to send an interim response then receive the rest
8478 of the parameter/data bytes */
8479 reply_outbuf(req, 0, 0);
8480 show_msg((char *)req->outbuf);
8481 END_PROFILE(SMBtrans2);
8482 return;
8484 bad_param:
8486 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8487 SAFE_FREE(state->data);
8488 SAFE_FREE(state->param);
8489 TALLOC_FREE(state);
8490 END_PROFILE(SMBtrans2);
8491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8495 /****************************************************************************
8496 Reply to a SMBtranss2
8497 ****************************************************************************/
8499 void reply_transs2(struct smb_request *req)
8501 connection_struct *conn = req->conn;
8502 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8503 struct trans_state *state;
8505 START_PROFILE(SMBtranss2);
8507 show_msg((char *)req->inbuf);
8509 if (req->wct < 8) {
8510 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8511 END_PROFILE(SMBtranss2);
8512 return;
8515 for (state = conn->pending_trans; state != NULL;
8516 state = state->next) {
8517 if (state->mid == req->mid) {
8518 break;
8522 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8523 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8524 END_PROFILE(SMBtranss2);
8525 return;
8528 /* Revise state->total_param and state->total_data in case they have
8529 changed downwards */
8531 if (SVAL(req->vwv+0, 0) < state->total_param)
8532 state->total_param = SVAL(req->vwv+0, 0);
8533 if (SVAL(req->vwv+1, 0) < state->total_data)
8534 state->total_data = SVAL(req->vwv+1, 0);
8536 pcnt = SVAL(req->vwv+2, 0);
8537 poff = SVAL(req->vwv+3, 0);
8538 pdisp = SVAL(req->vwv+4, 0);
8540 dcnt = SVAL(req->vwv+5, 0);
8541 doff = SVAL(req->vwv+6, 0);
8542 ddisp = SVAL(req->vwv+7, 0);
8544 state->received_param += pcnt;
8545 state->received_data += dcnt;
8547 if ((state->received_data > state->total_data) ||
8548 (state->received_param > state->total_param))
8549 goto bad_param;
8551 if (pcnt) {
8552 if (trans_oob(state->total_param, pdisp, pcnt)
8553 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8554 goto bad_param;
8556 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8559 if (dcnt) {
8560 if (trans_oob(state->total_data, ddisp, dcnt)
8561 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8562 goto bad_param;
8564 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8567 if ((state->received_param < state->total_param) ||
8568 (state->received_data < state->total_data)) {
8569 END_PROFILE(SMBtranss2);
8570 return;
8573 handle_trans2(conn, req, state);
8575 DLIST_REMOVE(conn->pending_trans, state);
8576 SAFE_FREE(state->data);
8577 SAFE_FREE(state->param);
8578 TALLOC_FREE(state);
8580 END_PROFILE(SMBtranss2);
8581 return;
8583 bad_param:
8585 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8586 DLIST_REMOVE(conn->pending_trans, state);
8587 SAFE_FREE(state->data);
8588 SAFE_FREE(state->param);
8589 TALLOC_FREE(state);
8590 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8591 END_PROFILE(SMBtranss2);
8592 return;