samba-3.5.8 for ARM
[tomato.git] / release / src-rt-6.x.4708 / router / samba-3.5.8 / source3 / smbd / trans2.c
blobdc5924d3dc745c88206f5f4b3371d5424b1d38df
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->base_name, deny_mode,
1072 open_ofun,
1073 &access_mask, &share_mode,
1074 &create_disposition,
1075 &create_options)) {
1076 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1077 goto out;
1080 /* Any data in this call is an EA list. */
1081 if (total_data && (total_data != 4)) {
1082 if (total_data < 10) {
1083 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1084 goto out;
1087 if (IVAL(pdata,0) > total_data) {
1088 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1089 IVAL(pdata,0), (unsigned int)total_data));
1090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1091 goto out;
1094 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1095 total_data - 4);
1096 if (!ea_list) {
1097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1098 goto out;
1101 if (!lp_ea_support(SNUM(conn))) {
1102 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1103 goto out;
1107 status = SMB_VFS_CREATE_FILE(
1108 conn, /* conn */
1109 req, /* req */
1110 0, /* root_dir_fid */
1111 smb_fname, /* fname */
1112 access_mask, /* access_mask */
1113 share_mode, /* share_access */
1114 create_disposition, /* create_disposition*/
1115 create_options, /* create_options */
1116 open_attr, /* file_attributes */
1117 oplock_request, /* oplock_request */
1118 open_size, /* allocation_size */
1119 NULL, /* sd */
1120 ea_list, /* ea_list */
1121 &fsp, /* result */
1122 &smb_action); /* psbuf */
1124 if (!NT_STATUS_IS_OK(status)) {
1125 if (open_was_deferred(req->mid)) {
1126 /* We have re-scheduled this call. */
1127 goto out;
1129 reply_openerror(req, status);
1130 goto out;
1133 size = get_file_size_stat(&smb_fname->st);
1134 fattr = dos_mode(conn, smb_fname);
1135 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1136 inode = smb_fname->st.st_ex_ino;
1137 if (fattr & aDIR) {
1138 close_file(req, fsp, ERROR_CLOSE);
1139 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1140 goto out;
1143 /* Realloc the size of parameters and data we will return */
1144 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1145 if(*pparams == NULL ) {
1146 reply_nterror(req, NT_STATUS_NO_MEMORY);
1147 goto out;
1149 params = *pparams;
1151 SSVAL(params,0,fsp->fnum);
1152 SSVAL(params,2,fattr);
1153 srv_put_dos_date2(params,4, mtime);
1154 SIVAL(params,8, (uint32)size);
1155 SSVAL(params,12,deny_mode);
1156 SSVAL(params,14,0); /* open_type - file or directory. */
1157 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1159 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1160 smb_action |= EXTENDED_OPLOCK_GRANTED;
1163 SSVAL(params,18,smb_action);
1166 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1168 SIVAL(params,20,inode);
1169 SSVAL(params,24,0); /* Padding. */
1170 if (flags & 8) {
1171 uint32 ea_size = estimate_ea_size(conn, fsp,
1172 fsp->fsp_name->base_name);
1173 SIVAL(params, 26, ea_size);
1174 } else {
1175 SIVAL(params, 26, 0);
1178 /* Send the required number of replies */
1179 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1180 out:
1181 TALLOC_FREE(smb_fname);
1184 /*********************************************************
1185 Routine to check if a given string matches exactly.
1186 as a special case a mask of "." does NOT match. That
1187 is required for correct wildcard semantics
1188 Case can be significant or not.
1189 **********************************************************/
1191 static bool exact_match(bool has_wild,
1192 bool case_sensitive,
1193 const char *str,
1194 const char *mask)
1196 if (mask[0] == '.' && mask[1] == 0) {
1197 return false;
1200 if (has_wild) {
1201 return false;
1204 if (case_sensitive) {
1205 return strcmp(str,mask)==0;
1206 } else {
1207 return StrCaseCmp(str,mask) == 0;
1211 /****************************************************************************
1212 Return the filetype for UNIX extensions.
1213 ****************************************************************************/
1215 static uint32 unix_filetype(mode_t mode)
1217 if(S_ISREG(mode))
1218 return UNIX_TYPE_FILE;
1219 else if(S_ISDIR(mode))
1220 return UNIX_TYPE_DIR;
1221 #ifdef S_ISLNK
1222 else if(S_ISLNK(mode))
1223 return UNIX_TYPE_SYMLINK;
1224 #endif
1225 #ifdef S_ISCHR
1226 else if(S_ISCHR(mode))
1227 return UNIX_TYPE_CHARDEV;
1228 #endif
1229 #ifdef S_ISBLK
1230 else if(S_ISBLK(mode))
1231 return UNIX_TYPE_BLKDEV;
1232 #endif
1233 #ifdef S_ISFIFO
1234 else if(S_ISFIFO(mode))
1235 return UNIX_TYPE_FIFO;
1236 #endif
1237 #ifdef S_ISSOCK
1238 else if(S_ISSOCK(mode))
1239 return UNIX_TYPE_SOCKET;
1240 #endif
1242 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1243 return UNIX_TYPE_UNKNOWN;
1246 /****************************************************************************
1247 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1248 ****************************************************************************/
1250 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1252 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1253 const SMB_STRUCT_STAT *psbuf,
1254 uint32 perms,
1255 enum perm_type ptype,
1256 mode_t *ret_perms)
1258 mode_t ret = 0;
1260 if (perms == SMB_MODE_NO_CHANGE) {
1261 if (!VALID_STAT(*psbuf)) {
1262 return NT_STATUS_INVALID_PARAMETER;
1263 } else {
1264 *ret_perms = psbuf->st_ex_mode;
1265 return NT_STATUS_OK;
1269 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1270 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1271 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1272 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1273 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1274 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1275 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1276 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1277 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1278 #ifdef S_ISVTX
1279 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1280 #endif
1281 #ifdef S_ISGID
1282 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1283 #endif
1284 #ifdef S_ISUID
1285 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1286 #endif
1288 switch (ptype) {
1289 case PERM_NEW_FILE:
1290 /* Apply mode mask */
1291 ret &= lp_create_mask(SNUM(conn));
1292 /* Add in force bits */
1293 ret |= lp_force_create_mode(SNUM(conn));
1294 break;
1295 case PERM_NEW_DIR:
1296 ret &= lp_dir_mask(SNUM(conn));
1297 /* Add in force bits */
1298 ret |= lp_force_dir_mode(SNUM(conn));
1299 break;
1300 case PERM_EXISTING_FILE:
1301 /* Apply mode mask */
1302 ret &= lp_security_mask(SNUM(conn));
1303 /* Add in force bits */
1304 ret |= lp_force_security_mode(SNUM(conn));
1305 break;
1306 case PERM_EXISTING_DIR:
1307 /* Apply mode mask */
1308 ret &= lp_dir_security_mask(SNUM(conn));
1309 /* Add in force bits */
1310 ret |= lp_force_dir_security_mode(SNUM(conn));
1311 break;
1314 *ret_perms = ret;
1315 return NT_STATUS_OK;
1318 /****************************************************************************
1319 Needed to show the msdfs symlinks as directories. Modifies psbuf
1320 to be a directory if it's a msdfs link.
1321 ****************************************************************************/
1323 static bool check_msdfs_link(connection_struct *conn,
1324 const char *pathname,
1325 SMB_STRUCT_STAT *psbuf)
1327 int saved_errno = errno;
1328 if(lp_host_msdfs() &&
1329 lp_msdfs_root(SNUM(conn)) &&
1330 is_msdfs_link(conn, pathname, psbuf)) {
1332 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1333 "as a directory\n",
1334 pathname));
1335 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1336 errno = saved_errno;
1337 return true;
1339 errno = saved_errno;
1340 return false;
1344 /****************************************************************************
1345 Get a level dependent lanman2 dir entry.
1346 ****************************************************************************/
1348 struct smbd_dirptr_lanman2_state {
1349 connection_struct *conn;
1350 uint32_t info_level;
1351 bool check_mangled_names;
1352 bool has_wild;
1353 bool got_exact_match;
1356 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1357 void *private_data,
1358 const char *dname,
1359 const char *mask,
1360 char **_fname)
1362 struct smbd_dirptr_lanman2_state *state =
1363 (struct smbd_dirptr_lanman2_state *)private_data;
1364 bool ok;
1365 char mangled_name[13]; /* mangled 8.3 name. */
1366 bool got_match;
1367 const char *fname;
1369 /* Mangle fname if it's an illegal name. */
1370 if (mangle_must_mangle(dname, state->conn->params)) {
1371 ok = name_to_8_3(dname, mangled_name,
1372 true, state->conn->params);
1373 if (!ok) {
1374 return false;
1376 fname = mangled_name;
1377 } else {
1378 fname = dname;
1381 got_match = exact_match(state->has_wild,
1382 state->conn->case_sensitive,
1383 fname, mask);
1384 state->got_exact_match = got_match;
1385 if (!got_match) {
1386 got_match = mask_match(fname, mask,
1387 state->conn->case_sensitive);
1390 if(!got_match && state->check_mangled_names &&
1391 !mangle_is_8_3(fname, false, state->conn->params)) {
1393 * It turns out that NT matches wildcards against
1394 * both long *and* short names. This may explain some
1395 * of the wildcard wierdness from old DOS clients
1396 * that some people have been seeing.... JRA.
1398 /* Force the mangling into 8.3. */
1399 ok = name_to_8_3(fname, mangled_name,
1400 false, state->conn->params);
1401 if (!ok) {
1402 return false;
1405 got_match = exact_match(state->has_wild,
1406 state->conn->case_sensitive,
1407 mangled_name, mask);
1408 state->got_exact_match = got_match;
1409 if (!got_match) {
1410 got_match = mask_match(mangled_name, mask,
1411 state->conn->case_sensitive);
1415 if (!got_match) {
1416 return false;
1419 *_fname = talloc_strdup(ctx, fname);
1420 if (*_fname == NULL) {
1421 return false;
1424 return true;
1427 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1428 void *private_data,
1429 struct smb_filename *smb_fname,
1430 uint32_t *_mode)
1432 struct smbd_dirptr_lanman2_state *state =
1433 (struct smbd_dirptr_lanman2_state *)private_data;
1434 bool ms_dfs_link = false;
1435 uint32_t mode = 0;
1437 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1438 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1439 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1440 "Couldn't lstat [%s] (%s)\n",
1441 smb_fname_str_dbg(smb_fname),
1442 strerror(errno)));
1443 return false;
1445 } else if (!VALID_STAT(smb_fname->st) &&
1446 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1447 /* Needed to show the msdfs symlinks as
1448 * directories */
1450 ms_dfs_link = check_msdfs_link(state->conn,
1451 smb_fname->base_name,
1452 &smb_fname->st);
1453 if (!ms_dfs_link) {
1454 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1455 "Couldn't stat [%s] (%s)\n",
1456 smb_fname_str_dbg(smb_fname),
1457 strerror(errno)));
1458 return false;
1462 if (ms_dfs_link) {
1463 mode = dos_mode_msdfs(state->conn, smb_fname);
1464 } else {
1465 mode = dos_mode(state->conn, smb_fname);
1468 *_mode = mode;
1469 return true;
1472 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1473 connection_struct *conn,
1474 uint16_t flags2,
1475 uint32_t info_level,
1476 struct ea_list *name_list,
1477 bool check_mangled_names,
1478 bool requires_resume_key,
1479 uint32_t mode,
1480 const char *fname,
1481 const struct smb_filename *smb_fname,
1482 uint64_t space_remaining,
1483 uint8_t align,
1484 bool do_pad,
1485 char *base_data,
1486 char **ppdata,
1487 char *end_data,
1488 bool *out_of_space,
1489 uint64_t *last_entry_off)
1491 char *p, *q, *pdata = *ppdata;
1492 uint32_t reskey=0;
1493 uint64_t file_size = 0;
1494 uint64_t allocation_size = 0;
1495 uint64_t file_index = 0;
1496 uint32_t len;
1497 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1498 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1499 time_t c_date = (time_t)0;
1500 char *nameptr;
1501 char *last_entry_ptr;
1502 bool was_8_3;
1503 off_t off;
1504 off_t pad = 0;
1506 *out_of_space = false;
1508 ZERO_STRUCT(mdate_ts);
1509 ZERO_STRUCT(adate_ts);
1510 ZERO_STRUCT(create_date_ts);
1511 ZERO_STRUCT(cdate_ts);
1513 if (!(mode & aDIR)) {
1514 file_size = get_file_size_stat(&smb_fname->st);
1516 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1518 file_index = get_FileIndex(conn, &smb_fname->st);
1520 mdate_ts = smb_fname->st.st_ex_mtime;
1521 adate_ts = smb_fname->st.st_ex_atime;
1522 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1523 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1525 if (lp_dos_filetime_resolution(SNUM(conn))) {
1526 dos_filetime_timespec(&create_date_ts);
1527 dos_filetime_timespec(&mdate_ts);
1528 dos_filetime_timespec(&adate_ts);
1529 dos_filetime_timespec(&cdate_ts);
1532 create_date = convert_timespec_to_time_t(create_date_ts);
1533 mdate = convert_timespec_to_time_t(mdate_ts);
1534 adate = convert_timespec_to_time_t(adate_ts);
1535 c_date = convert_timespec_to_time_t(cdate_ts);
1537 /* align the record */
1538 off = PTR_DIFF(pdata, base_data);
1539 pad = (off + (align-1)) & ~(align-1);
1540 pad -= off;
1541 off += pad;
1542 /* initialize padding to 0 */
1543 if (pad) {
1544 memset(pdata, 0, pad);
1546 space_remaining -= pad;
1548 pdata += pad;
1549 p = pdata;
1550 last_entry_ptr = p;
1552 pad = 0;
1553 off = 0;
1555 switch (info_level) {
1556 case SMB_FIND_INFO_STANDARD:
1557 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1558 if(requires_resume_key) {
1559 SIVAL(p,0,reskey);
1560 p += 4;
1562 srv_put_dos_date2(p,0,create_date);
1563 srv_put_dos_date2(p,4,adate);
1564 srv_put_dos_date2(p,8,mdate);
1565 SIVAL(p,12,(uint32)file_size);
1566 SIVAL(p,16,(uint32)allocation_size);
1567 SSVAL(p,20,mode);
1568 p += 23;
1569 nameptr = p;
1570 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1571 p += ucs2_align(base_data, p, 0);
1573 len = srvstr_push(base_data, flags2, p,
1574 fname, PTR_DIFF(end_data, p),
1575 STR_TERMINATE);
1576 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1577 if (len > 2) {
1578 SCVAL(nameptr, -1, len - 2);
1579 } else {
1580 SCVAL(nameptr, -1, 0);
1582 } else {
1583 if (len > 1) {
1584 SCVAL(nameptr, -1, len - 1);
1585 } else {
1586 SCVAL(nameptr, -1, 0);
1589 p += len;
1590 break;
1592 case SMB_FIND_EA_SIZE:
1593 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1594 if (requires_resume_key) {
1595 SIVAL(p,0,reskey);
1596 p += 4;
1598 srv_put_dos_date2(p,0,create_date);
1599 srv_put_dos_date2(p,4,adate);
1600 srv_put_dos_date2(p,8,mdate);
1601 SIVAL(p,12,(uint32)file_size);
1602 SIVAL(p,16,(uint32)allocation_size);
1603 SSVAL(p,20,mode);
1605 unsigned int ea_size = estimate_ea_size(conn, NULL,
1606 smb_fname->base_name);
1607 SIVAL(p,22,ea_size); /* Extended attributes */
1609 p += 27;
1610 nameptr = p - 1;
1611 len = srvstr_push(base_data, flags2,
1612 p, fname, PTR_DIFF(end_data, p),
1613 STR_TERMINATE | STR_NOALIGN);
1614 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1615 if (len > 2) {
1616 len -= 2;
1617 } else {
1618 len = 0;
1620 } else {
1621 if (len > 1) {
1622 len -= 1;
1623 } else {
1624 len = 0;
1627 SCVAL(nameptr,0,len);
1628 p += len;
1629 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1630 break;
1632 case SMB_FIND_EA_LIST:
1634 struct ea_list *file_list = NULL;
1635 size_t ea_len = 0;
1637 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1638 if (!name_list) {
1639 return false;
1641 if (requires_resume_key) {
1642 SIVAL(p,0,reskey);
1643 p += 4;
1645 srv_put_dos_date2(p,0,create_date);
1646 srv_put_dos_date2(p,4,adate);
1647 srv_put_dos_date2(p,8,mdate);
1648 SIVAL(p,12,(uint32)file_size);
1649 SIVAL(p,16,(uint32)allocation_size);
1650 SSVAL(p,20,mode);
1651 p += 22; /* p now points to the EA area. */
1653 file_list = get_ea_list_from_file(ctx, conn, NULL,
1654 smb_fname->base_name,
1655 &ea_len);
1656 name_list = ea_list_union(name_list, file_list, &ea_len);
1658 /* We need to determine if this entry will fit in the space available. */
1659 /* Max string size is 255 bytes. */
1660 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1661 *out_of_space = true;
1662 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1663 return False; /* Not finished - just out of space */
1666 /* Push the ea_data followed by the name. */
1667 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1668 nameptr = p;
1669 len = srvstr_push(base_data, flags2,
1670 p + 1, fname, PTR_DIFF(end_data, p+1),
1671 STR_TERMINATE | STR_NOALIGN);
1672 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1673 if (len > 2) {
1674 len -= 2;
1675 } else {
1676 len = 0;
1678 } else {
1679 if (len > 1) {
1680 len -= 1;
1681 } else {
1682 len = 0;
1685 SCVAL(nameptr,0,len);
1686 p += len + 1;
1687 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1688 break;
1691 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1692 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1693 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1694 p += 4;
1695 SIVAL(p,0,reskey); p += 4;
1696 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1697 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1698 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1699 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1700 SOFF_T(p,0,file_size); p += 8;
1701 SOFF_T(p,0,allocation_size); p += 8;
1702 SIVAL(p,0,mode); p += 4;
1703 q = p; p += 4; /* q is placeholder for name length. */
1705 unsigned int ea_size = estimate_ea_size(conn, NULL,
1706 smb_fname->base_name);
1707 SIVAL(p,0,ea_size); /* Extended attributes */
1708 p += 4;
1710 /* Clear the short name buffer. This is
1711 * IMPORTANT as not doing so will trigger
1712 * a Win2k client bug. JRA.
1714 if (!was_8_3 && check_mangled_names) {
1715 char mangled_name[13]; /* mangled 8.3 name. */
1716 if (!name_to_8_3(fname,mangled_name,True,
1717 conn->params)) {
1718 /* Error - mangle failed ! */
1719 memset(mangled_name,'\0',12);
1721 mangled_name[12] = 0;
1722 len = srvstr_push(base_data, flags2,
1723 p+2, mangled_name, 24,
1724 STR_UPPER|STR_UNICODE);
1725 if (len < 24) {
1726 memset(p + 2 + len,'\0',24 - len);
1728 SSVAL(p, 0, len);
1729 } else {
1730 memset(p,'\0',26);
1732 p += 2 + 24;
1733 len = srvstr_push(base_data, flags2, p,
1734 fname, PTR_DIFF(end_data, p),
1735 STR_TERMINATE_ASCII);
1736 SIVAL(q,0,len);
1737 p += len;
1739 len = PTR_DIFF(p, pdata);
1740 pad = (len + (align-1)) & ~(align-1);
1742 * offset to the next entry, the caller
1743 * will overwrite it for the last entry
1744 * that's why we always include the padding
1746 SIVAL(pdata,0,pad);
1748 * set padding to zero
1750 if (do_pad) {
1751 memset(p, 0, pad - len);
1752 p = pdata + pad;
1753 } else {
1754 p = pdata + len;
1756 break;
1758 case SMB_FIND_FILE_DIRECTORY_INFO:
1759 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1760 p += 4;
1761 SIVAL(p,0,reskey); p += 4;
1762 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1763 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1764 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1765 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1766 SOFF_T(p,0,file_size); p += 8;
1767 SOFF_T(p,0,allocation_size); p += 8;
1768 SIVAL(p,0,mode); p += 4;
1769 len = srvstr_push(base_data, flags2,
1770 p + 4, fname, PTR_DIFF(end_data, p+4),
1771 STR_TERMINATE_ASCII);
1772 SIVAL(p,0,len);
1773 p += 4 + len;
1775 len = PTR_DIFF(p, pdata);
1776 pad = (len + (align-1)) & ~(align-1);
1778 * offset to the next entry, the caller
1779 * will overwrite it for the last entry
1780 * that's why we always include the padding
1782 SIVAL(pdata,0,pad);
1784 * set padding to zero
1786 if (do_pad) {
1787 memset(p, 0, pad - len);
1788 p = pdata + pad;
1789 } else {
1790 p = pdata + len;
1792 break;
1794 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1795 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1796 p += 4;
1797 SIVAL(p,0,reskey); p += 4;
1798 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1799 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1800 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1801 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1802 SOFF_T(p,0,file_size); p += 8;
1803 SOFF_T(p,0,allocation_size); p += 8;
1804 SIVAL(p,0,mode); p += 4;
1805 q = p; p += 4; /* q is placeholder for name length. */
1807 unsigned int ea_size = estimate_ea_size(conn, NULL,
1808 smb_fname->base_name);
1809 SIVAL(p,0,ea_size); /* Extended attributes */
1810 p +=4;
1812 len = srvstr_push(base_data, flags2, p,
1813 fname, PTR_DIFF(end_data, p),
1814 STR_TERMINATE_ASCII);
1815 SIVAL(q, 0, len);
1816 p += len;
1818 len = PTR_DIFF(p, pdata);
1819 pad = (len + (align-1)) & ~(align-1);
1821 * offset to the next entry, the caller
1822 * will overwrite it for the last entry
1823 * that's why we always include the padding
1825 SIVAL(pdata,0,pad);
1827 * set padding to zero
1829 if (do_pad) {
1830 memset(p, 0, pad - len);
1831 p = pdata + pad;
1832 } else {
1833 p = pdata + len;
1835 break;
1837 case SMB_FIND_FILE_NAMES_INFO:
1838 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1839 p += 4;
1840 SIVAL(p,0,reskey); p += 4;
1841 p += 4;
1842 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1843 acl on a dir (tridge) */
1844 len = srvstr_push(base_data, flags2, p,
1845 fname, PTR_DIFF(end_data, p),
1846 STR_TERMINATE_ASCII);
1847 SIVAL(p, -4, len);
1848 p += len;
1850 len = PTR_DIFF(p, pdata);
1851 pad = (len + (align-1)) & ~(align-1);
1853 * offset to the next entry, the caller
1854 * will overwrite it for the last entry
1855 * that's why we always include the padding
1857 SIVAL(pdata,0,pad);
1859 * set padding to zero
1861 if (do_pad) {
1862 memset(p, 0, pad - len);
1863 p = pdata + pad;
1864 } else {
1865 p = pdata + len;
1867 break;
1869 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1870 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1871 p += 4;
1872 SIVAL(p,0,reskey); p += 4;
1873 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1874 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1875 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1876 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1877 SOFF_T(p,0,file_size); p += 8;
1878 SOFF_T(p,0,allocation_size); p += 8;
1879 SIVAL(p,0,mode); p += 4;
1880 q = p; p += 4; /* q is placeholder for name length. */
1882 unsigned int ea_size = estimate_ea_size(conn, NULL,
1883 smb_fname->base_name);
1884 SIVAL(p,0,ea_size); /* Extended attributes */
1885 p +=4;
1887 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1888 SBVAL(p,0,file_index); p += 8;
1889 len = srvstr_push(base_data, flags2, p,
1890 fname, PTR_DIFF(end_data, p),
1891 STR_TERMINATE_ASCII);
1892 SIVAL(q, 0, len);
1893 p += len;
1895 len = PTR_DIFF(p, pdata);
1896 pad = (len + (align-1)) & ~(align-1);
1898 * offset to the next entry, the caller
1899 * will overwrite it for the last entry
1900 * that's why we always include the padding
1902 SIVAL(pdata,0,pad);
1904 * set padding to zero
1906 if (do_pad) {
1907 memset(p, 0, pad - len);
1908 p = pdata + pad;
1909 } else {
1910 p = pdata + len;
1912 break;
1914 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1915 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1916 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1917 p += 4;
1918 SIVAL(p,0,reskey); p += 4;
1919 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1920 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1921 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1922 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1923 SOFF_T(p,0,file_size); p += 8;
1924 SOFF_T(p,0,allocation_size); p += 8;
1925 SIVAL(p,0,mode); p += 4;
1926 q = p; p += 4; /* q is placeholder for name length */
1928 unsigned int ea_size = estimate_ea_size(conn, NULL,
1929 smb_fname->base_name);
1930 SIVAL(p,0,ea_size); /* Extended attributes */
1931 p +=4;
1933 /* Clear the short name buffer. This is
1934 * IMPORTANT as not doing so will trigger
1935 * a Win2k client bug. JRA.
1937 if (!was_8_3 && check_mangled_names) {
1938 char mangled_name[13]; /* mangled 8.3 name. */
1939 if (!name_to_8_3(fname,mangled_name,True,
1940 conn->params)) {
1941 /* Error - mangle failed ! */
1942 memset(mangled_name,'\0',12);
1944 mangled_name[12] = 0;
1945 len = srvstr_push(base_data, flags2,
1946 p+2, mangled_name, 24,
1947 STR_UPPER|STR_UNICODE);
1948 SSVAL(p, 0, len);
1949 if (len < 24) {
1950 memset(p + 2 + len,'\0',24 - len);
1952 SSVAL(p, 0, len);
1953 } else {
1954 memset(p,'\0',26);
1956 p += 26;
1957 SSVAL(p,0,0); p += 2; /* Reserved ? */
1958 SBVAL(p,0,file_index); p += 8;
1959 len = srvstr_push(base_data, flags2, p,
1960 fname, PTR_DIFF(end_data, p),
1961 STR_TERMINATE_ASCII);
1962 SIVAL(q,0,len);
1963 p += len;
1965 len = PTR_DIFF(p, pdata);
1966 pad = (len + (align-1)) & ~(align-1);
1968 * offset to the next entry, the caller
1969 * will overwrite it for the last entry
1970 * that's why we always include the padding
1972 SIVAL(pdata,0,pad);
1974 * set padding to zero
1976 if (do_pad) {
1977 memset(p, 0, pad - len);
1978 p = pdata + pad;
1979 } else {
1980 p = pdata + len;
1982 break;
1984 /* CIFS UNIX Extension. */
1986 case SMB_FIND_FILE_UNIX:
1987 case SMB_FIND_FILE_UNIX_INFO2:
1988 p+= 4;
1989 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1991 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1993 if (info_level == SMB_FIND_FILE_UNIX) {
1994 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1995 p = store_file_unix_basic(conn, p,
1996 NULL, &smb_fname->st);
1997 len = srvstr_push(base_data, flags2, p,
1998 fname, PTR_DIFF(end_data, p),
1999 STR_TERMINATE);
2000 } else {
2001 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2002 p = store_file_unix_basic_info2(conn, p,
2003 NULL, &smb_fname->st);
2004 nameptr = p;
2005 p += 4;
2006 len = srvstr_push(base_data, flags2, p, fname,
2007 PTR_DIFF(end_data, p), 0);
2008 SIVAL(nameptr, 0, len);
2011 p += len;
2013 len = PTR_DIFF(p, pdata);
2014 pad = (len + (align-1)) & ~(align-1);
2016 * offset to the next entry, the caller
2017 * will overwrite it for the last entry
2018 * that's why we always include the padding
2020 SIVAL(pdata,0,pad);
2022 * set padding to zero
2024 if (do_pad) {
2025 memset(p, 0, pad - len);
2026 p = pdata + pad;
2027 } else {
2028 p = pdata + len;
2030 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2032 break;
2034 default:
2035 return false;
2038 if (PTR_DIFF(p,pdata) > space_remaining) {
2039 *out_of_space = true;
2040 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2041 return false; /* Not finished - just out of space */
2044 /* Setup the last entry pointer, as an offset from base_data */
2045 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2046 /* Advance the data pointer to the next slot */
2047 *ppdata = p;
2049 return true;
2052 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2053 connection_struct *conn,
2054 struct dptr_struct *dirptr,
2055 uint16 flags2,
2056 const char *path_mask,
2057 uint32 dirtype,
2058 int info_level,
2059 int requires_resume_key,
2060 bool dont_descend,
2061 bool ask_sharemode,
2062 uint8_t align,
2063 bool do_pad,
2064 char **ppdata,
2065 char *base_data,
2066 char *end_data,
2067 int space_remaining,
2068 bool *out_of_space,
2069 bool *got_exact_match,
2070 int *_last_entry_off,
2071 struct ea_list *name_list)
2073 const char *p;
2074 const char *mask = NULL;
2075 long prev_dirpos = 0;
2076 uint32_t mode = 0;
2077 char *fname = NULL;
2078 struct smb_filename *smb_fname = NULL;
2079 struct smbd_dirptr_lanman2_state state;
2080 bool ok;
2081 uint64_t last_entry_off = 0;
2083 ZERO_STRUCT(state);
2084 state.conn = conn;
2085 state.info_level = info_level;
2086 state.check_mangled_names = lp_manglednames(conn->params);
2087 state.has_wild = dptr_has_wild(dirptr);
2088 state.got_exact_match = false;
2090 *out_of_space = false;
2091 *got_exact_match = false;
2093 p = strrchr_m(path_mask,'/');
2094 if(p != NULL) {
2095 if(p[1] == '\0') {
2096 mask = "*.*";
2097 } else {
2098 mask = p+1;
2100 } else {
2101 mask = path_mask;
2104 ok = smbd_dirptr_get_entry(ctx,
2105 dirptr,
2106 mask,
2107 dirtype,
2108 dont_descend,
2109 ask_sharemode,
2110 smbd_dirptr_lanman2_match_fn,
2111 smbd_dirptr_lanman2_mode_fn,
2112 &state,
2113 &fname,
2114 &smb_fname,
2115 &mode,
2116 &prev_dirpos);
2117 if (!ok) {
2118 return false;
2121 *got_exact_match = state.got_exact_match;
2123 ok = smbd_marshall_dir_entry(ctx,
2124 conn,
2125 flags2,
2126 info_level,
2127 name_list,
2128 state.check_mangled_names,
2129 requires_resume_key,
2130 mode,
2131 fname,
2132 smb_fname,
2133 space_remaining,
2134 align,
2135 do_pad,
2136 base_data,
2137 ppdata,
2138 end_data,
2139 out_of_space,
2140 &last_entry_off);
2141 TALLOC_FREE(fname);
2142 TALLOC_FREE(smb_fname);
2143 if (*out_of_space) {
2144 dptr_SeekDir(dirptr, prev_dirpos);
2145 return false;
2147 if (!ok) {
2148 return false;
2151 *_last_entry_off = last_entry_off;
2152 return true;
2155 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2156 connection_struct *conn,
2157 struct dptr_struct *dirptr,
2158 uint16 flags2,
2159 const char *path_mask,
2160 uint32 dirtype,
2161 int info_level,
2162 bool requires_resume_key,
2163 bool dont_descend,
2164 bool ask_sharemode,
2165 char **ppdata,
2166 char *base_data,
2167 char *end_data,
2168 int space_remaining,
2169 bool *out_of_space,
2170 bool *got_exact_match,
2171 int *last_entry_off,
2172 struct ea_list *name_list)
2174 uint8_t align = 4;
2175 const bool do_pad = true;
2177 if (info_level >= 1 && info_level <= 3) {
2178 /* No alignment on earlier info levels. */
2179 align = 1;
2182 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2183 path_mask, dirtype, info_level,
2184 requires_resume_key, dont_descend, ask_sharemode,
2185 align, do_pad,
2186 ppdata, base_data, end_data,
2187 space_remaining,
2188 out_of_space, got_exact_match,
2189 last_entry_off, name_list);
2192 /****************************************************************************
2193 Reply to a TRANS2_FINDFIRST.
2194 ****************************************************************************/
2196 static void call_trans2findfirst(connection_struct *conn,
2197 struct smb_request *req,
2198 char **pparams, int total_params,
2199 char **ppdata, int total_data,
2200 unsigned int max_data_bytes)
2202 /* We must be careful here that we don't return more than the
2203 allowed number of data bytes. If this means returning fewer than
2204 maxentries then so be it. We assume that the redirector has
2205 enough room for the fixed number of parameter bytes it has
2206 requested. */
2207 struct smb_filename *smb_dname = NULL;
2208 char *params = *pparams;
2209 char *pdata = *ppdata;
2210 char *data_end;
2211 uint32 dirtype;
2212 int maxentries;
2213 uint16 findfirst_flags;
2214 bool close_after_first;
2215 bool close_if_end;
2216 bool requires_resume_key;
2217 int info_level;
2218 char *directory = NULL;
2219 char *mask = NULL;
2220 char *p;
2221 int last_entry_off=0;
2222 int dptr_num = -1;
2223 int numentries = 0;
2224 int i;
2225 bool finished = False;
2226 bool dont_descend = False;
2227 bool out_of_space = False;
2228 int space_remaining;
2229 bool mask_contains_wcard = False;
2230 struct ea_list *ea_list = NULL;
2231 NTSTATUS ntstatus = NT_STATUS_OK;
2232 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2233 TALLOC_CTX *ctx = talloc_tos();
2234 struct dptr_struct *dirptr = NULL;
2235 struct smbd_server_connection *sconn = smbd_server_conn;
2237 if (total_params < 13) {
2238 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2239 goto out;
2242 dirtype = SVAL(params,0);
2243 maxentries = SVAL(params,2);
2244 findfirst_flags = SVAL(params,4);
2245 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2246 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2247 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2248 info_level = SVAL(params,6);
2250 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2251 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2252 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2253 info_level, max_data_bytes));
2255 if (!maxentries) {
2256 /* W2K3 seems to treat zero as 1. */
2257 maxentries = 1;
2260 switch (info_level) {
2261 case SMB_FIND_INFO_STANDARD:
2262 case SMB_FIND_EA_SIZE:
2263 case SMB_FIND_EA_LIST:
2264 case SMB_FIND_FILE_DIRECTORY_INFO:
2265 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2266 case SMB_FIND_FILE_NAMES_INFO:
2267 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2268 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2269 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2270 break;
2271 case SMB_FIND_FILE_UNIX:
2272 case SMB_FIND_FILE_UNIX_INFO2:
2273 /* Always use filesystem for UNIX mtime query. */
2274 ask_sharemode = false;
2275 if (!lp_unix_extensions()) {
2276 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2277 goto out;
2279 break;
2280 default:
2281 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2282 goto out;
2285 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2286 params+12, total_params - 12,
2287 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2288 if (!NT_STATUS_IS_OK(ntstatus)) {
2289 reply_nterror(req, ntstatus);
2290 goto out;
2293 ntstatus = filename_convert(ctx, conn,
2294 req->flags2 & FLAGS2_DFS_PATHNAMES,
2295 directory,
2296 (UCF_SAVE_LCOMP |
2297 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2298 &mask_contains_wcard,
2299 &smb_dname);
2300 if (!NT_STATUS_IS_OK(ntstatus)) {
2301 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2302 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2303 ERRSRV, ERRbadpath);
2304 goto out;
2306 reply_nterror(req, ntstatus);
2307 goto out;
2310 mask = smb_dname->original_lcomp;
2312 directory = smb_dname->base_name;
2314 p = strrchr_m(directory,'/');
2315 if(p == NULL) {
2316 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2317 if((directory[0] == '.') && (directory[1] == '\0')) {
2318 mask = talloc_strdup(ctx,"*");
2319 if (!mask) {
2320 reply_nterror(req, NT_STATUS_NO_MEMORY);
2321 goto out;
2323 mask_contains_wcard = True;
2325 directory = talloc_strdup(talloc_tos(), "./");
2326 if (!directory) {
2327 reply_nterror(req, NT_STATUS_NO_MEMORY);
2328 goto out;
2330 } else {
2331 *p = 0;
2334 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2336 if (info_level == SMB_FIND_EA_LIST) {
2337 uint32 ea_size;
2339 if (total_data < 4) {
2340 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2341 goto out;
2344 ea_size = IVAL(pdata,0);
2345 if (ea_size != total_data) {
2346 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2347 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2349 goto out;
2352 if (!lp_ea_support(SNUM(conn))) {
2353 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2354 goto out;
2357 /* Pull out the list of names. */
2358 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2359 if (!ea_list) {
2360 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2361 goto out;
2365 *ppdata = (char *)SMB_REALLOC(
2366 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2367 if(*ppdata == NULL ) {
2368 reply_nterror(req, NT_STATUS_NO_MEMORY);
2369 goto out;
2371 pdata = *ppdata;
2372 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2374 /* Realloc the params space */
2375 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2376 if (*pparams == NULL) {
2377 reply_nterror(req, NT_STATUS_NO_MEMORY);
2378 goto out;
2380 params = *pparams;
2382 /* Save the wildcard match and attribs we are using on this directory -
2383 needed as lanman2 assumes these are being saved between calls */
2385 ntstatus = dptr_create(conn,
2386 directory,
2387 False,
2388 True,
2389 req->smbpid,
2390 mask,
2391 mask_contains_wcard,
2392 dirtype,
2393 &dirptr);
2395 if (!NT_STATUS_IS_OK(ntstatus)) {
2396 reply_nterror(req, ntstatus);
2397 goto out;
2400 dptr_num = dptr_dnum(dirptr);
2401 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2403 /* Initialize per TRANS2_FIND_FIRST operation data */
2404 dptr_init_search_op(dirptr);
2406 /* We don't need to check for VOL here as this is returned by
2407 a different TRANS2 call. */
2409 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2410 directory,lp_dontdescend(SNUM(conn))));
2411 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2412 dont_descend = True;
2414 p = pdata;
2415 space_remaining = max_data_bytes;
2416 out_of_space = False;
2418 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2419 bool got_exact_match = False;
2421 /* this is a heuristic to avoid seeking the dirptr except when
2422 absolutely necessary. It allows for a filename of about 40 chars */
2423 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2424 out_of_space = True;
2425 finished = False;
2426 } else {
2427 finished = !get_lanman2_dir_entry(ctx,
2428 conn,
2429 dirptr,
2430 req->flags2,
2431 mask,dirtype,info_level,
2432 requires_resume_key,dont_descend,
2433 ask_sharemode,
2434 &p,pdata,data_end,
2435 space_remaining, &out_of_space,
2436 &got_exact_match,
2437 &last_entry_off, ea_list);
2440 if (finished && out_of_space)
2441 finished = False;
2443 if (!finished && !out_of_space)
2444 numentries++;
2447 * As an optimisation if we know we aren't looking
2448 * for a wildcard name (ie. the name matches the wildcard exactly)
2449 * then we can finish on any (first) match.
2450 * This speeds up large directory searches. JRA.
2453 if(got_exact_match)
2454 finished = True;
2456 /* Ensure space_remaining never goes -ve. */
2457 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2458 space_remaining = 0;
2459 out_of_space = true;
2460 } else {
2461 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2465 /* Check if we can close the dirptr */
2466 if(close_after_first || (finished && close_if_end)) {
2467 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2468 dptr_close(sconn, &dptr_num);
2472 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2473 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2474 * the protocol level is less than NT1. Tested with smbclient. JRA.
2475 * This should fix the OS/2 client bug #2335.
2478 if(numentries == 0) {
2479 dptr_close(sconn, &dptr_num);
2480 if (get_Protocol() < PROTOCOL_NT1) {
2481 reply_force_doserror(req, ERRDOS, ERRnofiles);
2482 goto out;
2483 } else {
2484 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2485 ERRDOS, ERRbadfile);
2486 goto out;
2490 /* At this point pdata points to numentries directory entries. */
2492 /* Set up the return parameter block */
2493 SSVAL(params,0,dptr_num);
2494 SSVAL(params,2,numentries);
2495 SSVAL(params,4,finished);
2496 SSVAL(params,6,0); /* Never an EA error */
2497 SSVAL(params,8,last_entry_off);
2499 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2500 max_data_bytes);
2502 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2503 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2504 if (!directory) {
2505 reply_nterror(req, NT_STATUS_NO_MEMORY);
2509 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2510 smb_fn_name(req->cmd),
2511 mask, directory, dirtype, numentries ) );
2514 * Force a name mangle here to ensure that the
2515 * mask as an 8.3 name is top of the mangled cache.
2516 * The reasons for this are subtle. Don't remove
2517 * this code unless you know what you are doing
2518 * (see PR#13758). JRA.
2521 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2522 char mangled_name[13];
2523 name_to_8_3(mask, mangled_name, True, conn->params);
2525 out:
2526 TALLOC_FREE(smb_dname);
2527 return;
2530 /****************************************************************************
2531 Reply to a TRANS2_FINDNEXT.
2532 ****************************************************************************/
2534 static void call_trans2findnext(connection_struct *conn,
2535 struct smb_request *req,
2536 char **pparams, int total_params,
2537 char **ppdata, int total_data,
2538 unsigned int max_data_bytes)
2540 /* We must be careful here that we don't return more than the
2541 allowed number of data bytes. If this means returning fewer than
2542 maxentries then so be it. We assume that the redirector has
2543 enough room for the fixed number of parameter bytes it has
2544 requested. */
2545 char *params = *pparams;
2546 char *pdata = *ppdata;
2547 char *data_end;
2548 int dptr_num;
2549 int maxentries;
2550 uint16 info_level;
2551 uint32 resume_key;
2552 uint16 findnext_flags;
2553 bool close_after_request;
2554 bool close_if_end;
2555 bool requires_resume_key;
2556 bool continue_bit;
2557 bool mask_contains_wcard = False;
2558 char *resume_name = NULL;
2559 const char *mask = NULL;
2560 const char *directory = NULL;
2561 char *p = NULL;
2562 uint16 dirtype;
2563 int numentries = 0;
2564 int i, last_entry_off=0;
2565 bool finished = False;
2566 bool dont_descend = False;
2567 bool out_of_space = False;
2568 int space_remaining;
2569 struct ea_list *ea_list = NULL;
2570 NTSTATUS ntstatus = NT_STATUS_OK;
2571 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2572 TALLOC_CTX *ctx = talloc_tos();
2573 struct dptr_struct *dirptr;
2574 struct smbd_server_connection *sconn = smbd_server_conn;
2576 if (total_params < 13) {
2577 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2578 return;
2581 dptr_num = SVAL(params,0);
2582 maxentries = SVAL(params,2);
2583 info_level = SVAL(params,4);
2584 resume_key = IVAL(params,6);
2585 findnext_flags = SVAL(params,10);
2586 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2587 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2588 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2589 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2591 if (!continue_bit) {
2592 /* We only need resume_name if continue_bit is zero. */
2593 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2594 params+12,
2595 total_params - 12, STR_TERMINATE, &ntstatus,
2596 &mask_contains_wcard);
2597 if (!NT_STATUS_IS_OK(ntstatus)) {
2598 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2599 complain (it thinks we're asking for the directory above the shared
2600 path or an invalid name). Catch this as the resume name is only compared, never used in
2601 a file access. JRA. */
2602 srvstr_pull_talloc(ctx, params, req->flags2,
2603 &resume_name, params+12,
2604 total_params - 12,
2605 STR_TERMINATE);
2607 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2608 reply_nterror(req, ntstatus);
2609 return;
2614 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2615 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2616 resume_key = %d resume name = %s continue=%d level = %d\n",
2617 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2618 requires_resume_key, resume_key,
2619 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2621 if (!maxentries) {
2622 /* W2K3 seems to treat zero as 1. */
2623 maxentries = 1;
2626 switch (info_level) {
2627 case SMB_FIND_INFO_STANDARD:
2628 case SMB_FIND_EA_SIZE:
2629 case SMB_FIND_EA_LIST:
2630 case SMB_FIND_FILE_DIRECTORY_INFO:
2631 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2632 case SMB_FIND_FILE_NAMES_INFO:
2633 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2634 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2635 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2636 break;
2637 case SMB_FIND_FILE_UNIX:
2638 case SMB_FIND_FILE_UNIX_INFO2:
2639 /* Always use filesystem for UNIX mtime query. */
2640 ask_sharemode = false;
2641 if (!lp_unix_extensions()) {
2642 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2643 return;
2645 break;
2646 default:
2647 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2648 return;
2651 if (info_level == SMB_FIND_EA_LIST) {
2652 uint32 ea_size;
2654 if (total_data < 4) {
2655 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2656 return;
2659 ea_size = IVAL(pdata,0);
2660 if (ea_size != total_data) {
2661 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2662 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2663 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2664 return;
2667 if (!lp_ea_support(SNUM(conn))) {
2668 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2669 return;
2672 /* Pull out the list of names. */
2673 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2674 if (!ea_list) {
2675 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2676 return;
2680 *ppdata = (char *)SMB_REALLOC(
2681 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2682 if(*ppdata == NULL) {
2683 reply_nterror(req, NT_STATUS_NO_MEMORY);
2684 return;
2687 pdata = *ppdata;
2688 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2690 /* Realloc the params space */
2691 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2692 if(*pparams == NULL ) {
2693 reply_nterror(req, NT_STATUS_NO_MEMORY);
2694 return;
2697 params = *pparams;
2699 /* Check that the dptr is valid */
2700 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2701 reply_nterror(req, STATUS_NO_MORE_FILES);
2702 return;
2705 directory = dptr_path(sconn, dptr_num);
2707 /* Get the wildcard mask from the dptr */
2708 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2709 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2710 reply_nterror(req, STATUS_NO_MORE_FILES);
2711 return;
2714 mask = p;
2716 /* Get the attr mask from the dptr */
2717 dirtype = dptr_attr(sconn, dptr_num);
2719 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2720 dptr_num, mask, dirtype,
2721 (long)dirptr,
2722 dptr_TellDir(dirptr)));
2724 /* Initialize per TRANS2_FIND_NEXT operation data */
2725 dptr_init_search_op(dirptr);
2727 /* We don't need to check for VOL here as this is returned by
2728 a different TRANS2 call. */
2730 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2731 directory,lp_dontdescend(SNUM(conn))));
2732 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2733 dont_descend = True;
2735 p = pdata;
2736 space_remaining = max_data_bytes;
2737 out_of_space = False;
2740 * Seek to the correct position. We no longer use the resume key but
2741 * depend on the last file name instead.
2744 if(!continue_bit && resume_name && *resume_name) {
2745 SMB_STRUCT_STAT st;
2747 long current_pos = 0;
2749 * Remember, name_to_8_3 is called by
2750 * get_lanman2_dir_entry(), so the resume name
2751 * could be mangled. Ensure we check the unmangled name.
2754 if (mangle_is_mangled(resume_name, conn->params)) {
2755 char *new_resume_name = NULL;
2756 mangle_lookup_name_from_8_3(ctx,
2757 resume_name,
2758 &new_resume_name,
2759 conn->params);
2760 if (new_resume_name) {
2761 resume_name = new_resume_name;
2766 * Fix for NT redirector problem triggered by resume key indexes
2767 * changing between directory scans. We now return a resume key of 0
2768 * and instead look for the filename to continue from (also given
2769 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2770 * findfirst/findnext (as is usual) then the directory pointer
2771 * should already be at the correct place.
2774 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2775 } /* end if resume_name && !continue_bit */
2777 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2778 bool got_exact_match = False;
2780 /* this is a heuristic to avoid seeking the dirptr except when
2781 absolutely necessary. It allows for a filename of about 40 chars */
2782 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2783 out_of_space = True;
2784 finished = False;
2785 } else {
2786 finished = !get_lanman2_dir_entry(ctx,
2787 conn,
2788 dirptr,
2789 req->flags2,
2790 mask,dirtype,info_level,
2791 requires_resume_key,dont_descend,
2792 ask_sharemode,
2793 &p,pdata,data_end,
2794 space_remaining, &out_of_space,
2795 &got_exact_match,
2796 &last_entry_off, ea_list);
2799 if (finished && out_of_space)
2800 finished = False;
2802 if (!finished && !out_of_space)
2803 numentries++;
2806 * As an optimisation if we know we aren't looking
2807 * for a wildcard name (ie. the name matches the wildcard exactly)
2808 * then we can finish on any (first) match.
2809 * This speeds up large directory searches. JRA.
2812 if(got_exact_match)
2813 finished = True;
2815 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2818 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2819 smb_fn_name(req->cmd),
2820 mask, directory, dirtype, numentries ) );
2822 /* Check if we can close the dirptr */
2823 if(close_after_request || (finished && close_if_end)) {
2824 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2825 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2828 /* Set up the return parameter block */
2829 SSVAL(params,0,numentries);
2830 SSVAL(params,2,finished);
2831 SSVAL(params,4,0); /* Never an EA error */
2832 SSVAL(params,6,last_entry_off);
2834 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2835 max_data_bytes);
2837 return;
2840 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2842 E_md4hash(lp_servicename(SNUM(conn)),objid);
2843 return objid;
2846 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2848 SMB_ASSERT(extended_info != NULL);
2850 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2851 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2852 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2853 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2854 #ifdef SAMBA_VERSION_REVISION
2855 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2856 #endif
2857 extended_info->samba_subversion = 0;
2858 #ifdef SAMBA_VERSION_RC_RELEASE
2859 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2860 #else
2861 #ifdef SAMBA_VERSION_PRE_RELEASE
2862 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2863 #endif
2864 #endif
2865 #ifdef SAMBA_VERSION_VENDOR_PATCH
2866 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2867 #endif
2868 extended_info->samba_gitcommitdate = 0;
2869 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2870 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2871 #endif
2873 memset(extended_info->samba_version_string, 0,
2874 sizeof(extended_info->samba_version_string));
2876 snprintf (extended_info->samba_version_string,
2877 sizeof(extended_info->samba_version_string),
2878 "%s", samba_version_string());
2881 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2882 TALLOC_CTX *mem_ctx,
2883 uint16_t info_level,
2884 uint16_t flags2,
2885 unsigned int max_data_bytes,
2886 char **ppdata,
2887 int *ret_data_len)
2889 char *pdata, *end_data;
2890 int data_len = 0, len;
2891 const char *vname = volume_label(SNUM(conn));
2892 int snum = SNUM(conn);
2893 char *fstype = lp_fstype(SNUM(conn));
2894 uint32 additional_flags = 0;
2895 struct smb_filename smb_fname_dot;
2896 SMB_STRUCT_STAT st;
2898 if (IS_IPC(conn)) {
2899 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2900 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2901 "info level (0x%x) on IPC$.\n",
2902 (unsigned int)info_level));
2903 return NT_STATUS_ACCESS_DENIED;
2907 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2909 ZERO_STRUCT(smb_fname_dot);
2910 smb_fname_dot.base_name = discard_const_p(char, ".");
2912 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2913 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2914 return map_nt_error_from_unix(errno);
2917 st = smb_fname_dot.st;
2919 *ppdata = (char *)SMB_REALLOC(
2920 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2921 if (*ppdata == NULL) {
2922 return NT_STATUS_NO_MEMORY;
2925 pdata = *ppdata;
2926 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2927 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2929 switch (info_level) {
2930 case SMB_INFO_ALLOCATION:
2932 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2933 data_len = 18;
2934 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2935 return map_nt_error_from_unix(errno);
2938 block_size = lp_block_size(snum);
2939 if (bsize < block_size) {
2940 uint64_t factor = block_size/bsize;
2941 bsize = block_size;
2942 dsize /= factor;
2943 dfree /= factor;
2945 if (bsize > block_size) {
2946 uint64_t factor = bsize/block_size;
2947 bsize = block_size;
2948 dsize *= factor;
2949 dfree *= factor;
2951 bytes_per_sector = 512;
2952 sectors_per_unit = bsize/bytes_per_sector;
2954 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2955 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2956 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2958 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2959 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2960 SIVAL(pdata,l1_cUnit,dsize);
2961 SIVAL(pdata,l1_cUnitAvail,dfree);
2962 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2963 break;
2966 case SMB_INFO_VOLUME:
2967 /* Return volume name */
2969 * Add volume serial number - hash of a combination of
2970 * the called hostname and the service name.
2972 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2974 * Win2k3 and previous mess this up by sending a name length
2975 * one byte short. I believe only older clients (OS/2 Win9x) use
2976 * this call so try fixing this by adding a terminating null to
2977 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2979 len = srvstr_push(
2980 pdata, flags2,
2981 pdata+l2_vol_szVolLabel, vname,
2982 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2983 STR_NOALIGN|STR_TERMINATE);
2984 SCVAL(pdata,l2_vol_cch,len);
2985 data_len = l2_vol_szVolLabel + len;
2986 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2987 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2988 len, vname));
2989 break;
2991 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2992 case SMB_FS_ATTRIBUTE_INFORMATION:
2994 additional_flags = 0;
2995 #if defined(HAVE_SYS_QUOTAS)
2996 additional_flags |= FILE_VOLUME_QUOTAS;
2997 #endif
2999 if(lp_nt_acl_support(SNUM(conn))) {
3000 additional_flags |= FILE_PERSISTENT_ACLS;
3003 /* Capabilities are filled in at connection time through STATVFS call */
3004 additional_flags |= conn->fs_capabilities;
3005 additional_flags |= lp_parm_int(conn->params->service,
3006 "share", "fake_fscaps",
3009 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3010 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3011 additional_flags); /* FS ATTRIBUTES */
3013 SIVAL(pdata,4,255); /* Max filename component length */
3014 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3015 and will think we can't do long filenames */
3016 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3017 PTR_DIFF(end_data, pdata+12),
3018 STR_UNICODE);
3019 SIVAL(pdata,8,len);
3020 data_len = 12 + len;
3021 break;
3023 case SMB_QUERY_FS_LABEL_INFO:
3024 case SMB_FS_LABEL_INFORMATION:
3025 len = srvstr_push(pdata, flags2, pdata+4, vname,
3026 PTR_DIFF(end_data, pdata+4), 0);
3027 data_len = 4 + len;
3028 SIVAL(pdata,0,len);
3029 break;
3031 case SMB_QUERY_FS_VOLUME_INFO:
3032 case SMB_FS_VOLUME_INFORMATION:
3035 * Add volume serial number - hash of a combination of
3036 * the called hostname and the service name.
3038 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3039 (str_checksum(get_local_machine_name())<<16));
3041 /* Max label len is 32 characters. */
3042 len = srvstr_push(pdata, flags2, pdata+18, vname,
3043 PTR_DIFF(end_data, pdata+18),
3044 STR_UNICODE);
3045 SIVAL(pdata,12,len);
3046 data_len = 18+len;
3048 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3049 (int)strlen(vname),vname, lp_servicename(snum)));
3050 break;
3052 case SMB_QUERY_FS_SIZE_INFO:
3053 case SMB_FS_SIZE_INFORMATION:
3055 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3056 data_len = 24;
3057 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3058 return map_nt_error_from_unix(errno);
3060 block_size = lp_block_size(snum);
3061 if (bsize < block_size) {
3062 uint64_t factor = block_size/bsize;
3063 bsize = block_size;
3064 dsize /= factor;
3065 dfree /= factor;
3067 if (bsize > block_size) {
3068 uint64_t factor = bsize/block_size;
3069 bsize = block_size;
3070 dsize *= factor;
3071 dfree *= factor;
3073 bytes_per_sector = 512;
3074 sectors_per_unit = bsize/bytes_per_sector;
3075 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3076 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3077 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3078 SBIG_UINT(pdata,0,dsize);
3079 SBIG_UINT(pdata,8,dfree);
3080 SIVAL(pdata,16,sectors_per_unit);
3081 SIVAL(pdata,20,bytes_per_sector);
3082 break;
3085 case SMB_FS_FULL_SIZE_INFORMATION:
3087 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3088 data_len = 32;
3089 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3090 return map_nt_error_from_unix(errno);
3092 block_size = lp_block_size(snum);
3093 if (bsize < block_size) {
3094 uint64_t factor = block_size/bsize;
3095 bsize = block_size;
3096 dsize /= factor;
3097 dfree /= factor;
3099 if (bsize > block_size) {
3100 uint64_t factor = bsize/block_size;
3101 bsize = block_size;
3102 dsize *= factor;
3103 dfree *= factor;
3105 bytes_per_sector = 512;
3106 sectors_per_unit = bsize/bytes_per_sector;
3107 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3108 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3109 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3110 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3111 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3112 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3113 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3114 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3115 break;
3118 case SMB_QUERY_FS_DEVICE_INFO:
3119 case SMB_FS_DEVICE_INFORMATION:
3120 data_len = 8;
3121 SIVAL(pdata,0,0); /* dev type */
3122 SIVAL(pdata,4,0); /* characteristics */
3123 break;
3125 #ifdef HAVE_SYS_QUOTAS
3126 case SMB_FS_QUOTA_INFORMATION:
3128 * what we have to send --metze:
3130 * Unknown1: 24 NULL bytes
3131 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3132 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3133 * Quota Flags: 2 byte :
3134 * Unknown3: 6 NULL bytes
3136 * 48 bytes total
3138 * details for Quota Flags:
3140 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3141 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3142 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3143 * 0x0001 Enable Quotas: enable quota for this fs
3147 /* we need to fake up a fsp here,
3148 * because its not send in this call
3150 files_struct fsp;
3151 SMB_NTQUOTA_STRUCT quotas;
3153 ZERO_STRUCT(fsp);
3154 ZERO_STRUCT(quotas);
3156 fsp.conn = conn;
3157 fsp.fnum = -1;
3159 /* access check */
3160 if (conn->server_info->utok.uid != sec_initial_uid()) {
3161 DEBUG(0,("set_user_quota: access_denied "
3162 "service [%s] user [%s]\n",
3163 lp_servicename(SNUM(conn)),
3164 conn->server_info->unix_name));
3165 return NT_STATUS_ACCESS_DENIED;
3168 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3169 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3170 return map_nt_error_from_unix(errno);
3173 data_len = 48;
3175 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3176 lp_servicename(SNUM(conn))));
3178 /* Unknown1 24 NULL bytes*/
3179 SBIG_UINT(pdata,0,(uint64_t)0);
3180 SBIG_UINT(pdata,8,(uint64_t)0);
3181 SBIG_UINT(pdata,16,(uint64_t)0);
3183 /* Default Soft Quota 8 bytes */
3184 SBIG_UINT(pdata,24,quotas.softlim);
3186 /* Default Hard Quota 8 bytes */
3187 SBIG_UINT(pdata,32,quotas.hardlim);
3189 /* Quota flag 2 bytes */
3190 SSVAL(pdata,40,quotas.qflags);
3192 /* Unknown3 6 NULL bytes */
3193 SSVAL(pdata,42,0);
3194 SIVAL(pdata,44,0);
3196 break;
3198 #endif /* HAVE_SYS_QUOTAS */
3199 case SMB_FS_OBJECTID_INFORMATION:
3201 unsigned char objid[16];
3202 struct smb_extended_info extended_info;
3203 memcpy(pdata,create_volume_objectid(conn, objid),16);
3204 samba_extended_info_version (&extended_info);
3205 SIVAL(pdata,16,extended_info.samba_magic);
3206 SIVAL(pdata,20,extended_info.samba_version);
3207 SIVAL(pdata,24,extended_info.samba_subversion);
3208 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3209 memcpy(pdata+36,extended_info.samba_version_string,28);
3210 data_len = 64;
3211 break;
3215 * Query the version and capabilities of the CIFS UNIX extensions
3216 * in use.
3219 case SMB_QUERY_CIFS_UNIX_INFO:
3221 bool large_write = lp_min_receive_file_size() &&
3222 !srv_is_signing_active(smbd_server_conn);
3223 bool large_read = !srv_is_signing_active(smbd_server_conn);
3224 int encrypt_caps = 0;
3226 if (!lp_unix_extensions()) {
3227 return NT_STATUS_INVALID_LEVEL;
3230 switch (conn->encrypt_level) {
3231 case 0:
3232 encrypt_caps = 0;
3233 break;
3234 case 1:
3235 case Auto:
3236 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3237 break;
3238 case Required:
3239 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3240 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3241 large_write = false;
3242 large_read = false;
3243 break;
3246 data_len = 12;
3247 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3248 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3250 /* We have POSIX ACLs, pathname, encryption,
3251 * large read/write, and locking capability. */
3253 SBIG_UINT(pdata,4,((uint64_t)(
3254 CIFS_UNIX_POSIX_ACLS_CAP|
3255 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3256 CIFS_UNIX_FCNTL_LOCKS_CAP|
3257 CIFS_UNIX_EXTATTR_CAP|
3258 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3259 encrypt_caps|
3260 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3261 (large_write ?
3262 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3263 break;
3266 case SMB_QUERY_POSIX_FS_INFO:
3268 int rc;
3269 vfs_statvfs_struct svfs;
3271 if (!lp_unix_extensions()) {
3272 return NT_STATUS_INVALID_LEVEL;
3275 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3277 if (!rc) {
3278 data_len = 56;
3279 SIVAL(pdata,0,svfs.OptimalTransferSize);
3280 SIVAL(pdata,4,svfs.BlockSize);
3281 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3282 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3283 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3284 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3285 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3286 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3287 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3288 #ifdef EOPNOTSUPP
3289 } else if (rc == EOPNOTSUPP) {
3290 return NT_STATUS_INVALID_LEVEL;
3291 #endif /* EOPNOTSUPP */
3292 } else {
3293 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3294 return NT_STATUS_DOS(ERRSRV, ERRerror);
3296 break;
3299 case SMB_QUERY_POSIX_WHOAMI:
3301 uint32_t flags = 0;
3302 uint32_t sid_bytes;
3303 int i;
3305 if (!lp_unix_extensions()) {
3306 return NT_STATUS_INVALID_LEVEL;
3309 if (max_data_bytes < 40) {
3310 return NT_STATUS_BUFFER_TOO_SMALL;
3313 /* We ARE guest if global_sid_Builtin_Guests is
3314 * in our list of SIDs.
3316 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3317 conn->server_info->ptok)) {
3318 flags |= SMB_WHOAMI_GUEST;
3321 /* We are NOT guest if global_sid_Authenticated_Users
3322 * is in our list of SIDs.
3324 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3325 conn->server_info->ptok)) {
3326 flags &= ~SMB_WHOAMI_GUEST;
3329 /* NOTE: 8 bytes for UID/GID, irrespective of native
3330 * platform size. This matches
3331 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3333 data_len = 4 /* flags */
3334 + 4 /* flag mask */
3335 + 8 /* uid */
3336 + 8 /* gid */
3337 + 4 /* ngroups */
3338 + 4 /* num_sids */
3339 + 4 /* SID bytes */
3340 + 4 /* pad/reserved */
3341 + (conn->server_info->utok.ngroups * 8)
3342 /* groups list */
3343 + (conn->server_info->ptok->num_sids *
3344 SID_MAX_SIZE)
3345 /* SID list */;
3347 SIVAL(pdata, 0, flags);
3348 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3349 SBIG_UINT(pdata, 8,
3350 (uint64_t)conn->server_info->utok.uid);
3351 SBIG_UINT(pdata, 16,
3352 (uint64_t)conn->server_info->utok.gid);
3355 if (data_len >= max_data_bytes) {
3356 /* Potential overflow, skip the GIDs and SIDs. */
3358 SIVAL(pdata, 24, 0); /* num_groups */
3359 SIVAL(pdata, 28, 0); /* num_sids */
3360 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3361 SIVAL(pdata, 36, 0); /* reserved */
3363 data_len = 40;
3364 break;
3367 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3368 SIVAL(pdata, 28, conn->server_info->num_sids);
3370 /* We walk the SID list twice, but this call is fairly
3371 * infrequent, and I don't expect that it's performance
3372 * sensitive -- jpeach
3374 for (i = 0, sid_bytes = 0;
3375 i < conn->server_info->ptok->num_sids; ++i) {
3376 sid_bytes += ndr_size_dom_sid(
3377 &conn->server_info->ptok->user_sids[i],
3378 NULL,
3382 /* SID list byte count */
3383 SIVAL(pdata, 32, sid_bytes);
3385 /* 4 bytes pad/reserved - must be zero */
3386 SIVAL(pdata, 36, 0);
3387 data_len = 40;
3389 /* GID list */
3390 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3391 SBIG_UINT(pdata, data_len,
3392 (uint64_t)conn->server_info->utok.groups[i]);
3393 data_len += 8;
3396 /* SID list */
3397 for (i = 0;
3398 i < conn->server_info->ptok->num_sids; ++i) {
3399 int sid_len = ndr_size_dom_sid(
3400 &conn->server_info->ptok->user_sids[i],
3401 NULL,
3404 sid_linearize(pdata + data_len, sid_len,
3405 &conn->server_info->ptok->user_sids[i]);
3406 data_len += sid_len;
3409 break;
3412 case SMB_MAC_QUERY_FS_INFO:
3414 * Thursby MAC extension... ONLY on NTFS filesystems
3415 * once we do streams then we don't need this
3417 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3418 data_len = 88;
3419 SIVAL(pdata,84,0x100); /* Don't support mac... */
3420 break;
3422 /* drop through */
3423 default:
3424 return NT_STATUS_INVALID_LEVEL;
3427 *ret_data_len = data_len;
3428 return NT_STATUS_OK;
3431 /****************************************************************************
3432 Reply to a TRANS2_QFSINFO (query filesystem info).
3433 ****************************************************************************/
3435 static void call_trans2qfsinfo(connection_struct *conn,
3436 struct smb_request *req,
3437 char **pparams, int total_params,
3438 char **ppdata, int total_data,
3439 unsigned int max_data_bytes)
3441 char *params = *pparams;
3442 uint16_t info_level;
3443 int data_len = 0;
3444 NTSTATUS status;
3446 if (total_params < 2) {
3447 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3448 return;
3451 info_level = SVAL(params,0);
3453 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3454 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3455 DEBUG(0,("call_trans2qfsinfo: encryption required "
3456 "and info level 0x%x sent.\n",
3457 (unsigned int)info_level));
3458 exit_server_cleanly("encryption required "
3459 "on connection");
3460 return;
3464 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3466 status = smbd_do_qfsinfo(conn, req,
3467 info_level,
3468 req->flags2,
3469 max_data_bytes,
3470 ppdata, &data_len);
3471 if (!NT_STATUS_IS_OK(status)) {
3472 reply_nterror(req, status);
3473 return;
3476 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3477 max_data_bytes);
3479 DEBUG( 4, ( "%s info_level = %d\n",
3480 smb_fn_name(req->cmd), info_level) );
3482 return;
3485 /****************************************************************************
3486 Reply to a TRANS2_SETFSINFO (set filesystem info).
3487 ****************************************************************************/
3489 static void call_trans2setfsinfo(connection_struct *conn,
3490 struct smb_request *req,
3491 char **pparams, int total_params,
3492 char **ppdata, int total_data,
3493 unsigned int max_data_bytes)
3495 char *pdata = *ppdata;
3496 char *params = *pparams;
3497 uint16 info_level;
3499 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3501 /* */
3502 if (total_params < 4) {
3503 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3504 total_params));
3505 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3506 return;
3509 info_level = SVAL(params,2);
3511 if (IS_IPC(conn)) {
3512 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3513 info_level != SMB_SET_CIFS_UNIX_INFO) {
3514 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3515 "info level (0x%x) on IPC$.\n",
3516 (unsigned int)info_level));
3517 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3518 return;
3522 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3523 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3524 DEBUG(0,("call_trans2setfsinfo: encryption required "
3525 "and info level 0x%x sent.\n",
3526 (unsigned int)info_level));
3527 exit_server_cleanly("encryption required "
3528 "on connection");
3529 return;
3533 switch(info_level) {
3534 case SMB_SET_CIFS_UNIX_INFO:
3536 uint16 client_unix_major;
3537 uint16 client_unix_minor;
3538 uint32 client_unix_cap_low;
3539 uint32 client_unix_cap_high;
3541 if (!lp_unix_extensions()) {
3542 reply_nterror(req,
3543 NT_STATUS_INVALID_LEVEL);
3544 return;
3547 /* There should be 12 bytes of capabilities set. */
3548 if (total_data < 8) {
3549 reply_nterror(
3550 req,
3551 NT_STATUS_INVALID_PARAMETER);
3552 return;
3554 client_unix_major = SVAL(pdata,0);
3555 client_unix_minor = SVAL(pdata,2);
3556 client_unix_cap_low = IVAL(pdata,4);
3557 client_unix_cap_high = IVAL(pdata,8);
3558 /* Just print these values for now. */
3559 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3560 cap_low = 0x%x, cap_high = 0x%x\n",
3561 (unsigned int)client_unix_major,
3562 (unsigned int)client_unix_minor,
3563 (unsigned int)client_unix_cap_low,
3564 (unsigned int)client_unix_cap_high ));
3566 /* Here is where we must switch to posix pathname processing... */
3567 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3568 lp_set_posix_pathnames();
3569 mangle_change_to_posix();
3572 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3573 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3574 /* Client that knows how to do posix locks,
3575 * but not posix open/mkdir operations. Set a
3576 * default type for read/write checks. */
3578 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3581 break;
3584 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3586 NTSTATUS status;
3587 size_t param_len = 0;
3588 size_t data_len = total_data;
3590 if (!lp_unix_extensions()) {
3591 reply_nterror(
3592 req,
3593 NT_STATUS_INVALID_LEVEL);
3594 return;
3597 if (lp_smb_encrypt(SNUM(conn)) == false) {
3598 reply_nterror(
3599 req,
3600 NT_STATUS_NOT_SUPPORTED);
3601 return;
3604 DEBUG( 4,("call_trans2setfsinfo: "
3605 "request transport encryption.\n"));
3607 status = srv_request_encryption_setup(conn,
3608 (unsigned char **)ppdata,
3609 &data_len,
3610 (unsigned char **)pparams,
3611 &param_len);
3613 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3614 !NT_STATUS_IS_OK(status)) {
3615 reply_nterror(req, status);
3616 return;
3619 send_trans2_replies(conn, req,
3620 *pparams,
3621 param_len,
3622 *ppdata,
3623 data_len,
3624 max_data_bytes);
3626 if (NT_STATUS_IS_OK(status)) {
3627 /* Server-side transport
3628 * encryption is now *on*. */
3629 status = srv_encryption_start(conn);
3630 if (!NT_STATUS_IS_OK(status)) {
3631 exit_server_cleanly(
3632 "Failure in setting "
3633 "up encrypted transport");
3636 return;
3639 case SMB_FS_QUOTA_INFORMATION:
3641 files_struct *fsp = NULL;
3642 SMB_NTQUOTA_STRUCT quotas;
3644 ZERO_STRUCT(quotas);
3646 /* access check */
3647 if ((conn->server_info->utok.uid != sec_initial_uid())
3648 ||!CAN_WRITE(conn)) {
3649 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3650 lp_servicename(SNUM(conn)),
3651 conn->server_info->unix_name));
3652 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3653 return;
3656 /* note: normaly there're 48 bytes,
3657 * but we didn't use the last 6 bytes for now
3658 * --metze
3660 fsp = file_fsp(req, SVAL(params,0));
3662 if (!check_fsp_ntquota_handle(conn, req,
3663 fsp)) {
3664 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3665 reply_nterror(
3666 req, NT_STATUS_INVALID_HANDLE);
3667 return;
3670 if (total_data < 42) {
3671 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3672 total_data));
3673 reply_nterror(
3674 req,
3675 NT_STATUS_INVALID_PARAMETER);
3676 return;
3679 /* unknown_1 24 NULL bytes in pdata*/
3681 /* the soft quotas 8 bytes (uint64_t)*/
3682 quotas.softlim = (uint64_t)IVAL(pdata,24);
3683 #ifdef LARGE_SMB_OFF_T
3684 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3685 #else /* LARGE_SMB_OFF_T */
3686 if ((IVAL(pdata,28) != 0)&&
3687 ((quotas.softlim != 0xFFFFFFFF)||
3688 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3689 /* more than 32 bits? */
3690 reply_nterror(
3691 req,
3692 NT_STATUS_INVALID_PARAMETER);
3693 return;
3695 #endif /* LARGE_SMB_OFF_T */
3697 /* the hard quotas 8 bytes (uint64_t)*/
3698 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3699 #ifdef LARGE_SMB_OFF_T
3700 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3701 #else /* LARGE_SMB_OFF_T */
3702 if ((IVAL(pdata,36) != 0)&&
3703 ((quotas.hardlim != 0xFFFFFFFF)||
3704 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3705 /* more than 32 bits? */
3706 reply_nterror(
3707 req,
3708 NT_STATUS_INVALID_PARAMETER);
3709 return;
3711 #endif /* LARGE_SMB_OFF_T */
3713 /* quota_flags 2 bytes **/
3714 quotas.qflags = SVAL(pdata,40);
3716 /* unknown_2 6 NULL bytes follow*/
3718 /* now set the quotas */
3719 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3720 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3721 reply_nterror(req, map_nt_error_from_unix(errno));
3722 return;
3725 break;
3727 default:
3728 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3729 info_level));
3730 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3731 return;
3732 break;
3736 * sending this reply works fine,
3737 * but I'm not sure it's the same
3738 * like windows do...
3739 * --metze
3741 reply_outbuf(req, 10, 0);
3744 #if defined(HAVE_POSIX_ACLS)
3745 /****************************************************************************
3746 Utility function to count the number of entries in a POSIX acl.
3747 ****************************************************************************/
3749 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3751 unsigned int ace_count = 0;
3752 int entry_id = SMB_ACL_FIRST_ENTRY;
3753 SMB_ACL_ENTRY_T entry;
3755 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3756 /* get_next... */
3757 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3758 entry_id = SMB_ACL_NEXT_ENTRY;
3760 ace_count++;
3762 return ace_count;
3765 /****************************************************************************
3766 Utility function to marshall a POSIX acl into wire format.
3767 ****************************************************************************/
3769 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3771 int entry_id = SMB_ACL_FIRST_ENTRY;
3772 SMB_ACL_ENTRY_T entry;
3774 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3775 SMB_ACL_TAG_T tagtype;
3776 SMB_ACL_PERMSET_T permset;
3777 unsigned char perms = 0;
3778 unsigned int own_grp;
3780 /* get_next... */
3781 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3782 entry_id = SMB_ACL_NEXT_ENTRY;
3785 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3786 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3787 return False;
3790 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3791 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3792 return False;
3795 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3796 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3797 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3799 SCVAL(pdata,1,perms);
3801 switch (tagtype) {
3802 case SMB_ACL_USER_OBJ:
3803 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3804 own_grp = (unsigned int)pst->st_ex_uid;
3805 SIVAL(pdata,2,own_grp);
3806 SIVAL(pdata,6,0);
3807 break;
3808 case SMB_ACL_USER:
3810 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3811 if (!puid) {
3812 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3813 return False;
3815 own_grp = (unsigned int)*puid;
3816 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3817 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3818 SIVAL(pdata,2,own_grp);
3819 SIVAL(pdata,6,0);
3820 break;
3822 case SMB_ACL_GROUP_OBJ:
3823 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3824 own_grp = (unsigned int)pst->st_ex_gid;
3825 SIVAL(pdata,2,own_grp);
3826 SIVAL(pdata,6,0);
3827 break;
3828 case SMB_ACL_GROUP:
3830 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3831 if (!pgid) {
3832 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3833 return False;
3835 own_grp = (unsigned int)*pgid;
3836 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3837 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3838 SIVAL(pdata,2,own_grp);
3839 SIVAL(pdata,6,0);
3840 break;
3842 case SMB_ACL_MASK:
3843 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3844 SIVAL(pdata,2,0xFFFFFFFF);
3845 SIVAL(pdata,6,0xFFFFFFFF);
3846 break;
3847 case SMB_ACL_OTHER:
3848 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3849 SIVAL(pdata,2,0xFFFFFFFF);
3850 SIVAL(pdata,6,0xFFFFFFFF);
3851 break;
3852 default:
3853 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3854 return False;
3856 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3859 return True;
3861 #endif
3863 /****************************************************************************
3864 Store the FILE_UNIX_BASIC info.
3865 ****************************************************************************/
3867 static char *store_file_unix_basic(connection_struct *conn,
3868 char *pdata,
3869 files_struct *fsp,
3870 const SMB_STRUCT_STAT *psbuf)
3872 uint64_t file_index = get_FileIndex(conn, psbuf);
3874 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3875 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3877 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3878 pdata += 8;
3880 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3881 pdata += 8;
3883 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3884 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3885 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3886 pdata += 24;
3888 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3889 SIVAL(pdata,4,0);
3890 pdata += 8;
3892 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3893 SIVAL(pdata,4,0);
3894 pdata += 8;
3896 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3897 pdata += 4;
3899 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3900 SIVAL(pdata,4,0);
3901 pdata += 8;
3903 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3904 SIVAL(pdata,4,0);
3905 pdata += 8;
3907 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3908 pdata += 8;
3910 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3911 SIVAL(pdata,4,0);
3912 pdata += 8;
3914 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3915 SIVAL(pdata,4,0);
3916 pdata += 8;
3918 return pdata;
3921 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3922 * the chflags(2) (or equivalent) flags.
3924 * XXX: this really should be behind the VFS interface. To do this, we would
3925 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3926 * Each VFS module could then implement its own mapping as appropriate for the
3927 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3929 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3930 info2_flags_map[] =
3932 #ifdef UF_NODUMP
3933 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3934 #endif
3936 #ifdef UF_IMMUTABLE
3937 { UF_IMMUTABLE, EXT_IMMUTABLE },
3938 #endif
3940 #ifdef UF_APPEND
3941 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3942 #endif
3944 #ifdef UF_HIDDEN
3945 { UF_HIDDEN, EXT_HIDDEN },
3946 #endif
3948 /* Do not remove. We need to guarantee that this array has at least one
3949 * entry to build on HP-UX.
3951 { 0, 0 }
3955 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3956 uint32 *smb_fflags, uint32 *smb_fmask)
3958 int i;
3960 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3961 *smb_fmask |= info2_flags_map[i].smb_fflag;
3962 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3963 *smb_fflags |= info2_flags_map[i].smb_fflag;
3968 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3969 const uint32 smb_fflags,
3970 const uint32 smb_fmask,
3971 int *stat_fflags)
3973 uint32 max_fmask = 0;
3974 int i;
3976 *stat_fflags = psbuf->st_ex_flags;
3978 /* For each flags requested in smb_fmask, check the state of the
3979 * corresponding flag in smb_fflags and set or clear the matching
3980 * stat flag.
3983 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3984 max_fmask |= info2_flags_map[i].smb_fflag;
3985 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3986 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3987 *stat_fflags |= info2_flags_map[i].stat_fflag;
3988 } else {
3989 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3994 /* If smb_fmask is asking to set any bits that are not supported by
3995 * our flag mappings, we should fail.
3997 if ((smb_fmask & max_fmask) != smb_fmask) {
3998 return False;
4001 return True;
4005 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4006 * of file flags and birth (create) time.
4008 static char *store_file_unix_basic_info2(connection_struct *conn,
4009 char *pdata,
4010 files_struct *fsp,
4011 const SMB_STRUCT_STAT *psbuf)
4013 uint32 file_flags = 0;
4014 uint32 flags_mask = 0;
4016 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4018 /* Create (birth) time 64 bit */
4019 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4020 pdata += 8;
4022 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4023 SIVAL(pdata, 0, file_flags); /* flags */
4024 SIVAL(pdata, 4, flags_mask); /* mask */
4025 pdata += 8;
4027 return pdata;
4030 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4031 const struct stream_struct *streams,
4032 char *data,
4033 unsigned int max_data_bytes,
4034 unsigned int *data_size)
4036 unsigned int i;
4037 unsigned int ofs = 0;
4039 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4040 unsigned int next_offset;
4041 size_t namelen;
4042 smb_ucs2_t *namebuf;
4044 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4045 streams[i].name, &namelen) ||
4046 namelen <= 2)
4048 return NT_STATUS_INVALID_PARAMETER;
4052 * name_buf is now null-terminated, we need to marshall as not
4053 * terminated
4056 namelen -= 2;
4058 SIVAL(data, ofs+4, namelen);
4059 SOFF_T(data, ofs+8, streams[i].size);
4060 SOFF_T(data, ofs+16, streams[i].alloc_size);
4061 memcpy(data+ofs+24, namebuf, namelen);
4062 TALLOC_FREE(namebuf);
4064 next_offset = ofs + 24 + namelen;
4066 if (i == num_streams-1) {
4067 SIVAL(data, ofs, 0);
4069 else {
4070 unsigned int align = ndr_align_size(next_offset, 8);
4072 memset(data+next_offset, 0, align);
4073 next_offset += align;
4075 SIVAL(data, ofs, next_offset - ofs);
4076 ofs = next_offset;
4079 ofs = next_offset;
4082 *data_size = ofs;
4084 return NT_STATUS_OK;
4087 /****************************************************************************
4088 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4089 ****************************************************************************/
4091 static void call_trans2qpipeinfo(connection_struct *conn,
4092 struct smb_request *req,
4093 unsigned int tran_call,
4094 char **pparams, int total_params,
4095 char **ppdata, int total_data,
4096 unsigned int max_data_bytes)
4098 char *params = *pparams;
4099 char *pdata = *ppdata;
4100 unsigned int data_size = 0;
4101 unsigned int param_size = 2;
4102 uint16 info_level;
4103 files_struct *fsp;
4105 if (!params) {
4106 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4107 return;
4110 if (total_params < 4) {
4111 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4112 return;
4115 fsp = file_fsp(req, SVAL(params,0));
4116 if (!fsp_is_np(fsp)) {
4117 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4118 return;
4121 info_level = SVAL(params,2);
4123 *pparams = (char *)SMB_REALLOC(*pparams,2);
4124 if (*pparams == NULL) {
4125 reply_nterror(req, NT_STATUS_NO_MEMORY);
4126 return;
4128 params = *pparams;
4129 SSVAL(params,0,0);
4130 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4131 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4132 if (*ppdata == NULL ) {
4133 reply_nterror(req, NT_STATUS_NO_MEMORY);
4134 return;
4136 pdata = *ppdata;
4138 switch (info_level) {
4139 case SMB_FILE_STANDARD_INFORMATION:
4140 memset(pdata,0,24);
4141 SOFF_T(pdata,0,4096LL);
4142 SIVAL(pdata,16,1);
4143 SIVAL(pdata,20,1);
4144 data_size = 24;
4145 break;
4147 default:
4148 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4149 return;
4152 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4153 max_data_bytes);
4155 return;
4158 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4159 TALLOC_CTX *mem_ctx,
4160 uint16_t info_level,
4161 files_struct *fsp,
4162 struct smb_filename *smb_fname,
4163 bool delete_pending,
4164 struct timespec write_time_ts,
4165 bool ms_dfs_link,
4166 struct ea_list *ea_list,
4167 int lock_data_count,
4168 char *lock_data,
4169 uint16_t flags2,
4170 unsigned int max_data_bytes,
4171 char **ppdata,
4172 unsigned int *pdata_size)
4174 char *pdata = *ppdata;
4175 char *dstart, *dend;
4176 unsigned int data_size;
4177 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4178 time_t create_time, mtime, atime, c_time;
4179 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4180 char *p;
4181 char *base_name;
4182 char *dos_fname;
4183 int mode;
4184 int nlink;
4185 NTSTATUS status;
4186 uint64_t file_size = 0;
4187 uint64_t pos = 0;
4188 uint64_t allocation_size = 0;
4189 uint64_t file_index = 0;
4190 uint32_t access_mask = 0;
4192 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4193 return NT_STATUS_INVALID_LEVEL;
4196 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4197 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4198 info_level, max_data_bytes));
4200 if (ms_dfs_link) {
4201 mode = dos_mode_msdfs(conn, smb_fname);
4202 } else {
4203 mode = dos_mode(conn, smb_fname);
4206 nlink = psbuf->st_ex_nlink;
4208 if (nlink && (mode&aDIR)) {
4209 nlink = 1;
4212 if ((nlink > 0) && delete_pending) {
4213 nlink -= 1;
4216 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4217 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4218 if (*ppdata == NULL) {
4219 return NT_STATUS_NO_MEMORY;
4221 pdata = *ppdata;
4222 dstart = pdata;
4223 dend = dstart + data_size - 1;
4225 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4226 update_stat_ex_mtime(psbuf, write_time_ts);
4229 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4230 mtime_ts = psbuf->st_ex_mtime;
4231 atime_ts = psbuf->st_ex_atime;
4232 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4234 if (lp_dos_filetime_resolution(SNUM(conn))) {
4235 dos_filetime_timespec(&create_time_ts);
4236 dos_filetime_timespec(&mtime_ts);
4237 dos_filetime_timespec(&atime_ts);
4238 dos_filetime_timespec(&ctime_ts);
4241 create_time = convert_timespec_to_time_t(create_time_ts);
4242 mtime = convert_timespec_to_time_t(mtime_ts);
4243 atime = convert_timespec_to_time_t(atime_ts);
4244 c_time = convert_timespec_to_time_t(ctime_ts);
4246 p = strrchr_m(smb_fname->base_name,'/');
4247 if (!p)
4248 base_name = smb_fname->base_name;
4249 else
4250 base_name = p+1;
4252 /* NT expects the name to be in an exact form of the *full*
4253 filename. See the trans2 torture test */
4254 if (ISDOT(base_name)) {
4255 dos_fname = talloc_strdup(mem_ctx, "\\");
4256 if (!dos_fname) {
4257 return NT_STATUS_NO_MEMORY;
4259 } else {
4260 dos_fname = talloc_asprintf(mem_ctx,
4261 "\\%s",
4262 smb_fname->base_name);
4263 if (!dos_fname) {
4264 return NT_STATUS_NO_MEMORY;
4266 if (is_ntfs_stream_smb_fname(smb_fname)) {
4267 dos_fname = talloc_asprintf(dos_fname, "%s",
4268 smb_fname->stream_name);
4269 if (!dos_fname) {
4270 return NT_STATUS_NO_MEMORY;
4274 string_replace(dos_fname, '/', '\\');
4277 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4279 if (!fsp) {
4280 /* Do we have this path open ? */
4281 files_struct *fsp1;
4282 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4283 fsp1 = file_find_di_first(fileid);
4284 if (fsp1 && fsp1->initial_allocation_size) {
4285 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4289 if (!(mode & aDIR)) {
4290 file_size = get_file_size_stat(psbuf);
4293 if (fsp) {
4294 pos = fsp->fh->position_information;
4297 if (fsp) {
4298 access_mask = fsp->access_mask;
4299 } else {
4300 /* GENERIC_EXECUTE mapping from Windows */
4301 access_mask = 0x12019F;
4304 /* This should be an index number - looks like
4305 dev/ino to me :-)
4307 I think this causes us to fail the IFSKIT
4308 BasicFileInformationTest. -tpot */
4309 file_index = get_FileIndex(conn, psbuf);
4311 switch (info_level) {
4312 case SMB_INFO_STANDARD:
4313 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4314 data_size = 22;
4315 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4316 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4317 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4318 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4319 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4320 SSVAL(pdata,l1_attrFile,mode);
4321 break;
4323 case SMB_INFO_QUERY_EA_SIZE:
4325 unsigned int ea_size =
4326 estimate_ea_size(conn, fsp,
4327 smb_fname->base_name);
4328 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4329 data_size = 26;
4330 srv_put_dos_date2(pdata,0,create_time);
4331 srv_put_dos_date2(pdata,4,atime);
4332 srv_put_dos_date2(pdata,8,mtime); /* write time */
4333 SIVAL(pdata,12,(uint32)file_size);
4334 SIVAL(pdata,16,(uint32)allocation_size);
4335 SSVAL(pdata,20,mode);
4336 SIVAL(pdata,22,ea_size);
4337 break;
4340 case SMB_INFO_IS_NAME_VALID:
4341 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4342 if (fsp) {
4343 /* os/2 needs this ? really ?*/
4344 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4346 /* This is only reached for qpathinfo */
4347 data_size = 0;
4348 break;
4350 case SMB_INFO_QUERY_EAS_FROM_LIST:
4352 size_t total_ea_len = 0;
4353 struct ea_list *ea_file_list = NULL;
4355 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4357 ea_file_list =
4358 get_ea_list_from_file(mem_ctx, conn, fsp,
4359 smb_fname->base_name,
4360 &total_ea_len);
4361 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4363 if (!ea_list || (total_ea_len > data_size)) {
4364 data_size = 4;
4365 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4366 break;
4369 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4370 break;
4373 case SMB_INFO_QUERY_ALL_EAS:
4375 /* We have data_size bytes to put EA's into. */
4376 size_t total_ea_len = 0;
4378 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4380 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4381 smb_fname->base_name,
4382 &total_ea_len);
4383 if (!ea_list || (total_ea_len > data_size)) {
4384 data_size = 4;
4385 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4386 break;
4389 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4390 break;
4393 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4395 /* This is FileFullEaInformation - 0xF which maps to
4396 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4398 /* We have data_size bytes to put EA's into. */
4399 size_t total_ea_len = 0;
4400 struct ea_list *ea_file_list = NULL;
4402 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4404 /*TODO: add filtering and index handling */
4406 ea_file_list =
4407 get_ea_list_from_file(mem_ctx, conn, fsp,
4408 smb_fname->base_name,
4409 &total_ea_len);
4410 if (!ea_file_list) {
4411 return NT_STATUS_NO_EAS_ON_FILE;
4414 status = fill_ea_chained_buffer(mem_ctx,
4415 pdata,
4416 data_size,
4417 &data_size,
4418 conn, ea_file_list);
4419 if (!NT_STATUS_IS_OK(status)) {
4420 return status;
4422 break;
4425 case SMB_FILE_BASIC_INFORMATION:
4426 case SMB_QUERY_FILE_BASIC_INFO:
4428 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4429 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4430 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4431 } else {
4432 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4433 data_size = 40;
4434 SIVAL(pdata,36,0);
4436 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4437 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4438 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4439 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4440 SIVAL(pdata,32,mode);
4442 DEBUG(5,("SMB_QFBI - "));
4443 DEBUG(5,("create: %s ", ctime(&create_time)));
4444 DEBUG(5,("access: %s ", ctime(&atime)));
4445 DEBUG(5,("write: %s ", ctime(&mtime)));
4446 DEBUG(5,("change: %s ", ctime(&c_time)));
4447 DEBUG(5,("mode: %x\n", mode));
4448 break;
4450 case SMB_FILE_STANDARD_INFORMATION:
4451 case SMB_QUERY_FILE_STANDARD_INFO:
4453 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4454 data_size = 24;
4455 SOFF_T(pdata,0,allocation_size);
4456 SOFF_T(pdata,8,file_size);
4457 SIVAL(pdata,16,nlink);
4458 SCVAL(pdata,20,delete_pending?1:0);
4459 SCVAL(pdata,21,(mode&aDIR)?1:0);
4460 SSVAL(pdata,22,0); /* Padding. */
4461 break;
4463 case SMB_FILE_EA_INFORMATION:
4464 case SMB_QUERY_FILE_EA_INFO:
4466 unsigned int ea_size =
4467 estimate_ea_size(conn, fsp, smb_fname->base_name);
4468 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4469 data_size = 4;
4470 SIVAL(pdata,0,ea_size);
4471 break;
4474 /* Get the 8.3 name - used if NT SMB was negotiated. */
4475 case SMB_QUERY_FILE_ALT_NAME_INFO:
4476 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4478 int len;
4479 char mangled_name[13];
4480 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4481 if (!name_to_8_3(base_name,mangled_name,
4482 True,conn->params)) {
4483 return NT_STATUS_NO_MEMORY;
4485 len = srvstr_push(dstart, flags2,
4486 pdata+4, mangled_name,
4487 PTR_DIFF(dend, pdata+4),
4488 STR_UNICODE);
4489 data_size = 4 + len;
4490 SIVAL(pdata,0,len);
4491 break;
4494 case SMB_QUERY_FILE_NAME_INFO:
4496 int len;
4498 this must be *exactly* right for ACLs on mapped drives to work
4500 len = srvstr_push(dstart, flags2,
4501 pdata+4, dos_fname,
4502 PTR_DIFF(dend, pdata+4),
4503 STR_UNICODE);
4504 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4505 data_size = 4 + len;
4506 SIVAL(pdata,0,len);
4507 break;
4510 case SMB_FILE_ALLOCATION_INFORMATION:
4511 case SMB_QUERY_FILE_ALLOCATION_INFO:
4512 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4513 data_size = 8;
4514 SOFF_T(pdata,0,allocation_size);
4515 break;
4517 case SMB_FILE_END_OF_FILE_INFORMATION:
4518 case SMB_QUERY_FILE_END_OF_FILEINFO:
4519 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4520 data_size = 8;
4521 SOFF_T(pdata,0,file_size);
4522 break;
4524 case SMB_QUERY_FILE_ALL_INFO:
4525 case SMB_FILE_ALL_INFORMATION:
4527 int len;
4528 unsigned int ea_size =
4529 estimate_ea_size(conn, fsp, smb_fname->base_name);
4530 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4531 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4532 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4533 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4534 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4535 SIVAL(pdata,32,mode);
4536 SIVAL(pdata,36,0); /* padding. */
4537 pdata += 40;
4538 SOFF_T(pdata,0,allocation_size);
4539 SOFF_T(pdata,8,file_size);
4540 SIVAL(pdata,16,nlink);
4541 SCVAL(pdata,20,delete_pending);
4542 SCVAL(pdata,21,(mode&aDIR)?1:0);
4543 SSVAL(pdata,22,0);
4544 pdata += 24;
4545 SIVAL(pdata,0,ea_size);
4546 pdata += 4; /* EA info */
4547 len = srvstr_push(dstart, flags2,
4548 pdata+4, dos_fname,
4549 PTR_DIFF(dend, pdata+4),
4550 STR_UNICODE);
4551 SIVAL(pdata,0,len);
4552 pdata += 4 + len;
4553 data_size = PTR_DIFF(pdata,(*ppdata));
4554 break;
4557 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4559 int len;
4560 unsigned int ea_size =
4561 estimate_ea_size(conn, fsp, smb_fname->base_name);
4562 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4563 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4564 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4565 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4566 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4567 SIVAL(pdata, 0x20, mode);
4568 SIVAL(pdata, 0x24, 0); /* padding. */
4569 SBVAL(pdata, 0x28, allocation_size);
4570 SBVAL(pdata, 0x30, file_size);
4571 SIVAL(pdata, 0x38, nlink);
4572 SCVAL(pdata, 0x3C, delete_pending);
4573 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4574 SSVAL(pdata, 0x3E, 0); /* padding */
4575 SBVAL(pdata, 0x40, file_index);
4576 SIVAL(pdata, 0x48, ea_size);
4577 SIVAL(pdata, 0x4C, access_mask);
4578 SBVAL(pdata, 0x50, pos);
4579 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4580 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4582 pdata += 0x60;
4584 len = srvstr_push(dstart, flags2,
4585 pdata+4, dos_fname,
4586 PTR_DIFF(dend, pdata+4),
4587 STR_UNICODE);
4588 SIVAL(pdata,0,len);
4589 pdata += 4 + len;
4590 data_size = PTR_DIFF(pdata,(*ppdata));
4591 break;
4593 case SMB_FILE_INTERNAL_INFORMATION:
4595 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4596 SBVAL(pdata, 0, file_index);
4597 data_size = 8;
4598 break;
4600 case SMB_FILE_ACCESS_INFORMATION:
4601 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4602 SIVAL(pdata, 0, access_mask);
4603 data_size = 4;
4604 break;
4606 case SMB_FILE_NAME_INFORMATION:
4607 /* Pathname with leading '\'. */
4609 size_t byte_len;
4610 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4611 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4612 SIVAL(pdata,0,byte_len);
4613 data_size = 4 + byte_len;
4614 break;
4617 case SMB_FILE_DISPOSITION_INFORMATION:
4618 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4619 data_size = 1;
4620 SCVAL(pdata,0,delete_pending);
4621 break;
4623 case SMB_FILE_POSITION_INFORMATION:
4624 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4625 data_size = 8;
4626 SOFF_T(pdata,0,pos);
4627 break;
4629 case SMB_FILE_MODE_INFORMATION:
4630 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4631 SIVAL(pdata,0,mode);
4632 data_size = 4;
4633 break;
4635 case SMB_FILE_ALIGNMENT_INFORMATION:
4636 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4637 SIVAL(pdata,0,0); /* No alignment needed. */
4638 data_size = 4;
4639 break;
4642 * NT4 server just returns "invalid query" to this - if we try
4643 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4644 * want this. JRA.
4646 /* The first statement above is false - verified using Thursby
4647 * client against NT4 -- gcolley.
4649 case SMB_QUERY_FILE_STREAM_INFO:
4650 case SMB_FILE_STREAM_INFORMATION: {
4651 unsigned int num_streams;
4652 struct stream_struct *streams;
4654 DEBUG(10,("smbd_do_qfilepathinfo: "
4655 "SMB_FILE_STREAM_INFORMATION\n"));
4657 if (is_ntfs_stream_smb_fname(smb_fname)) {
4658 return NT_STATUS_INVALID_PARAMETER;
4661 status = SMB_VFS_STREAMINFO(
4662 conn, fsp, smb_fname->base_name, talloc_tos(),
4663 &num_streams, &streams);
4665 if (!NT_STATUS_IS_OK(status)) {
4666 DEBUG(10, ("could not get stream info: %s\n",
4667 nt_errstr(status)));
4668 return status;
4671 status = marshall_stream_info(num_streams, streams,
4672 pdata, max_data_bytes,
4673 &data_size);
4675 if (!NT_STATUS_IS_OK(status)) {
4676 DEBUG(10, ("marshall_stream_info failed: %s\n",
4677 nt_errstr(status)));
4678 return status;
4681 TALLOC_FREE(streams);
4683 break;
4685 case SMB_QUERY_COMPRESSION_INFO:
4686 case SMB_FILE_COMPRESSION_INFORMATION:
4687 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4688 SOFF_T(pdata,0,file_size);
4689 SIVAL(pdata,8,0); /* ??? */
4690 SIVAL(pdata,12,0); /* ??? */
4691 data_size = 16;
4692 break;
4694 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4695 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4696 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4697 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4698 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4699 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4700 SOFF_T(pdata,32,allocation_size);
4701 SOFF_T(pdata,40,file_size);
4702 SIVAL(pdata,48,mode);
4703 SIVAL(pdata,52,0); /* ??? */
4704 data_size = 56;
4705 break;
4707 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4708 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4709 SIVAL(pdata,0,mode);
4710 SIVAL(pdata,4,0);
4711 data_size = 8;
4712 break;
4715 * CIFS UNIX Extensions.
4718 case SMB_QUERY_FILE_UNIX_BASIC:
4720 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4721 data_size = PTR_DIFF(pdata,(*ppdata));
4724 int i;
4725 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4727 for (i=0; i<100; i++)
4728 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4729 DEBUG(4,("\n"));
4732 break;
4734 case SMB_QUERY_FILE_UNIX_INFO2:
4736 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4737 data_size = PTR_DIFF(pdata,(*ppdata));
4740 int i;
4741 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4743 for (i=0; i<100; i++)
4744 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4745 DEBUG(4,("\n"));
4748 break;
4750 case SMB_QUERY_FILE_UNIX_LINK:
4752 int len;
4753 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4755 if (!buffer) {
4756 return NT_STATUS_NO_MEMORY;
4759 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4760 #ifdef S_ISLNK
4761 if(!S_ISLNK(psbuf->st_ex_mode)) {
4762 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4764 #else
4765 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4766 #endif
4767 len = SMB_VFS_READLINK(conn,
4768 smb_fname->base_name,
4769 buffer, PATH_MAX);
4770 if (len == -1) {
4771 return map_nt_error_from_unix(errno);
4773 buffer[len] = 0;
4774 len = srvstr_push(dstart, flags2,
4775 pdata, buffer,
4776 PTR_DIFF(dend, pdata),
4777 STR_TERMINATE);
4778 pdata += len;
4779 data_size = PTR_DIFF(pdata,(*ppdata));
4781 break;
4784 #if defined(HAVE_POSIX_ACLS)
4785 case SMB_QUERY_POSIX_ACL:
4787 SMB_ACL_T file_acl = NULL;
4788 SMB_ACL_T def_acl = NULL;
4789 uint16 num_file_acls = 0;
4790 uint16 num_def_acls = 0;
4792 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4793 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4794 } else {
4795 file_acl =
4796 SMB_VFS_SYS_ACL_GET_FILE(conn,
4797 smb_fname->base_name,
4798 SMB_ACL_TYPE_ACCESS);
4801 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4802 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4803 "not implemented on "
4804 "filesystem containing %s\n",
4805 smb_fname->base_name));
4806 return NT_STATUS_NOT_IMPLEMENTED;
4809 if (S_ISDIR(psbuf->st_ex_mode)) {
4810 if (fsp && fsp->is_directory) {
4811 def_acl =
4812 SMB_VFS_SYS_ACL_GET_FILE(
4813 conn,
4814 fsp->fsp_name->base_name,
4815 SMB_ACL_TYPE_DEFAULT);
4816 } else {
4817 def_acl =
4818 SMB_VFS_SYS_ACL_GET_FILE(
4819 conn,
4820 smb_fname->base_name,
4821 SMB_ACL_TYPE_DEFAULT);
4823 def_acl = free_empty_sys_acl(conn, def_acl);
4826 num_file_acls = count_acl_entries(conn, file_acl);
4827 num_def_acls = count_acl_entries(conn, def_acl);
4829 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4830 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4831 data_size,
4832 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4833 SMB_POSIX_ACL_HEADER_SIZE) ));
4834 if (file_acl) {
4835 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4837 if (def_acl) {
4838 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4840 return NT_STATUS_BUFFER_TOO_SMALL;
4843 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4844 SSVAL(pdata,2,num_file_acls);
4845 SSVAL(pdata,4,num_def_acls);
4846 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4847 if (file_acl) {
4848 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4850 if (def_acl) {
4851 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4853 return NT_STATUS_INTERNAL_ERROR;
4855 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4856 if (file_acl) {
4857 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4859 if (def_acl) {
4860 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4862 return NT_STATUS_INTERNAL_ERROR;
4865 if (file_acl) {
4866 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4868 if (def_acl) {
4869 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4871 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4872 break;
4874 #endif
4877 case SMB_QUERY_POSIX_LOCK:
4879 uint64_t count;
4880 uint64_t offset;
4881 uint32 lock_pid;
4882 enum brl_type lock_type;
4884 /* We need an open file with a real fd for this. */
4885 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4886 return NT_STATUS_INVALID_LEVEL;
4889 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4890 return NT_STATUS_INVALID_PARAMETER;
4893 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4894 case POSIX_LOCK_TYPE_READ:
4895 lock_type = READ_LOCK;
4896 break;
4897 case POSIX_LOCK_TYPE_WRITE:
4898 lock_type = WRITE_LOCK;
4899 break;
4900 case POSIX_LOCK_TYPE_UNLOCK:
4901 default:
4902 /* There's no point in asking for an unlock... */
4903 return NT_STATUS_INVALID_PARAMETER;
4906 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4907 #if defined(HAVE_LONGLONG)
4908 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4909 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4910 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4911 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4912 #else /* HAVE_LONGLONG */
4913 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4914 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4915 #endif /* HAVE_LONGLONG */
4917 status = query_lock(fsp,
4918 &lock_pid,
4919 &count,
4920 &offset,
4921 &lock_type,
4922 POSIX_LOCK);
4924 if (ERROR_WAS_LOCK_DENIED(status)) {
4925 /* Here we need to report who has it locked... */
4926 data_size = POSIX_LOCK_DATA_SIZE;
4928 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4929 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4930 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4931 #if defined(HAVE_LONGLONG)
4932 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4933 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4934 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4935 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4936 #else /* HAVE_LONGLONG */
4937 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4938 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4939 #endif /* HAVE_LONGLONG */
4941 } else if (NT_STATUS_IS_OK(status)) {
4942 /* For success we just return a copy of what we sent
4943 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4944 data_size = POSIX_LOCK_DATA_SIZE;
4945 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4946 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4947 } else {
4948 return status;
4950 break;
4953 default:
4954 return NT_STATUS_INVALID_LEVEL;
4957 *pdata_size = data_size;
4958 return NT_STATUS_OK;
4961 /****************************************************************************
4962 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4963 file name or file id).
4964 ****************************************************************************/
4966 static void call_trans2qfilepathinfo(connection_struct *conn,
4967 struct smb_request *req,
4968 unsigned int tran_call,
4969 char **pparams, int total_params,
4970 char **ppdata, int total_data,
4971 unsigned int max_data_bytes)
4973 char *params = *pparams;
4974 char *pdata = *ppdata;
4975 uint16 info_level;
4976 unsigned int data_size = 0;
4977 unsigned int param_size = 2;
4978 struct smb_filename *smb_fname = NULL;
4979 bool delete_pending = False;
4980 struct timespec write_time_ts;
4981 files_struct *fsp = NULL;
4982 struct file_id fileid;
4983 struct ea_list *ea_list = NULL;
4984 int lock_data_count = 0;
4985 char *lock_data = NULL;
4986 bool ms_dfs_link = false;
4987 NTSTATUS status = NT_STATUS_OK;
4989 if (!params) {
4990 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4991 return;
4994 ZERO_STRUCT(write_time_ts);
4996 if (tran_call == TRANSACT2_QFILEINFO) {
4997 if (total_params < 4) {
4998 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4999 return;
5002 if (IS_IPC(conn)) {
5003 call_trans2qpipeinfo(conn, req, tran_call,
5004 pparams, total_params,
5005 ppdata, total_data,
5006 max_data_bytes);
5007 return;
5010 fsp = file_fsp(req, SVAL(params,0));
5011 info_level = SVAL(params,2);
5013 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5015 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5016 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5017 return;
5020 /* Initial check for valid fsp ptr. */
5021 if (!check_fsp_open(conn, req, fsp)) {
5022 return;
5025 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5026 &smb_fname);
5027 if (!NT_STATUS_IS_OK(status)) {
5028 reply_nterror(req, status);
5029 return;
5032 if(fsp->fake_file_handle) {
5034 * This is actually for the QUOTA_FAKE_FILE --metze
5037 /* We know this name is ok, it's already passed the checks. */
5039 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5041 * This is actually a QFILEINFO on a directory
5042 * handle (returned from an NT SMB). NT5.0 seems
5043 * to do this call. JRA.
5046 if (INFO_LEVEL_IS_UNIX(info_level)) {
5047 /* Always do lstat for UNIX calls. */
5048 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5049 DEBUG(3,("call_trans2qfilepathinfo: "
5050 "SMB_VFS_LSTAT of %s failed "
5051 "(%s)\n",
5052 smb_fname_str_dbg(smb_fname),
5053 strerror(errno)));
5054 reply_nterror(req,
5055 map_nt_error_from_unix(errno));
5056 return;
5058 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5059 DEBUG(3,("call_trans2qfilepathinfo: "
5060 "SMB_VFS_STAT of %s failed (%s)\n",
5061 smb_fname_str_dbg(smb_fname),
5062 strerror(errno)));
5063 reply_nterror(req,
5064 map_nt_error_from_unix(errno));
5065 return;
5068 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5069 get_file_infos(fileid, &delete_pending, &write_time_ts);
5070 } else {
5072 * Original code - this is an open file.
5074 if (!check_fsp(conn, req, fsp)) {
5075 return;
5078 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5079 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5080 fsp->fnum, strerror(errno)));
5081 reply_nterror(req,
5082 map_nt_error_from_unix(errno));
5083 return;
5085 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5086 get_file_infos(fileid, &delete_pending, &write_time_ts);
5089 } else {
5090 char *fname = NULL;
5092 /* qpathinfo */
5093 if (total_params < 7) {
5094 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5095 return;
5098 info_level = SVAL(params,0);
5100 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5102 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5103 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5104 return;
5107 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5108 total_params - 6,
5109 STR_TERMINATE, &status);
5110 if (!NT_STATUS_IS_OK(status)) {
5111 reply_nterror(req, status);
5112 return;
5115 status = filename_convert(req,
5116 conn,
5117 req->flags2 & FLAGS2_DFS_PATHNAMES,
5118 fname,
5120 NULL,
5121 &smb_fname);
5122 if (!NT_STATUS_IS_OK(status)) {
5123 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5124 reply_botherror(req,
5125 NT_STATUS_PATH_NOT_COVERED,
5126 ERRSRV, ERRbadpath);
5127 return;
5129 reply_nterror(req, status);
5130 return;
5133 /* If this is a stream, check if there is a delete_pending. */
5134 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5135 && is_ntfs_stream_smb_fname(smb_fname)) {
5136 struct smb_filename *smb_fname_base = NULL;
5138 /* Create an smb_filename with stream_name == NULL. */
5139 status =
5140 create_synthetic_smb_fname(talloc_tos(),
5141 smb_fname->base_name,
5142 NULL, NULL,
5143 &smb_fname_base);
5144 if (!NT_STATUS_IS_OK(status)) {
5145 reply_nterror(req, status);
5146 return;
5149 if (INFO_LEVEL_IS_UNIX(info_level)) {
5150 /* Always do lstat for UNIX calls. */
5151 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5152 DEBUG(3,("call_trans2qfilepathinfo: "
5153 "SMB_VFS_LSTAT of %s failed "
5154 "(%s)\n",
5155 smb_fname_str_dbg(smb_fname_base),
5156 strerror(errno)));
5157 TALLOC_FREE(smb_fname_base);
5158 reply_nterror(req,
5159 map_nt_error_from_unix(errno));
5160 return;
5162 } else {
5163 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5164 DEBUG(3,("call_trans2qfilepathinfo: "
5165 "fileinfo of %s failed "
5166 "(%s)\n",
5167 smb_fname_str_dbg(smb_fname_base),
5168 strerror(errno)));
5169 TALLOC_FREE(smb_fname_base);
5170 reply_nterror(req,
5171 map_nt_error_from_unix(errno));
5172 return;
5176 fileid = vfs_file_id_from_sbuf(conn,
5177 &smb_fname_base->st);
5178 TALLOC_FREE(smb_fname_base);
5179 get_file_infos(fileid, &delete_pending, NULL);
5180 if (delete_pending) {
5181 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5182 return;
5186 if (INFO_LEVEL_IS_UNIX(info_level)) {
5187 /* Always do lstat for UNIX calls. */
5188 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5189 DEBUG(3,("call_trans2qfilepathinfo: "
5190 "SMB_VFS_LSTAT of %s failed (%s)\n",
5191 smb_fname_str_dbg(smb_fname),
5192 strerror(errno)));
5193 reply_nterror(req,
5194 map_nt_error_from_unix(errno));
5195 return;
5198 } else if (!VALID_STAT(smb_fname->st) &&
5199 SMB_VFS_STAT(conn, smb_fname) &&
5200 (info_level != SMB_INFO_IS_NAME_VALID)) {
5201 ms_dfs_link = check_msdfs_link(conn,
5202 smb_fname->base_name,
5203 &smb_fname->st);
5205 if (!ms_dfs_link) {
5206 DEBUG(3,("call_trans2qfilepathinfo: "
5207 "SMB_VFS_STAT of %s failed (%s)\n",
5208 smb_fname_str_dbg(smb_fname),
5209 strerror(errno)));
5210 reply_nterror(req,
5211 map_nt_error_from_unix(errno));
5212 return;
5216 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5217 get_file_infos(fileid, &delete_pending, &write_time_ts);
5218 if (delete_pending) {
5219 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5220 return;
5224 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5225 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5226 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5228 /* Pull out any data sent here before we realloc. */
5229 switch (info_level) {
5230 case SMB_INFO_QUERY_EAS_FROM_LIST:
5232 /* Pull any EA list from the data portion. */
5233 uint32 ea_size;
5235 if (total_data < 4) {
5236 reply_nterror(
5237 req, NT_STATUS_INVALID_PARAMETER);
5238 return;
5240 ea_size = IVAL(pdata,0);
5242 if (total_data > 0 && ea_size != total_data) {
5243 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5244 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5245 reply_nterror(
5246 req, NT_STATUS_INVALID_PARAMETER);
5247 return;
5250 if (!lp_ea_support(SNUM(conn))) {
5251 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5252 return;
5255 /* Pull out the list of names. */
5256 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5257 if (!ea_list) {
5258 reply_nterror(
5259 req, NT_STATUS_INVALID_PARAMETER);
5260 return;
5262 break;
5265 case SMB_QUERY_POSIX_LOCK:
5267 if (fsp == NULL || fsp->fh->fd == -1) {
5268 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5269 return;
5272 if (total_data != POSIX_LOCK_DATA_SIZE) {
5273 reply_nterror(
5274 req, NT_STATUS_INVALID_PARAMETER);
5275 return;
5278 /* Copy the lock range data. */
5279 lock_data = (char *)TALLOC_MEMDUP(
5280 req, pdata, total_data);
5281 if (!lock_data) {
5282 reply_nterror(req, NT_STATUS_NO_MEMORY);
5283 return;
5285 lock_data_count = total_data;
5287 default:
5288 break;
5291 *pparams = (char *)SMB_REALLOC(*pparams,2);
5292 if (*pparams == NULL) {
5293 reply_nterror(req, NT_STATUS_NO_MEMORY);
5294 return;
5296 params = *pparams;
5297 SSVAL(params,0,0);
5300 * draft-leach-cifs-v1-spec-02.txt
5301 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5302 * says:
5304 * The requested information is placed in the Data portion of the
5305 * transaction response. For the information levels greater than 0x100,
5306 * the transaction response has 1 parameter word which should be
5307 * ignored by the client.
5309 * However Windows only follows this rule for the IS_NAME_VALID call.
5311 switch (info_level) {
5312 case SMB_INFO_IS_NAME_VALID:
5313 param_size = 0;
5314 break;
5317 if ((info_level & 0xFF00) == 0xFF00) {
5319 * We use levels that start with 0xFF00
5320 * internally to represent SMB2 specific levels
5322 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5323 return;
5326 status = smbd_do_qfilepathinfo(conn, req, info_level,
5327 fsp, smb_fname,
5328 delete_pending, write_time_ts,
5329 ms_dfs_link, ea_list,
5330 lock_data_count, lock_data,
5331 req->flags2, max_data_bytes,
5332 ppdata, &data_size);
5333 if (!NT_STATUS_IS_OK(status)) {
5334 reply_nterror(req, status);
5335 return;
5338 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5339 max_data_bytes);
5341 return;
5344 /****************************************************************************
5345 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5346 code.
5347 ****************************************************************************/
5349 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5350 connection_struct *conn,
5351 const struct smb_filename *smb_fname_old,
5352 const struct smb_filename *smb_fname_new)
5354 NTSTATUS status = NT_STATUS_OK;
5356 /* source must already exist. */
5357 if (!VALID_STAT(smb_fname_old->st)) {
5358 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5361 /* Disallow if newname already exists. */
5362 if (VALID_STAT(smb_fname_new->st)) {
5363 return NT_STATUS_OBJECT_NAME_COLLISION;
5366 /* No links from a directory. */
5367 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5368 return NT_STATUS_FILE_IS_A_DIRECTORY;
5371 /* Setting a hardlink to/from a stream isn't currently supported. */
5372 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5373 is_ntfs_stream_smb_fname(smb_fname_new)) {
5374 return NT_STATUS_INVALID_PARAMETER;
5377 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5378 smb_fname_old->base_name, smb_fname_new->base_name));
5380 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5381 smb_fname_new->base_name) != 0) {
5382 status = map_nt_error_from_unix(errno);
5383 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5384 nt_errstr(status), smb_fname_old->base_name,
5385 smb_fname_new->base_name));
5387 return status;
5390 /****************************************************************************
5391 Deal with setting the time from any of the setfilepathinfo functions.
5392 ****************************************************************************/
5394 NTSTATUS smb_set_file_time(connection_struct *conn,
5395 files_struct *fsp,
5396 const struct smb_filename *smb_fname,
5397 struct smb_file_time *ft,
5398 bool setting_write_time)
5400 struct smb_filename smb_fname_base;
5401 uint32 action =
5402 FILE_NOTIFY_CHANGE_LAST_ACCESS
5403 |FILE_NOTIFY_CHANGE_LAST_WRITE
5404 |FILE_NOTIFY_CHANGE_CREATION;
5406 if (!VALID_STAT(smb_fname->st)) {
5407 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5410 /* get some defaults (no modifications) if any info is zero or -1. */
5411 if (null_timespec(ft->create_time)) {
5412 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5415 if (null_timespec(ft->atime)) {
5416 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5419 if (null_timespec(ft->mtime)) {
5420 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5423 if (!setting_write_time) {
5424 /* ft->mtime comes from change time, not write time. */
5425 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5428 /* Ensure the resolution is the correct for
5429 * what we can store on this filesystem. */
5431 round_timespec(conn->ts_res, &ft->create_time);
5432 round_timespec(conn->ts_res, &ft->ctime);
5433 round_timespec(conn->ts_res, &ft->atime);
5434 round_timespec(conn->ts_res, &ft->mtime);
5436 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5437 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5438 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5439 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5440 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5441 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5442 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5443 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5445 if (setting_write_time) {
5447 * This was a Windows setfileinfo on an open file.
5448 * NT does this a lot. We also need to
5449 * set the time here, as it can be read by
5450 * FindFirst/FindNext and with the patch for bug #2045
5451 * in smbd/fileio.c it ensures that this timestamp is
5452 * kept sticky even after a write. We save the request
5453 * away and will set it on file close and after a write. JRA.
5456 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5457 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5459 if (fsp != NULL) {
5460 if (fsp->base_fsp) {
5461 set_sticky_write_time_fsp(fsp->base_fsp,
5462 ft->mtime);
5463 } else {
5464 set_sticky_write_time_fsp(fsp, ft->mtime);
5466 } else {
5467 set_sticky_write_time_path(
5468 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5469 ft->mtime);
5473 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5475 /* Always call ntimes on the base, even if a stream was passed in. */
5476 smb_fname_base = *smb_fname;
5477 smb_fname_base.stream_name = NULL;
5479 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5480 return map_nt_error_from_unix(errno);
5483 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5484 smb_fname->base_name);
5485 return NT_STATUS_OK;
5488 /****************************************************************************
5489 Deal with setting the dosmode from any of the setfilepathinfo functions.
5490 ****************************************************************************/
5492 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5493 const struct smb_filename *smb_fname,
5494 uint32 dosmode)
5496 struct smb_filename *smb_fname_base = NULL;
5497 NTSTATUS status;
5499 if (!VALID_STAT(smb_fname->st)) {
5500 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5503 /* Always operate on the base_name, even if a stream was passed in. */
5504 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5505 NULL, &smb_fname->st,
5506 &smb_fname_base);
5507 if (!NT_STATUS_IS_OK(status)) {
5508 return status;
5511 if (dosmode) {
5512 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5513 dosmode |= aDIR;
5514 } else {
5515 dosmode &= ~aDIR;
5519 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5521 /* check the mode isn't different, before changing it */
5522 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5523 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5524 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5525 (unsigned int)dosmode));
5527 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5528 false)) {
5529 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5530 "%s failed (%s)\n",
5531 smb_fname_str_dbg(smb_fname_base),
5532 strerror(errno)));
5533 status = map_nt_error_from_unix(errno);
5534 goto out;
5537 status = NT_STATUS_OK;
5538 out:
5539 TALLOC_FREE(smb_fname_base);
5540 return status;
5543 /****************************************************************************
5544 Deal with setting the size from any of the setfilepathinfo functions.
5545 ****************************************************************************/
5547 static NTSTATUS smb_set_file_size(connection_struct *conn,
5548 struct smb_request *req,
5549 files_struct *fsp,
5550 const struct smb_filename *smb_fname,
5551 const SMB_STRUCT_STAT *psbuf,
5552 SMB_OFF_T size,
5553 bool fail_after_createfile)
5555 NTSTATUS status = NT_STATUS_OK;
5556 struct smb_filename *smb_fname_tmp = NULL;
5557 files_struct *new_fsp = NULL;
5559 if (!VALID_STAT(*psbuf)) {
5560 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5563 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5565 if (size == get_file_size_stat(psbuf)) {
5566 return NT_STATUS_OK;
5569 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5570 smb_fname_str_dbg(smb_fname), (double)size));
5572 if (fsp && fsp->fh->fd != -1) {
5573 /* Handle based call. */
5574 if (vfs_set_filelen(fsp, size) == -1) {
5575 return map_nt_error_from_unix(errno);
5577 trigger_write_time_update_immediate(fsp);
5578 return NT_STATUS_OK;
5581 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5582 if (!NT_STATUS_IS_OK(status)) {
5583 return status;
5586 smb_fname_tmp->st = *psbuf;
5588 status = SMB_VFS_CREATE_FILE(
5589 conn, /* conn */
5590 req, /* req */
5591 0, /* root_dir_fid */
5592 smb_fname_tmp, /* fname */
5593 FILE_WRITE_ATTRIBUTES, /* access_mask */
5594 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5595 FILE_SHARE_DELETE),
5596 FILE_OPEN, /* create_disposition*/
5597 0, /* create_options */
5598 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5599 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5600 0, /* allocation_size */
5601 NULL, /* sd */
5602 NULL, /* ea_list */
5603 &new_fsp, /* result */
5604 NULL); /* pinfo */
5606 TALLOC_FREE(smb_fname_tmp);
5608 if (!NT_STATUS_IS_OK(status)) {
5609 /* NB. We check for open_was_deferred in the caller. */
5610 return status;
5613 /* See RAW-SFILEINFO-END-OF-FILE */
5614 if (fail_after_createfile) {
5615 close_file(req, new_fsp,NORMAL_CLOSE);
5616 return NT_STATUS_INVALID_LEVEL;
5619 if (vfs_set_filelen(new_fsp, size) == -1) {
5620 status = map_nt_error_from_unix(errno);
5621 close_file(req, new_fsp,NORMAL_CLOSE);
5622 return status;
5625 trigger_write_time_update_immediate(new_fsp);
5626 close_file(req, new_fsp,NORMAL_CLOSE);
5627 return NT_STATUS_OK;
5630 /****************************************************************************
5631 Deal with SMB_INFO_SET_EA.
5632 ****************************************************************************/
5634 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5635 const char *pdata,
5636 int total_data,
5637 files_struct *fsp,
5638 const struct smb_filename *smb_fname)
5640 struct ea_list *ea_list = NULL;
5641 TALLOC_CTX *ctx = NULL;
5642 NTSTATUS status = NT_STATUS_OK;
5644 if (total_data < 10) {
5646 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5647 length. They seem to have no effect. Bug #3212. JRA */
5649 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5650 /* We're done. We only get EA info in this call. */
5651 return NT_STATUS_OK;
5654 return NT_STATUS_INVALID_PARAMETER;
5657 if (IVAL(pdata,0) > total_data) {
5658 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5659 IVAL(pdata,0), (unsigned int)total_data));
5660 return NT_STATUS_INVALID_PARAMETER;
5663 ctx = talloc_tos();
5664 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5665 if (!ea_list) {
5666 return NT_STATUS_INVALID_PARAMETER;
5668 status = set_ea(conn, fsp, smb_fname, ea_list);
5670 return status;
5673 /****************************************************************************
5674 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5675 ****************************************************************************/
5677 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5678 const char *pdata,
5679 int total_data,
5680 files_struct *fsp)
5682 struct ea_list *ea_list = NULL;
5683 NTSTATUS status;
5685 if (!fsp) {
5686 return NT_STATUS_INVALID_HANDLE;
5689 if (!lp_ea_support(SNUM(conn))) {
5690 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5691 "EA's not supported.\n",
5692 (unsigned int)total_data));
5693 return NT_STATUS_EAS_NOT_SUPPORTED;
5696 if (total_data < 10) {
5697 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5698 "too small.\n",
5699 (unsigned int)total_data));
5700 return NT_STATUS_INVALID_PARAMETER;
5703 ea_list = read_nttrans_ea_list(talloc_tos(),
5704 pdata,
5705 total_data);
5707 if (!ea_list) {
5708 return NT_STATUS_INVALID_PARAMETER;
5710 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5712 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5713 smb_fname_str_dbg(fsp->fsp_name),
5714 nt_errstr(status) ));
5716 return status;
5720 /****************************************************************************
5721 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5722 ****************************************************************************/
5724 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5725 const char *pdata,
5726 int total_data,
5727 files_struct *fsp,
5728 struct smb_filename *smb_fname)
5730 NTSTATUS status = NT_STATUS_OK;
5731 bool delete_on_close;
5732 uint32 dosmode = 0;
5734 if (total_data < 1) {
5735 return NT_STATUS_INVALID_PARAMETER;
5738 if (fsp == NULL) {
5739 return NT_STATUS_INVALID_HANDLE;
5742 delete_on_close = (CVAL(pdata,0) ? True : False);
5743 dosmode = dos_mode(conn, smb_fname);
5745 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5746 "delete_on_close = %u\n",
5747 smb_fname_str_dbg(smb_fname),
5748 (unsigned int)dosmode,
5749 (unsigned int)delete_on_close ));
5751 if (delete_on_close) {
5752 status = can_set_delete_on_close(fsp, dosmode);
5753 if (!NT_STATUS_IS_OK(status)) {
5754 return status;
5758 /* The set is across all open files on this dev/inode pair. */
5759 if (!set_delete_on_close(fsp, delete_on_close,
5760 &conn->server_info->utok)) {
5761 return NT_STATUS_ACCESS_DENIED;
5763 return NT_STATUS_OK;
5766 /****************************************************************************
5767 Deal with SMB_FILE_POSITION_INFORMATION.
5768 ****************************************************************************/
5770 static NTSTATUS smb_file_position_information(connection_struct *conn,
5771 const char *pdata,
5772 int total_data,
5773 files_struct *fsp)
5775 uint64_t position_information;
5777 if (total_data < 8) {
5778 return NT_STATUS_INVALID_PARAMETER;
5781 if (fsp == NULL) {
5782 /* Ignore on pathname based set. */
5783 return NT_STATUS_OK;
5786 position_information = (uint64_t)IVAL(pdata,0);
5787 #ifdef LARGE_SMB_OFF_T
5788 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5789 #else /* LARGE_SMB_OFF_T */
5790 if (IVAL(pdata,4) != 0) {
5791 /* more than 32 bits? */
5792 return NT_STATUS_INVALID_PARAMETER;
5794 #endif /* LARGE_SMB_OFF_T */
5796 DEBUG(10,("smb_file_position_information: Set file position "
5797 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5798 (double)position_information));
5799 fsp->fh->position_information = position_information;
5800 return NT_STATUS_OK;
5803 /****************************************************************************
5804 Deal with SMB_FILE_MODE_INFORMATION.
5805 ****************************************************************************/
5807 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5808 const char *pdata,
5809 int total_data)
5811 uint32 mode;
5813 if (total_data < 4) {
5814 return NT_STATUS_INVALID_PARAMETER;
5816 mode = IVAL(pdata,0);
5817 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5818 return NT_STATUS_INVALID_PARAMETER;
5820 return NT_STATUS_OK;
5823 /****************************************************************************
5824 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5825 ****************************************************************************/
5827 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5828 struct smb_request *req,
5829 const char *pdata,
5830 int total_data,
5831 const struct smb_filename *smb_fname)
5833 char *link_target = NULL;
5834 const char *newname = smb_fname->base_name;
5835 TALLOC_CTX *ctx = talloc_tos();
5837 /* Set a symbolic link. */
5838 /* Don't allow this if follow links is false. */
5840 if (total_data == 0) {
5841 return NT_STATUS_INVALID_PARAMETER;
5844 if (!lp_symlinks(SNUM(conn))) {
5845 return NT_STATUS_ACCESS_DENIED;
5848 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5849 total_data, STR_TERMINATE);
5851 if (!link_target) {
5852 return NT_STATUS_INVALID_PARAMETER;
5855 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5856 newname, link_target ));
5858 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5859 return map_nt_error_from_unix(errno);
5862 return NT_STATUS_OK;
5865 /****************************************************************************
5866 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5867 ****************************************************************************/
5869 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5870 struct smb_request *req,
5871 const char *pdata, int total_data,
5872 const struct smb_filename *smb_fname_new)
5874 char *oldname = NULL;
5875 struct smb_filename *smb_fname_old = NULL;
5876 TALLOC_CTX *ctx = talloc_tos();
5877 NTSTATUS status = NT_STATUS_OK;
5879 /* Set a hard link. */
5880 if (total_data == 0) {
5881 return NT_STATUS_INVALID_PARAMETER;
5884 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5885 total_data, STR_TERMINATE, &status);
5886 if (!NT_STATUS_IS_OK(status)) {
5887 return status;
5890 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5891 smb_fname_str_dbg(smb_fname_new), oldname));
5893 status = filename_convert(ctx,
5894 conn,
5895 req->flags2 & FLAGS2_DFS_PATHNAMES,
5896 oldname,
5898 NULL,
5899 &smb_fname_old);
5900 if (!NT_STATUS_IS_OK(status)) {
5901 return status;
5904 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5907 /****************************************************************************
5908 Deal with SMB_FILE_RENAME_INFORMATION.
5909 ****************************************************************************/
5911 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5912 struct smb_request *req,
5913 const char *pdata,
5914 int total_data,
5915 files_struct *fsp,
5916 struct smb_filename *smb_fname_src)
5918 bool overwrite;
5919 uint32 root_fid;
5920 uint32 len;
5921 char *newname = NULL;
5922 struct smb_filename *smb_fname_dst = NULL;
5923 bool dest_has_wcard = False;
5924 NTSTATUS status = NT_STATUS_OK;
5925 char *p;
5926 TALLOC_CTX *ctx = talloc_tos();
5928 if (total_data < 13) {
5929 return NT_STATUS_INVALID_PARAMETER;
5932 overwrite = (CVAL(pdata,0) ? True : False);
5933 root_fid = IVAL(pdata,4);
5934 len = IVAL(pdata,8);
5936 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5937 return NT_STATUS_INVALID_PARAMETER;
5940 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5941 len, 0, &status,
5942 &dest_has_wcard);
5943 if (!NT_STATUS_IS_OK(status)) {
5944 return status;
5947 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5948 newname));
5950 status = resolve_dfspath_wcard(ctx, conn,
5951 req->flags2 & FLAGS2_DFS_PATHNAMES,
5952 newname,
5953 true,
5954 &newname,
5955 &dest_has_wcard);
5956 if (!NT_STATUS_IS_OK(status)) {
5957 return status;
5960 /* Check the new name has no '/' characters. */
5961 if (strchr_m(newname, '/')) {
5962 return NT_STATUS_NOT_SUPPORTED;
5965 if (fsp && fsp->base_fsp) {
5966 /* newname must be a stream name. */
5967 if (newname[0] != ':') {
5968 return NT_STATUS_NOT_SUPPORTED;
5971 /* Create an smb_fname to call rename_internals_fsp() with. */
5972 status = create_synthetic_smb_fname(talloc_tos(),
5973 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5974 &smb_fname_dst);
5975 if (!NT_STATUS_IS_OK(status)) {
5976 goto out;
5980 * Set the original last component, since
5981 * rename_internals_fsp() requires it.
5983 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5984 newname);
5985 if (smb_fname_dst->original_lcomp == NULL) {
5986 status = NT_STATUS_NO_MEMORY;
5987 goto out;
5990 } else {
5992 * Build up an smb_fname_dst based on the filename passed in.
5993 * We basically just strip off the last component, and put on
5994 * the newname instead.
5996 char *base_name = NULL;
5998 /* newname must *not* be a stream name. */
5999 if (newname[0] == ':') {
6000 return NT_STATUS_NOT_SUPPORTED;
6004 * Strip off the last component (filename) of the path passed
6005 * in.
6007 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6008 if (!base_name) {
6009 return NT_STATUS_NO_MEMORY;
6011 p = strrchr_m(base_name, '/');
6012 if (p) {
6013 p[1] = '\0';
6014 } else {
6015 base_name = talloc_strdup(ctx, "./");
6016 if (!base_name) {
6017 return NT_STATUS_NO_MEMORY;
6020 /* Append the new name. */
6021 base_name = talloc_asprintf_append(base_name,
6022 "%s",
6023 newname);
6024 if (!base_name) {
6025 return NT_STATUS_NO_MEMORY;
6028 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6029 (UCF_SAVE_LCOMP |
6030 (dest_has_wcard ?
6031 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6032 0)));
6034 /* If an error we expect this to be
6035 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6037 if (!NT_STATUS_IS_OK(status)) {
6038 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6039 status)) {
6040 goto out;
6042 /* Create an smb_fname to call rename_internals_fsp() */
6043 status = create_synthetic_smb_fname(ctx,
6044 base_name, NULL,
6045 NULL,
6046 &smb_fname_dst);
6047 if (!NT_STATUS_IS_OK(status)) {
6048 goto out;
6053 if (fsp) {
6054 DEBUG(10,("smb_file_rename_information: "
6055 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6056 fsp->fnum, fsp_str_dbg(fsp),
6057 smb_fname_str_dbg(smb_fname_dst)));
6058 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6059 overwrite);
6060 } else {
6061 DEBUG(10,("smb_file_rename_information: "
6062 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6063 smb_fname_str_dbg(smb_fname_src),
6064 smb_fname_str_dbg(smb_fname_dst)));
6065 status = rename_internals(ctx, conn, req, smb_fname_src,
6066 smb_fname_dst, 0, overwrite, false,
6067 dest_has_wcard,
6068 FILE_WRITE_ATTRIBUTES);
6070 out:
6071 TALLOC_FREE(smb_fname_dst);
6072 return status;
6075 /****************************************************************************
6076 Deal with SMB_SET_POSIX_ACL.
6077 ****************************************************************************/
6079 #if defined(HAVE_POSIX_ACLS)
6080 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6081 const char *pdata,
6082 int total_data,
6083 files_struct *fsp,
6084 const struct smb_filename *smb_fname)
6086 uint16 posix_acl_version;
6087 uint16 num_file_acls;
6088 uint16 num_def_acls;
6089 bool valid_file_acls = True;
6090 bool valid_def_acls = True;
6092 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6093 return NT_STATUS_INVALID_PARAMETER;
6095 posix_acl_version = SVAL(pdata,0);
6096 num_file_acls = SVAL(pdata,2);
6097 num_def_acls = SVAL(pdata,4);
6099 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6100 valid_file_acls = False;
6101 num_file_acls = 0;
6104 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6105 valid_def_acls = False;
6106 num_def_acls = 0;
6109 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6110 return NT_STATUS_INVALID_PARAMETER;
6113 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6114 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6115 return NT_STATUS_INVALID_PARAMETER;
6118 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6119 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6120 (unsigned int)num_file_acls,
6121 (unsigned int)num_def_acls));
6123 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6124 smb_fname->base_name, num_file_acls,
6125 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6126 return map_nt_error_from_unix(errno);
6129 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6130 smb_fname->base_name, &smb_fname->st, num_def_acls,
6131 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6132 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6133 return map_nt_error_from_unix(errno);
6135 return NT_STATUS_OK;
6137 #endif
6139 /****************************************************************************
6140 Deal with SMB_SET_POSIX_LOCK.
6141 ****************************************************************************/
6143 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6144 struct smb_request *req,
6145 const char *pdata,
6146 int total_data,
6147 files_struct *fsp)
6149 uint64_t count;
6150 uint64_t offset;
6151 uint32 lock_pid;
6152 bool blocking_lock = False;
6153 enum brl_type lock_type;
6155 NTSTATUS status = NT_STATUS_OK;
6157 if (fsp == NULL || fsp->fh->fd == -1) {
6158 return NT_STATUS_INVALID_HANDLE;
6161 if (total_data != POSIX_LOCK_DATA_SIZE) {
6162 return NT_STATUS_INVALID_PARAMETER;
6165 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6166 case POSIX_LOCK_TYPE_READ:
6167 lock_type = READ_LOCK;
6168 break;
6169 case POSIX_LOCK_TYPE_WRITE:
6170 /* Return the right POSIX-mappable error code for files opened read-only. */
6171 if (!fsp->can_write) {
6172 return NT_STATUS_INVALID_HANDLE;
6174 lock_type = WRITE_LOCK;
6175 break;
6176 case POSIX_LOCK_TYPE_UNLOCK:
6177 lock_type = UNLOCK_LOCK;
6178 break;
6179 default:
6180 return NT_STATUS_INVALID_PARAMETER;
6183 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6184 blocking_lock = False;
6185 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6186 blocking_lock = True;
6187 } else {
6188 return NT_STATUS_INVALID_PARAMETER;
6191 if (!lp_blocking_locks(SNUM(conn))) {
6192 blocking_lock = False;
6195 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6196 #if defined(HAVE_LONGLONG)
6197 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6198 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6199 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6200 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6201 #else /* HAVE_LONGLONG */
6202 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6203 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6204 #endif /* HAVE_LONGLONG */
6206 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6207 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6208 fsp_str_dbg(fsp),
6209 (unsigned int)lock_type,
6210 (unsigned int)lock_pid,
6211 (double)count,
6212 (double)offset ));
6214 if (lock_type == UNLOCK_LOCK) {
6215 status = do_unlock(smbd_messaging_context(),
6216 fsp,
6217 lock_pid,
6218 count,
6219 offset,
6220 POSIX_LOCK);
6221 } else {
6222 uint32 block_smbpid;
6224 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6225 fsp,
6226 lock_pid,
6227 count,
6228 offset,
6229 lock_type,
6230 POSIX_LOCK,
6231 blocking_lock,
6232 &status,
6233 &block_smbpid,
6234 NULL);
6236 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6238 * A blocking lock was requested. Package up
6239 * this smb into a queued request and push it
6240 * onto the blocking lock queue.
6242 if(push_blocking_lock_request(br_lck,
6243 req,
6244 fsp,
6245 -1, /* infinite timeout. */
6247 lock_pid,
6248 lock_type,
6249 POSIX_LOCK,
6250 offset,
6251 count,
6252 block_smbpid)) {
6253 TALLOC_FREE(br_lck);
6254 return status;
6257 TALLOC_FREE(br_lck);
6260 return status;
6263 /****************************************************************************
6264 Deal with SMB_SET_FILE_BASIC_INFO.
6265 ****************************************************************************/
6267 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6268 const char *pdata,
6269 int total_data,
6270 files_struct *fsp,
6271 const struct smb_filename *smb_fname)
6273 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6274 struct smb_file_time ft;
6275 uint32 dosmode = 0;
6276 NTSTATUS status = NT_STATUS_OK;
6278 ZERO_STRUCT(ft);
6280 if (total_data < 36) {
6281 return NT_STATUS_INVALID_PARAMETER;
6284 /* Set the attributes */
6285 dosmode = IVAL(pdata,32);
6286 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6287 if (!NT_STATUS_IS_OK(status)) {
6288 return status;
6291 /* create time */
6292 ft.create_time = interpret_long_date(pdata);
6294 /* access time */
6295 ft.atime = interpret_long_date(pdata+8);
6297 /* write time. */
6298 ft.mtime = interpret_long_date(pdata+16);
6300 /* change time. */
6301 ft.ctime = interpret_long_date(pdata+24);
6303 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6304 smb_fname_str_dbg(smb_fname)));
6306 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6307 true);
6310 /****************************************************************************
6311 Deal with SMB_INFO_STANDARD.
6312 ****************************************************************************/
6314 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6315 const char *pdata,
6316 int total_data,
6317 files_struct *fsp,
6318 const struct smb_filename *smb_fname)
6320 struct smb_file_time ft;
6322 ZERO_STRUCT(ft);
6324 if (total_data < 12) {
6325 return NT_STATUS_INVALID_PARAMETER;
6328 /* create time */
6329 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6330 /* access time */
6331 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6332 /* write time */
6333 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6335 DEBUG(10,("smb_set_info_standard: file %s\n",
6336 smb_fname_str_dbg(smb_fname)));
6338 return smb_set_file_time(conn,
6339 fsp,
6340 smb_fname,
6341 &ft,
6342 true);
6345 /****************************************************************************
6346 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6347 ****************************************************************************/
6349 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6350 struct smb_request *req,
6351 const char *pdata,
6352 int total_data,
6353 files_struct *fsp,
6354 struct smb_filename *smb_fname)
6356 uint64_t allocation_size = 0;
6357 NTSTATUS status = NT_STATUS_OK;
6358 files_struct *new_fsp = NULL;
6360 if (!VALID_STAT(smb_fname->st)) {
6361 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6364 if (total_data < 8) {
6365 return NT_STATUS_INVALID_PARAMETER;
6368 allocation_size = (uint64_t)IVAL(pdata,0);
6369 #ifdef LARGE_SMB_OFF_T
6370 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6371 #else /* LARGE_SMB_OFF_T */
6372 if (IVAL(pdata,4) != 0) {
6373 /* more than 32 bits? */
6374 return NT_STATUS_INVALID_PARAMETER;
6376 #endif /* LARGE_SMB_OFF_T */
6378 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6379 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6380 (double)allocation_size));
6382 if (allocation_size) {
6383 allocation_size = smb_roundup(conn, allocation_size);
6386 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6387 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6388 (double)allocation_size));
6390 if (fsp && fsp->fh->fd != -1) {
6391 /* Open file handle. */
6392 /* Only change if needed. */
6393 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6394 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6395 return map_nt_error_from_unix(errno);
6398 /* But always update the time. */
6400 * This is equivalent to a write. Ensure it's seen immediately
6401 * if there are no pending writes.
6403 trigger_write_time_update_immediate(fsp);
6404 return NT_STATUS_OK;
6407 /* Pathname or stat or directory file. */
6408 status = SMB_VFS_CREATE_FILE(
6409 conn, /* conn */
6410 req, /* req */
6411 0, /* root_dir_fid */
6412 smb_fname, /* fname */
6413 FILE_WRITE_DATA, /* access_mask */
6414 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6415 FILE_SHARE_DELETE),
6416 FILE_OPEN, /* create_disposition*/
6417 0, /* create_options */
6418 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6419 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6420 0, /* allocation_size */
6421 NULL, /* sd */
6422 NULL, /* ea_list */
6423 &new_fsp, /* result */
6424 NULL); /* pinfo */
6426 if (!NT_STATUS_IS_OK(status)) {
6427 /* NB. We check for open_was_deferred in the caller. */
6428 return status;
6431 /* Only change if needed. */
6432 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6433 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6434 status = map_nt_error_from_unix(errno);
6435 close_file(req, new_fsp, NORMAL_CLOSE);
6436 return status;
6440 /* Changing the allocation size should set the last mod time. */
6442 * This is equivalent to a write. Ensure it's seen immediately
6443 * if there are no pending writes.
6445 trigger_write_time_update_immediate(new_fsp);
6447 close_file(req, new_fsp, NORMAL_CLOSE);
6448 return NT_STATUS_OK;
6451 /****************************************************************************
6452 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6453 ****************************************************************************/
6455 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6456 struct smb_request *req,
6457 const char *pdata,
6458 int total_data,
6459 files_struct *fsp,
6460 const struct smb_filename *smb_fname,
6461 bool fail_after_createfile)
6463 SMB_OFF_T size;
6465 if (total_data < 8) {
6466 return NT_STATUS_INVALID_PARAMETER;
6469 size = IVAL(pdata,0);
6470 #ifdef LARGE_SMB_OFF_T
6471 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6472 #else /* LARGE_SMB_OFF_T */
6473 if (IVAL(pdata,4) != 0) {
6474 /* more than 32 bits? */
6475 return NT_STATUS_INVALID_PARAMETER;
6477 #endif /* LARGE_SMB_OFF_T */
6478 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6479 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6480 (double)size));
6482 return smb_set_file_size(conn, req,
6483 fsp,
6484 smb_fname,
6485 &smb_fname->st,
6486 size,
6487 fail_after_createfile);
6490 /****************************************************************************
6491 Allow a UNIX info mknod.
6492 ****************************************************************************/
6494 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6495 const char *pdata,
6496 int total_data,
6497 const struct smb_filename *smb_fname)
6499 uint32 file_type = IVAL(pdata,56);
6500 #if defined(HAVE_MAKEDEV)
6501 uint32 dev_major = IVAL(pdata,60);
6502 uint32 dev_minor = IVAL(pdata,68);
6503 #endif
6504 SMB_DEV_T dev = (SMB_DEV_T)0;
6505 uint32 raw_unixmode = IVAL(pdata,84);
6506 NTSTATUS status;
6507 mode_t unixmode;
6509 if (total_data < 100) {
6510 return NT_STATUS_INVALID_PARAMETER;
6513 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6514 PERM_NEW_FILE, &unixmode);
6515 if (!NT_STATUS_IS_OK(status)) {
6516 return status;
6519 #if defined(HAVE_MAKEDEV)
6520 dev = makedev(dev_major, dev_minor);
6521 #endif
6523 switch (file_type) {
6524 #if defined(S_IFIFO)
6525 case UNIX_TYPE_FIFO:
6526 unixmode |= S_IFIFO;
6527 break;
6528 #endif
6529 #if defined(S_IFSOCK)
6530 case UNIX_TYPE_SOCKET:
6531 unixmode |= S_IFSOCK;
6532 break;
6533 #endif
6534 #if defined(S_IFCHR)
6535 case UNIX_TYPE_CHARDEV:
6536 unixmode |= S_IFCHR;
6537 break;
6538 #endif
6539 #if defined(S_IFBLK)
6540 case UNIX_TYPE_BLKDEV:
6541 unixmode |= S_IFBLK;
6542 break;
6543 #endif
6544 default:
6545 return NT_STATUS_INVALID_PARAMETER;
6548 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6549 "%.0f mode 0%o for file %s\n", (double)dev,
6550 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6552 /* Ok - do the mknod. */
6553 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6554 return map_nt_error_from_unix(errno);
6557 /* If any of the other "set" calls fail we
6558 * don't want to end up with a half-constructed mknod.
6561 if (lp_inherit_perms(SNUM(conn))) {
6562 char *parent;
6563 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6564 &parent, NULL)) {
6565 return NT_STATUS_NO_MEMORY;
6567 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6568 unixmode);
6569 TALLOC_FREE(parent);
6572 return NT_STATUS_OK;
6575 /****************************************************************************
6576 Deal with SMB_SET_FILE_UNIX_BASIC.
6577 ****************************************************************************/
6579 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6580 struct smb_request *req,
6581 const char *pdata,
6582 int total_data,
6583 files_struct *fsp,
6584 const struct smb_filename *smb_fname)
6586 struct smb_file_time ft;
6587 uint32 raw_unixmode;
6588 mode_t unixmode;
6589 SMB_OFF_T size = 0;
6590 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6591 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6592 NTSTATUS status = NT_STATUS_OK;
6593 bool delete_on_fail = False;
6594 enum perm_type ptype;
6595 files_struct *all_fsps = NULL;
6596 bool modify_mtime = true;
6597 struct file_id id;
6598 struct smb_filename *smb_fname_tmp = NULL;
6599 SMB_STRUCT_STAT sbuf;
6601 ZERO_STRUCT(ft);
6603 if (total_data < 100) {
6604 return NT_STATUS_INVALID_PARAMETER;
6607 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6608 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6609 size=IVAL(pdata,0); /* first 8 Bytes are size */
6610 #ifdef LARGE_SMB_OFF_T
6611 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6612 #else /* LARGE_SMB_OFF_T */
6613 if (IVAL(pdata,4) != 0) {
6614 /* more than 32 bits? */
6615 return NT_STATUS_INVALID_PARAMETER;
6617 #endif /* LARGE_SMB_OFF_T */
6620 ft.atime = interpret_long_date(pdata+24); /* access_time */
6621 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6622 set_owner = (uid_t)IVAL(pdata,40);
6623 set_grp = (gid_t)IVAL(pdata,48);
6624 raw_unixmode = IVAL(pdata,84);
6626 if (VALID_STAT(smb_fname->st)) {
6627 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6628 ptype = PERM_EXISTING_DIR;
6629 } else {
6630 ptype = PERM_EXISTING_FILE;
6632 } else {
6633 ptype = PERM_NEW_FILE;
6636 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6637 ptype, &unixmode);
6638 if (!NT_STATUS_IS_OK(status)) {
6639 return status;
6642 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6643 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6644 smb_fname_str_dbg(smb_fname), (double)size,
6645 (unsigned int)set_owner, (unsigned int)set_grp,
6646 (int)raw_unixmode));
6648 sbuf = smb_fname->st;
6650 if (!VALID_STAT(sbuf)) {
6652 * The only valid use of this is to create character and block
6653 * devices, and named pipes. This is deprecated (IMHO) and
6654 * a new info level should be used for mknod. JRA.
6657 status = smb_unix_mknod(conn,
6658 pdata,
6659 total_data,
6660 smb_fname);
6661 if (!NT_STATUS_IS_OK(status)) {
6662 return status;
6665 status = copy_smb_filename(talloc_tos(), smb_fname,
6666 &smb_fname_tmp);
6667 if (!NT_STATUS_IS_OK(status)) {
6668 return status;
6671 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6672 status = map_nt_error_from_unix(errno);
6673 TALLOC_FREE(smb_fname_tmp);
6674 SMB_VFS_UNLINK(conn, smb_fname);
6675 return status;
6678 sbuf = smb_fname_tmp->st;
6679 smb_fname = smb_fname_tmp;
6681 /* Ensure we don't try and change anything else. */
6682 raw_unixmode = SMB_MODE_NO_CHANGE;
6683 size = get_file_size_stat(&sbuf);
6684 ft.atime = sbuf.st_ex_atime;
6685 ft.mtime = sbuf.st_ex_mtime;
6687 * We continue here as we might want to change the
6688 * owner uid/gid.
6690 delete_on_fail = True;
6693 #if 1
6694 /* Horrible backwards compatibility hack as an old server bug
6695 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6696 * */
6698 if (!size) {
6699 size = get_file_size_stat(&sbuf);
6701 #endif
6704 * Deal with the UNIX specific mode set.
6707 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6708 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6709 "setting mode 0%o for file %s\n",
6710 (unsigned int)unixmode,
6711 smb_fname_str_dbg(smb_fname)));
6712 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6713 return map_nt_error_from_unix(errno);
6718 * Deal with the UNIX specific uid set.
6721 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6722 (sbuf.st_ex_uid != set_owner)) {
6723 int ret;
6725 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6726 "changing owner %u for path %s\n",
6727 (unsigned int)set_owner,
6728 smb_fname_str_dbg(smb_fname)));
6730 if (S_ISLNK(sbuf.st_ex_mode)) {
6731 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6732 set_owner, (gid_t)-1);
6733 } else {
6734 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6735 set_owner, (gid_t)-1);
6738 if (ret != 0) {
6739 status = map_nt_error_from_unix(errno);
6740 if (delete_on_fail) {
6741 SMB_VFS_UNLINK(conn, smb_fname);
6743 return status;
6748 * Deal with the UNIX specific gid set.
6751 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6752 (sbuf.st_ex_gid != set_grp)) {
6753 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6754 "changing group %u for file %s\n",
6755 (unsigned int)set_owner,
6756 smb_fname_str_dbg(smb_fname)));
6757 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6758 set_grp) != 0) {
6759 status = map_nt_error_from_unix(errno);
6760 if (delete_on_fail) {
6761 SMB_VFS_UNLINK(conn, smb_fname);
6763 return status;
6767 /* Deal with any size changes. */
6769 status = smb_set_file_size(conn, req,
6770 fsp,
6771 smb_fname,
6772 &sbuf,
6773 size,
6774 false);
6775 if (!NT_STATUS_IS_OK(status)) {
6776 return status;
6779 /* Deal with any time changes. */
6780 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6781 /* No change, don't cancel anything. */
6782 return status;
6785 id = vfs_file_id_from_sbuf(conn, &sbuf);
6786 for(all_fsps = file_find_di_first(id); all_fsps;
6787 all_fsps = file_find_di_next(all_fsps)) {
6789 * We're setting the time explicitly for UNIX.
6790 * Cancel any pending changes over all handles.
6792 all_fsps->update_write_time_on_close = false;
6793 TALLOC_FREE(all_fsps->update_write_time_event);
6797 * Override the "setting_write_time"
6798 * parameter here as it almost does what
6799 * we need. Just remember if we modified
6800 * mtime and send the notify ourselves.
6802 if (null_timespec(ft.mtime)) {
6803 modify_mtime = false;
6806 status = smb_set_file_time(conn,
6807 fsp,
6808 smb_fname,
6809 &ft,
6810 false);
6811 if (modify_mtime) {
6812 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6813 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6815 return status;
6818 /****************************************************************************
6819 Deal with SMB_SET_FILE_UNIX_INFO2.
6820 ****************************************************************************/
6822 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6823 struct smb_request *req,
6824 const char *pdata,
6825 int total_data,
6826 files_struct *fsp,
6827 const struct smb_filename *smb_fname)
6829 NTSTATUS status;
6830 uint32 smb_fflags;
6831 uint32 smb_fmask;
6833 if (total_data < 116) {
6834 return NT_STATUS_INVALID_PARAMETER;
6837 /* Start by setting all the fields that are common between UNIX_BASIC
6838 * and UNIX_INFO2.
6840 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6841 fsp, smb_fname);
6842 if (!NT_STATUS_IS_OK(status)) {
6843 return status;
6846 smb_fflags = IVAL(pdata, 108);
6847 smb_fmask = IVAL(pdata, 112);
6849 /* NB: We should only attempt to alter the file flags if the client
6850 * sends a non-zero mask.
6852 if (smb_fmask != 0) {
6853 int stat_fflags = 0;
6855 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6856 smb_fmask, &stat_fflags)) {
6857 /* Client asked to alter a flag we don't understand. */
6858 return NT_STATUS_INVALID_PARAMETER;
6861 if (fsp && fsp->fh->fd != -1) {
6862 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6863 return NT_STATUS_NOT_SUPPORTED;
6864 } else {
6865 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6866 stat_fflags) != 0) {
6867 return map_nt_error_from_unix(errno);
6872 /* XXX: need to add support for changing the create_time here. You
6873 * can do this for paths on Darwin with setattrlist(2). The right way
6874 * to hook this up is probably by extending the VFS utimes interface.
6877 return NT_STATUS_OK;
6880 /****************************************************************************
6881 Create a directory with POSIX semantics.
6882 ****************************************************************************/
6884 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6885 struct smb_request *req,
6886 char **ppdata,
6887 int total_data,
6888 struct smb_filename *smb_fname,
6889 int *pdata_return_size)
6891 NTSTATUS status = NT_STATUS_OK;
6892 uint32 raw_unixmode = 0;
6893 uint32 mod_unixmode = 0;
6894 mode_t unixmode = (mode_t)0;
6895 files_struct *fsp = NULL;
6896 uint16 info_level_return = 0;
6897 int info;
6898 char *pdata = *ppdata;
6900 if (total_data < 18) {
6901 return NT_STATUS_INVALID_PARAMETER;
6904 raw_unixmode = IVAL(pdata,8);
6905 /* Next 4 bytes are not yet defined. */
6907 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6908 PERM_NEW_DIR, &unixmode);
6909 if (!NT_STATUS_IS_OK(status)) {
6910 return status;
6913 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6915 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6916 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6918 status = SMB_VFS_CREATE_FILE(
6919 conn, /* conn */
6920 req, /* req */
6921 0, /* root_dir_fid */
6922 smb_fname, /* fname */
6923 FILE_READ_ATTRIBUTES, /* access_mask */
6924 FILE_SHARE_NONE, /* share_access */
6925 FILE_CREATE, /* create_disposition*/
6926 FILE_DIRECTORY_FILE, /* create_options */
6927 mod_unixmode, /* file_attributes */
6928 0, /* oplock_request */
6929 0, /* allocation_size */
6930 NULL, /* sd */
6931 NULL, /* ea_list */
6932 &fsp, /* result */
6933 &info); /* pinfo */
6935 if (NT_STATUS_IS_OK(status)) {
6936 close_file(req, fsp, NORMAL_CLOSE);
6939 info_level_return = SVAL(pdata,16);
6941 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6942 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6943 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6944 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6945 } else {
6946 *pdata_return_size = 12;
6949 /* Realloc the data size */
6950 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6951 if (*ppdata == NULL) {
6952 *pdata_return_size = 0;
6953 return NT_STATUS_NO_MEMORY;
6955 pdata = *ppdata;
6957 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6958 SSVAL(pdata,2,0); /* No fnum. */
6959 SIVAL(pdata,4,info); /* Was directory created. */
6961 switch (info_level_return) {
6962 case SMB_QUERY_FILE_UNIX_BASIC:
6963 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6964 SSVAL(pdata,10,0); /* Padding. */
6965 store_file_unix_basic(conn, pdata + 12, fsp,
6966 &smb_fname->st);
6967 break;
6968 case SMB_QUERY_FILE_UNIX_INFO2:
6969 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6970 SSVAL(pdata,10,0); /* Padding. */
6971 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6972 &smb_fname->st);
6973 break;
6974 default:
6975 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6976 SSVAL(pdata,10,0); /* Padding. */
6977 break;
6980 return status;
6983 /****************************************************************************
6984 Open/Create a file with POSIX semantics.
6985 ****************************************************************************/
6987 static NTSTATUS smb_posix_open(connection_struct *conn,
6988 struct smb_request *req,
6989 char **ppdata,
6990 int total_data,
6991 struct smb_filename *smb_fname,
6992 int *pdata_return_size)
6994 bool extended_oplock_granted = False;
6995 char *pdata = *ppdata;
6996 uint32 flags = 0;
6997 uint32 wire_open_mode = 0;
6998 uint32 raw_unixmode = 0;
6999 uint32 mod_unixmode = 0;
7000 uint32 create_disp = 0;
7001 uint32 access_mask = 0;
7002 uint32 create_options = 0;
7003 NTSTATUS status = NT_STATUS_OK;
7004 mode_t unixmode = (mode_t)0;
7005 files_struct *fsp = NULL;
7006 int oplock_request = 0;
7007 int info = 0;
7008 uint16 info_level_return = 0;
7010 if (total_data < 18) {
7011 return NT_STATUS_INVALID_PARAMETER;
7014 flags = IVAL(pdata,0);
7015 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7016 if (oplock_request) {
7017 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7020 wire_open_mode = IVAL(pdata,4);
7022 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7023 return smb_posix_mkdir(conn, req,
7024 ppdata,
7025 total_data,
7026 smb_fname,
7027 pdata_return_size);
7030 switch (wire_open_mode & SMB_ACCMODE) {
7031 case SMB_O_RDONLY:
7032 access_mask = FILE_READ_DATA;
7033 break;
7034 case SMB_O_WRONLY:
7035 access_mask = FILE_WRITE_DATA;
7036 break;
7037 case SMB_O_RDWR:
7038 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7039 break;
7040 default:
7041 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7042 (unsigned int)wire_open_mode ));
7043 return NT_STATUS_INVALID_PARAMETER;
7046 wire_open_mode &= ~SMB_ACCMODE;
7048 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7049 create_disp = FILE_CREATE;
7050 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7051 create_disp = FILE_OVERWRITE_IF;
7052 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7053 create_disp = FILE_OPEN_IF;
7054 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7055 create_disp = FILE_OPEN;
7056 } else {
7057 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7058 (unsigned int)wire_open_mode ));
7059 return NT_STATUS_INVALID_PARAMETER;
7062 raw_unixmode = IVAL(pdata,8);
7063 /* Next 4 bytes are not yet defined. */
7065 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7066 (VALID_STAT(smb_fname->st) ?
7067 PERM_EXISTING_FILE : PERM_NEW_FILE),
7068 &unixmode);
7070 if (!NT_STATUS_IS_OK(status)) {
7071 return status;
7074 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7076 if (wire_open_mode & SMB_O_SYNC) {
7077 create_options |= FILE_WRITE_THROUGH;
7079 if (wire_open_mode & SMB_O_APPEND) {
7080 access_mask |= FILE_APPEND_DATA;
7082 if (wire_open_mode & SMB_O_DIRECT) {
7083 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7086 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7087 smb_fname_str_dbg(smb_fname),
7088 (unsigned int)wire_open_mode,
7089 (unsigned int)unixmode ));
7091 status = SMB_VFS_CREATE_FILE(
7092 conn, /* conn */
7093 req, /* req */
7094 0, /* root_dir_fid */
7095 smb_fname, /* fname */
7096 access_mask, /* access_mask */
7097 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7098 FILE_SHARE_DELETE),
7099 create_disp, /* create_disposition*/
7100 FILE_NON_DIRECTORY_FILE, /* create_options */
7101 mod_unixmode, /* file_attributes */
7102 oplock_request, /* oplock_request */
7103 0, /* allocation_size */
7104 NULL, /* sd */
7105 NULL, /* ea_list */
7106 &fsp, /* result */
7107 &info); /* pinfo */
7109 if (!NT_STATUS_IS_OK(status)) {
7110 return status;
7113 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7114 extended_oplock_granted = True;
7117 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7118 extended_oplock_granted = True;
7121 info_level_return = SVAL(pdata,16);
7123 /* Allocate the correct return size. */
7125 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7126 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7127 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7128 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7129 } else {
7130 *pdata_return_size = 12;
7133 /* Realloc the data size */
7134 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7135 if (*ppdata == NULL) {
7136 close_file(req, fsp, ERROR_CLOSE);
7137 *pdata_return_size = 0;
7138 return NT_STATUS_NO_MEMORY;
7140 pdata = *ppdata;
7142 if (extended_oplock_granted) {
7143 if (flags & REQUEST_BATCH_OPLOCK) {
7144 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7145 } else {
7146 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7148 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7149 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7150 } else {
7151 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7154 SSVAL(pdata,2,fsp->fnum);
7155 SIVAL(pdata,4,info); /* Was file created etc. */
7157 switch (info_level_return) {
7158 case SMB_QUERY_FILE_UNIX_BASIC:
7159 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7160 SSVAL(pdata,10,0); /* padding. */
7161 store_file_unix_basic(conn, pdata + 12, fsp,
7162 &smb_fname->st);
7163 break;
7164 case SMB_QUERY_FILE_UNIX_INFO2:
7165 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7166 SSVAL(pdata,10,0); /* padding. */
7167 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7168 &smb_fname->st);
7169 break;
7170 default:
7171 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7172 SSVAL(pdata,10,0); /* padding. */
7173 break;
7175 return NT_STATUS_OK;
7178 /****************************************************************************
7179 Delete a file with POSIX semantics.
7180 ****************************************************************************/
7182 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7183 struct smb_request *req,
7184 const char *pdata,
7185 int total_data,
7186 struct smb_filename *smb_fname)
7188 NTSTATUS status = NT_STATUS_OK;
7189 files_struct *fsp = NULL;
7190 uint16 flags = 0;
7191 char del = 1;
7192 int info = 0;
7193 int create_options = 0;
7194 int i;
7195 struct share_mode_lock *lck = NULL;
7197 if (total_data < 2) {
7198 return NT_STATUS_INVALID_PARAMETER;
7201 flags = SVAL(pdata,0);
7203 if (!VALID_STAT(smb_fname->st)) {
7204 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7207 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7208 !VALID_STAT_OF_DIR(smb_fname->st)) {
7209 return NT_STATUS_NOT_A_DIRECTORY;
7212 DEBUG(10,("smb_posix_unlink: %s %s\n",
7213 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7214 smb_fname_str_dbg(smb_fname)));
7216 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7217 create_options |= FILE_DIRECTORY_FILE;
7220 status = SMB_VFS_CREATE_FILE(
7221 conn, /* conn */
7222 req, /* req */
7223 0, /* root_dir_fid */
7224 smb_fname, /* fname */
7225 DELETE_ACCESS, /* access_mask */
7226 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7227 FILE_SHARE_DELETE),
7228 FILE_OPEN, /* create_disposition*/
7229 create_options, /* create_options */
7230 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7231 0, /* oplock_request */
7232 0, /* allocation_size */
7233 NULL, /* sd */
7234 NULL, /* ea_list */
7235 &fsp, /* result */
7236 &info); /* pinfo */
7238 if (!NT_STATUS_IS_OK(status)) {
7239 return status;
7243 * Don't lie to client. If we can't really delete due to
7244 * non-POSIX opens return SHARING_VIOLATION.
7247 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7248 NULL);
7249 if (lck == NULL) {
7250 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7251 "lock for file %s\n", fsp_str_dbg(fsp)));
7252 close_file(req, fsp, NORMAL_CLOSE);
7253 return NT_STATUS_INVALID_PARAMETER;
7257 * See if others still have the file open. If this is the case, then
7258 * don't delete. If all opens are POSIX delete we can set the delete
7259 * on close disposition.
7261 for (i=0; i<lck->num_share_modes; i++) {
7262 struct share_mode_entry *e = &lck->share_modes[i];
7263 if (is_valid_share_mode_entry(e)) {
7264 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7265 continue;
7267 /* Fail with sharing violation. */
7268 close_file(req, fsp, NORMAL_CLOSE);
7269 TALLOC_FREE(lck);
7270 return NT_STATUS_SHARING_VIOLATION;
7275 * Set the delete on close.
7277 status = smb_set_file_disposition_info(conn,
7278 &del,
7280 fsp,
7281 smb_fname);
7283 if (!NT_STATUS_IS_OK(status)) {
7284 close_file(req, fsp, NORMAL_CLOSE);
7285 TALLOC_FREE(lck);
7286 return status;
7288 TALLOC_FREE(lck);
7289 return close_file(req, fsp, NORMAL_CLOSE);
7292 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7293 struct smb_request *req,
7294 TALLOC_CTX *mem_ctx,
7295 uint16_t info_level,
7296 files_struct *fsp,
7297 struct smb_filename *smb_fname,
7298 char **ppdata, int total_data,
7299 int *ret_data_size)
7301 char *pdata = *ppdata;
7302 NTSTATUS status = NT_STATUS_OK;
7303 int data_return_size = 0;
7305 *ret_data_size = 0;
7307 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7308 return NT_STATUS_INVALID_LEVEL;
7311 if (!CAN_WRITE(conn)) {
7312 /* Allow POSIX opens. The open path will deny
7313 * any non-readonly opens. */
7314 if (info_level != SMB_POSIX_PATH_OPEN) {
7315 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7319 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7320 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7321 fsp ? fsp->fnum : -1, info_level, total_data));
7323 switch (info_level) {
7325 case SMB_INFO_STANDARD:
7327 status = smb_set_info_standard(conn,
7328 pdata,
7329 total_data,
7330 fsp,
7331 smb_fname);
7332 break;
7335 case SMB_INFO_SET_EA:
7337 status = smb_info_set_ea(conn,
7338 pdata,
7339 total_data,
7340 fsp,
7341 smb_fname);
7342 break;
7345 case SMB_SET_FILE_BASIC_INFO:
7346 case SMB_FILE_BASIC_INFORMATION:
7348 status = smb_set_file_basic_info(conn,
7349 pdata,
7350 total_data,
7351 fsp,
7352 smb_fname);
7353 break;
7356 case SMB_FILE_ALLOCATION_INFORMATION:
7357 case SMB_SET_FILE_ALLOCATION_INFO:
7359 status = smb_set_file_allocation_info(conn, req,
7360 pdata,
7361 total_data,
7362 fsp,
7363 smb_fname);
7364 break;
7367 case SMB_FILE_END_OF_FILE_INFORMATION:
7368 case SMB_SET_FILE_END_OF_FILE_INFO:
7371 * XP/Win7 both fail after the createfile with
7372 * SMB_SET_FILE_END_OF_FILE_INFO but not
7373 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7374 * The level is known here, so pass it down
7375 * appropriately.
7377 bool should_fail =
7378 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7380 status = smb_set_file_end_of_file_info(conn, req,
7381 pdata,
7382 total_data,
7383 fsp,
7384 smb_fname,
7385 should_fail);
7386 break;
7389 case SMB_FILE_DISPOSITION_INFORMATION:
7390 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7392 #if 0
7393 /* JRA - We used to just ignore this on a path ?
7394 * Shouldn't this be invalid level on a pathname
7395 * based call ?
7397 if (tran_call != TRANSACT2_SETFILEINFO) {
7398 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7400 #endif
7401 status = smb_set_file_disposition_info(conn,
7402 pdata,
7403 total_data,
7404 fsp,
7405 smb_fname);
7406 break;
7409 case SMB_FILE_POSITION_INFORMATION:
7411 status = smb_file_position_information(conn,
7412 pdata,
7413 total_data,
7414 fsp);
7415 break;
7418 case SMB_FILE_FULL_EA_INFORMATION:
7420 status = smb_set_file_full_ea_info(conn,
7421 pdata,
7422 total_data,
7423 fsp);
7424 break;
7427 /* From tridge Samba4 :
7428 * MODE_INFORMATION in setfileinfo (I have no
7429 * idea what "mode information" on a file is - it takes a value of 0,
7430 * 2, 4 or 6. What could it be?).
7433 case SMB_FILE_MODE_INFORMATION:
7435 status = smb_file_mode_information(conn,
7436 pdata,
7437 total_data);
7438 break;
7442 * CIFS UNIX extensions.
7445 case SMB_SET_FILE_UNIX_BASIC:
7447 status = smb_set_file_unix_basic(conn, req,
7448 pdata,
7449 total_data,
7450 fsp,
7451 smb_fname);
7452 break;
7455 case SMB_SET_FILE_UNIX_INFO2:
7457 status = smb_set_file_unix_info2(conn, req,
7458 pdata,
7459 total_data,
7460 fsp,
7461 smb_fname);
7462 break;
7465 case SMB_SET_FILE_UNIX_LINK:
7467 if (fsp) {
7468 /* We must have a pathname for this. */
7469 return NT_STATUS_INVALID_LEVEL;
7471 status = smb_set_file_unix_link(conn, req, pdata,
7472 total_data, smb_fname);
7473 break;
7476 case SMB_SET_FILE_UNIX_HLINK:
7478 if (fsp) {
7479 /* We must have a pathname for this. */
7480 return NT_STATUS_INVALID_LEVEL;
7482 status = smb_set_file_unix_hlink(conn, req,
7483 pdata, total_data,
7484 smb_fname);
7485 break;
7488 case SMB_FILE_RENAME_INFORMATION:
7490 status = smb_file_rename_information(conn, req,
7491 pdata, total_data,
7492 fsp, smb_fname);
7493 break;
7496 #if defined(HAVE_POSIX_ACLS)
7497 case SMB_SET_POSIX_ACL:
7499 status = smb_set_posix_acl(conn,
7500 pdata,
7501 total_data,
7502 fsp,
7503 smb_fname);
7504 break;
7506 #endif
7508 case SMB_SET_POSIX_LOCK:
7510 if (!fsp) {
7511 return NT_STATUS_INVALID_LEVEL;
7513 status = smb_set_posix_lock(conn, req,
7514 pdata, total_data, fsp);
7515 break;
7518 case SMB_POSIX_PATH_OPEN:
7520 if (fsp) {
7521 /* We must have a pathname for this. */
7522 return NT_STATUS_INVALID_LEVEL;
7525 status = smb_posix_open(conn, req,
7526 ppdata,
7527 total_data,
7528 smb_fname,
7529 &data_return_size);
7530 break;
7533 case SMB_POSIX_PATH_UNLINK:
7535 if (fsp) {
7536 /* We must have a pathname for this. */
7537 return NT_STATUS_INVALID_LEVEL;
7540 status = smb_posix_unlink(conn, req,
7541 pdata,
7542 total_data,
7543 smb_fname);
7544 break;
7547 default:
7548 return NT_STATUS_INVALID_LEVEL;
7551 if (!NT_STATUS_IS_OK(status)) {
7552 return status;
7555 *ret_data_size = data_return_size;
7556 return NT_STATUS_OK;
7559 /****************************************************************************
7560 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7561 ****************************************************************************/
7563 static void call_trans2setfilepathinfo(connection_struct *conn,
7564 struct smb_request *req,
7565 unsigned int tran_call,
7566 char **pparams, int total_params,
7567 char **ppdata, int total_data,
7568 unsigned int max_data_bytes)
7570 char *params = *pparams;
7571 char *pdata = *ppdata;
7572 uint16 info_level;
7573 struct smb_filename *smb_fname = NULL;
7574 files_struct *fsp = NULL;
7575 NTSTATUS status = NT_STATUS_OK;
7576 int data_return_size = 0;
7578 if (!params) {
7579 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7580 return;
7583 if (tran_call == TRANSACT2_SETFILEINFO) {
7584 if (total_params < 4) {
7585 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7586 return;
7589 fsp = file_fsp(req, SVAL(params,0));
7590 /* Basic check for non-null fsp. */
7591 if (!check_fsp_open(conn, req, fsp)) {
7592 return;
7594 info_level = SVAL(params,2);
7596 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7597 &smb_fname);
7598 if (!NT_STATUS_IS_OK(status)) {
7599 reply_nterror(req, status);
7600 return;
7603 if(fsp->is_directory || fsp->fh->fd == -1) {
7605 * This is actually a SETFILEINFO on a directory
7606 * handle (returned from an NT SMB). NT5.0 seems
7607 * to do this call. JRA.
7609 if (INFO_LEVEL_IS_UNIX(info_level)) {
7610 /* Always do lstat for UNIX calls. */
7611 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7612 DEBUG(3,("call_trans2setfilepathinfo: "
7613 "SMB_VFS_LSTAT of %s failed "
7614 "(%s)\n",
7615 smb_fname_str_dbg(smb_fname),
7616 strerror(errno)));
7617 reply_nterror(req, map_nt_error_from_unix(errno));
7618 return;
7620 } else {
7621 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7622 DEBUG(3,("call_trans2setfilepathinfo: "
7623 "fileinfo of %s failed (%s)\n",
7624 smb_fname_str_dbg(smb_fname),
7625 strerror(errno)));
7626 reply_nterror(req, map_nt_error_from_unix(errno));
7627 return;
7630 } else if (fsp->print_file) {
7632 * Doing a DELETE_ON_CLOSE should cancel a print job.
7634 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7635 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7637 DEBUG(3,("call_trans2setfilepathinfo: "
7638 "Cancelling print job (%s)\n",
7639 fsp_str_dbg(fsp)));
7641 SSVAL(params,0,0);
7642 send_trans2_replies(conn, req, params, 2,
7643 *ppdata, 0,
7644 max_data_bytes);
7645 return;
7646 } else {
7647 reply_nterror(req,
7648 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7649 return;
7651 } else {
7653 * Original code - this is an open file.
7655 if (!check_fsp(conn, req, fsp)) {
7656 return;
7659 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7660 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7661 "of fnum %d failed (%s)\n", fsp->fnum,
7662 strerror(errno)));
7663 reply_nterror(req, map_nt_error_from_unix(errno));
7664 return;
7667 } else {
7668 char *fname = NULL;
7670 /* set path info */
7671 if (total_params < 7) {
7672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7673 return;
7676 info_level = SVAL(params,0);
7677 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7678 total_params - 6, STR_TERMINATE,
7679 &status);
7680 if (!NT_STATUS_IS_OK(status)) {
7681 reply_nterror(req, status);
7682 return;
7685 status = filename_convert(req, conn,
7686 req->flags2 & FLAGS2_DFS_PATHNAMES,
7687 fname,
7689 NULL,
7690 &smb_fname);
7691 if (!NT_STATUS_IS_OK(status)) {
7692 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7693 reply_botherror(req,
7694 NT_STATUS_PATH_NOT_COVERED,
7695 ERRSRV, ERRbadpath);
7696 return;
7698 reply_nterror(req, status);
7699 return;
7702 if (INFO_LEVEL_IS_UNIX(info_level)) {
7704 * For CIFS UNIX extensions the target name may not exist.
7707 /* Always do lstat for UNIX calls. */
7708 SMB_VFS_LSTAT(conn, smb_fname);
7710 } else if (!VALID_STAT(smb_fname->st) &&
7711 SMB_VFS_STAT(conn, smb_fname)) {
7712 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7713 "%s failed (%s)\n",
7714 smb_fname_str_dbg(smb_fname),
7715 strerror(errno)));
7716 reply_nterror(req, map_nt_error_from_unix(errno));
7717 return;
7721 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7722 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7723 fsp ? fsp->fnum : -1, info_level,total_data));
7725 /* Realloc the parameter size */
7726 *pparams = (char *)SMB_REALLOC(*pparams,2);
7727 if (*pparams == NULL) {
7728 reply_nterror(req, NT_STATUS_NO_MEMORY);
7729 return;
7731 params = *pparams;
7733 SSVAL(params,0,0);
7735 status = smbd_do_setfilepathinfo(conn, req, req,
7736 info_level,
7737 fsp,
7738 smb_fname,
7739 ppdata, total_data,
7740 &data_return_size);
7741 if (!NT_STATUS_IS_OK(status)) {
7742 if (open_was_deferred(req->mid)) {
7743 /* We have re-scheduled this call. */
7744 return;
7746 if (blocking_lock_was_deferred(req->mid)) {
7747 /* We have re-scheduled this call. */
7748 return;
7750 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7751 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7752 ERRSRV, ERRbadpath);
7753 return;
7755 if (info_level == SMB_POSIX_PATH_OPEN) {
7756 reply_openerror(req, status);
7757 return;
7760 reply_nterror(req, status);
7761 return;
7764 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7765 max_data_bytes);
7767 return;
7770 /****************************************************************************
7771 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7772 ****************************************************************************/
7774 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7775 char **pparams, int total_params,
7776 char **ppdata, int total_data,
7777 unsigned int max_data_bytes)
7779 struct smb_filename *smb_dname = NULL;
7780 char *params = *pparams;
7781 char *pdata = *ppdata;
7782 char *directory = NULL;
7783 NTSTATUS status = NT_STATUS_OK;
7784 struct ea_list *ea_list = NULL;
7785 TALLOC_CTX *ctx = talloc_tos();
7787 if (!CAN_WRITE(conn)) {
7788 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7789 return;
7792 if (total_params < 5) {
7793 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7794 return;
7797 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7798 total_params - 4, STR_TERMINATE,
7799 &status);
7800 if (!NT_STATUS_IS_OK(status)) {
7801 reply_nterror(req, status);
7802 return;
7805 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7807 status = filename_convert(ctx,
7808 conn,
7809 req->flags2 & FLAGS2_DFS_PATHNAMES,
7810 directory,
7812 NULL,
7813 &smb_dname);
7815 if (!NT_STATUS_IS_OK(status)) {
7816 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7817 reply_botherror(req,
7818 NT_STATUS_PATH_NOT_COVERED,
7819 ERRSRV, ERRbadpath);
7820 return;
7822 reply_nterror(req, status);
7823 return;
7827 * OS/2 workplace shell seems to send SET_EA requests of "null"
7828 * length (4 bytes containing IVAL 4).
7829 * They seem to have no effect. Bug #3212. JRA.
7832 if (total_data && (total_data != 4)) {
7833 /* Any data in this call is an EA list. */
7834 if (total_data < 10) {
7835 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7836 goto out;
7839 if (IVAL(pdata,0) > total_data) {
7840 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7841 IVAL(pdata,0), (unsigned int)total_data));
7842 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7843 goto out;
7846 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7847 total_data - 4);
7848 if (!ea_list) {
7849 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7850 goto out;
7853 if (!lp_ea_support(SNUM(conn))) {
7854 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7855 goto out;
7858 /* If total_data == 4 Windows doesn't care what values
7859 * are placed in that field, it just ignores them.
7860 * The System i QNTC IBM SMB client puts bad values here,
7861 * so ignore them. */
7863 status = create_directory(conn, req, smb_dname);
7865 if (!NT_STATUS_IS_OK(status)) {
7866 reply_nterror(req, status);
7867 goto out;
7870 /* Try and set any given EA. */
7871 if (ea_list) {
7872 status = set_ea(conn, NULL, smb_dname, ea_list);
7873 if (!NT_STATUS_IS_OK(status)) {
7874 reply_nterror(req, status);
7875 goto out;
7879 /* Realloc the parameter and data sizes */
7880 *pparams = (char *)SMB_REALLOC(*pparams,2);
7881 if(*pparams == NULL) {
7882 reply_nterror(req, NT_STATUS_NO_MEMORY);
7883 goto out;
7885 params = *pparams;
7887 SSVAL(params,0,0);
7889 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7891 out:
7892 TALLOC_FREE(smb_dname);
7893 return;
7896 /****************************************************************************
7897 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7898 We don't actually do this - we just send a null response.
7899 ****************************************************************************/
7901 static void call_trans2findnotifyfirst(connection_struct *conn,
7902 struct smb_request *req,
7903 char **pparams, int total_params,
7904 char **ppdata, int total_data,
7905 unsigned int max_data_bytes)
7907 char *params = *pparams;
7908 uint16 info_level;
7910 if (total_params < 6) {
7911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7912 return;
7915 info_level = SVAL(params,4);
7916 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7918 switch (info_level) {
7919 case 1:
7920 case 2:
7921 break;
7922 default:
7923 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7924 return;
7927 /* Realloc the parameter and data sizes */
7928 *pparams = (char *)SMB_REALLOC(*pparams,6);
7929 if (*pparams == NULL) {
7930 reply_nterror(req, NT_STATUS_NO_MEMORY);
7931 return;
7933 params = *pparams;
7935 SSVAL(params,0,fnf_handle);
7936 SSVAL(params,2,0); /* No changes */
7937 SSVAL(params,4,0); /* No EA errors */
7939 fnf_handle++;
7941 if(fnf_handle == 0)
7942 fnf_handle = 257;
7944 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7946 return;
7949 /****************************************************************************
7950 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7951 changes). Currently this does nothing.
7952 ****************************************************************************/
7954 static void call_trans2findnotifynext(connection_struct *conn,
7955 struct smb_request *req,
7956 char **pparams, int total_params,
7957 char **ppdata, int total_data,
7958 unsigned int max_data_bytes)
7960 char *params = *pparams;
7962 DEBUG(3,("call_trans2findnotifynext\n"));
7964 /* Realloc the parameter and data sizes */
7965 *pparams = (char *)SMB_REALLOC(*pparams,4);
7966 if (*pparams == NULL) {
7967 reply_nterror(req, NT_STATUS_NO_MEMORY);
7968 return;
7970 params = *pparams;
7972 SSVAL(params,0,0); /* No changes */
7973 SSVAL(params,2,0); /* No EA errors */
7975 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7977 return;
7980 /****************************************************************************
7981 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7982 ****************************************************************************/
7984 static void call_trans2getdfsreferral(connection_struct *conn,
7985 struct smb_request *req,
7986 char **pparams, int total_params,
7987 char **ppdata, int total_data,
7988 unsigned int max_data_bytes)
7990 char *params = *pparams;
7991 char *pathname = NULL;
7992 int reply_size = 0;
7993 int max_referral_level;
7994 NTSTATUS status = NT_STATUS_OK;
7995 TALLOC_CTX *ctx = talloc_tos();
7997 DEBUG(10,("call_trans2getdfsreferral\n"));
7999 if (total_params < 3) {
8000 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8001 return;
8004 max_referral_level = SVAL(params,0);
8006 if(!lp_host_msdfs()) {
8007 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8008 return;
8011 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8012 total_params - 2, STR_TERMINATE);
8013 if (!pathname) {
8014 reply_nterror(req, NT_STATUS_NOT_FOUND);
8015 return;
8017 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8018 ppdata,&status)) < 0) {
8019 reply_nterror(req, status);
8020 return;
8023 SSVAL(req->inbuf, smb_flg2,
8024 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8025 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8027 return;
8030 #define LMCAT_SPL 0x53
8031 #define LMFUNC_GETJOBID 0x60
8033 /****************************************************************************
8034 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8035 ****************************************************************************/
8037 static void call_trans2ioctl(connection_struct *conn,
8038 struct smb_request *req,
8039 char **pparams, int total_params,
8040 char **ppdata, int total_data,
8041 unsigned int max_data_bytes)
8043 char *pdata = *ppdata;
8044 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8046 /* check for an invalid fid before proceeding */
8048 if (!fsp) {
8049 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8050 return;
8053 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8054 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8055 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8056 if (*ppdata == NULL) {
8057 reply_nterror(req, NT_STATUS_NO_MEMORY);
8058 return;
8060 pdata = *ppdata;
8062 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8063 CAN ACCEPT THIS IN UNICODE. JRA. */
8065 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8066 srvstr_push(pdata, req->flags2, pdata + 2,
8067 global_myname(), 15,
8068 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8069 srvstr_push(pdata, req->flags2, pdata+18,
8070 lp_servicename(SNUM(conn)), 13,
8071 STR_ASCII|STR_TERMINATE); /* Service name */
8072 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8073 max_data_bytes);
8074 return;
8077 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8078 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8081 /****************************************************************************
8082 Reply to a SMBfindclose (stop trans2 directory search).
8083 ****************************************************************************/
8085 void reply_findclose(struct smb_request *req)
8087 int dptr_num;
8088 struct smbd_server_connection *sconn = smbd_server_conn;
8090 START_PROFILE(SMBfindclose);
8092 if (req->wct < 1) {
8093 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8094 END_PROFILE(SMBfindclose);
8095 return;
8098 dptr_num = SVALS(req->vwv+0, 0);
8100 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8102 dptr_close(sconn, &dptr_num);
8104 reply_outbuf(req, 0, 0);
8106 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8108 END_PROFILE(SMBfindclose);
8109 return;
8112 /****************************************************************************
8113 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8114 ****************************************************************************/
8116 void reply_findnclose(struct smb_request *req)
8118 int dptr_num;
8120 START_PROFILE(SMBfindnclose);
8122 if (req->wct < 1) {
8123 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8124 END_PROFILE(SMBfindnclose);
8125 return;
8128 dptr_num = SVAL(req->vwv+0, 0);
8130 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8132 /* We never give out valid handles for a
8133 findnotifyfirst - so any dptr_num is ok here.
8134 Just ignore it. */
8136 reply_outbuf(req, 0, 0);
8138 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8140 END_PROFILE(SMBfindnclose);
8141 return;
8144 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8145 struct trans_state *state)
8147 if (get_Protocol() >= PROTOCOL_NT1) {
8148 req->flags2 |= 0x40; /* IS_LONG_NAME */
8149 SSVAL(req->inbuf,smb_flg2,req->flags2);
8152 if (conn->encrypt_level == Required && !req->encrypted) {
8153 if (state->call != TRANSACT2_QFSINFO &&
8154 state->call != TRANSACT2_SETFSINFO) {
8155 DEBUG(0,("handle_trans2: encryption required "
8156 "with call 0x%x\n",
8157 (unsigned int)state->call));
8158 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8159 return;
8163 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8165 /* Now we must call the relevant TRANS2 function */
8166 switch(state->call) {
8167 case TRANSACT2_OPEN:
8169 START_PROFILE(Trans2_open);
8170 call_trans2open(conn, req,
8171 &state->param, state->total_param,
8172 &state->data, state->total_data,
8173 state->max_data_return);
8174 END_PROFILE(Trans2_open);
8175 break;
8178 case TRANSACT2_FINDFIRST:
8180 START_PROFILE(Trans2_findfirst);
8181 call_trans2findfirst(conn, req,
8182 &state->param, state->total_param,
8183 &state->data, state->total_data,
8184 state->max_data_return);
8185 END_PROFILE(Trans2_findfirst);
8186 break;
8189 case TRANSACT2_FINDNEXT:
8191 START_PROFILE(Trans2_findnext);
8192 call_trans2findnext(conn, req,
8193 &state->param, state->total_param,
8194 &state->data, state->total_data,
8195 state->max_data_return);
8196 END_PROFILE(Trans2_findnext);
8197 break;
8200 case TRANSACT2_QFSINFO:
8202 START_PROFILE(Trans2_qfsinfo);
8203 call_trans2qfsinfo(conn, req,
8204 &state->param, state->total_param,
8205 &state->data, state->total_data,
8206 state->max_data_return);
8207 END_PROFILE(Trans2_qfsinfo);
8208 break;
8211 case TRANSACT2_SETFSINFO:
8213 START_PROFILE(Trans2_setfsinfo);
8214 call_trans2setfsinfo(conn, req,
8215 &state->param, state->total_param,
8216 &state->data, state->total_data,
8217 state->max_data_return);
8218 END_PROFILE(Trans2_setfsinfo);
8219 break;
8222 case TRANSACT2_QPATHINFO:
8223 case TRANSACT2_QFILEINFO:
8225 START_PROFILE(Trans2_qpathinfo);
8226 call_trans2qfilepathinfo(conn, req, state->call,
8227 &state->param, state->total_param,
8228 &state->data, state->total_data,
8229 state->max_data_return);
8230 END_PROFILE(Trans2_qpathinfo);
8231 break;
8234 case TRANSACT2_SETPATHINFO:
8235 case TRANSACT2_SETFILEINFO:
8237 START_PROFILE(Trans2_setpathinfo);
8238 call_trans2setfilepathinfo(conn, req, state->call,
8239 &state->param, state->total_param,
8240 &state->data, state->total_data,
8241 state->max_data_return);
8242 END_PROFILE(Trans2_setpathinfo);
8243 break;
8246 case TRANSACT2_FINDNOTIFYFIRST:
8248 START_PROFILE(Trans2_findnotifyfirst);
8249 call_trans2findnotifyfirst(conn, req,
8250 &state->param, state->total_param,
8251 &state->data, state->total_data,
8252 state->max_data_return);
8253 END_PROFILE(Trans2_findnotifyfirst);
8254 break;
8257 case TRANSACT2_FINDNOTIFYNEXT:
8259 START_PROFILE(Trans2_findnotifynext);
8260 call_trans2findnotifynext(conn, req,
8261 &state->param, state->total_param,
8262 &state->data, state->total_data,
8263 state->max_data_return);
8264 END_PROFILE(Trans2_findnotifynext);
8265 break;
8268 case TRANSACT2_MKDIR:
8270 START_PROFILE(Trans2_mkdir);
8271 call_trans2mkdir(conn, req,
8272 &state->param, state->total_param,
8273 &state->data, state->total_data,
8274 state->max_data_return);
8275 END_PROFILE(Trans2_mkdir);
8276 break;
8279 case TRANSACT2_GET_DFS_REFERRAL:
8281 START_PROFILE(Trans2_get_dfs_referral);
8282 call_trans2getdfsreferral(conn, req,
8283 &state->param, state->total_param,
8284 &state->data, state->total_data,
8285 state->max_data_return);
8286 END_PROFILE(Trans2_get_dfs_referral);
8287 break;
8290 case TRANSACT2_IOCTL:
8292 START_PROFILE(Trans2_ioctl);
8293 call_trans2ioctl(conn, req,
8294 &state->param, state->total_param,
8295 &state->data, state->total_data,
8296 state->max_data_return);
8297 END_PROFILE(Trans2_ioctl);
8298 break;
8301 default:
8302 /* Error in request */
8303 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8304 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8308 /****************************************************************************
8309 Reply to a SMBtrans2.
8310 ****************************************************************************/
8312 void reply_trans2(struct smb_request *req)
8314 connection_struct *conn = req->conn;
8315 unsigned int dsoff;
8316 unsigned int dscnt;
8317 unsigned int psoff;
8318 unsigned int pscnt;
8319 unsigned int tran_call;
8320 struct trans_state *state;
8321 NTSTATUS result;
8323 START_PROFILE(SMBtrans2);
8325 if (req->wct < 14) {
8326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8327 END_PROFILE(SMBtrans2);
8328 return;
8331 dsoff = SVAL(req->vwv+12, 0);
8332 dscnt = SVAL(req->vwv+11, 0);
8333 psoff = SVAL(req->vwv+10, 0);
8334 pscnt = SVAL(req->vwv+9, 0);
8335 tran_call = SVAL(req->vwv+14, 0);
8337 result = allow_new_trans(conn->pending_trans, req->mid);
8338 if (!NT_STATUS_IS_OK(result)) {
8339 DEBUG(2, ("Got invalid trans2 request: %s\n",
8340 nt_errstr(result)));
8341 reply_nterror(req, result);
8342 END_PROFILE(SMBtrans2);
8343 return;
8346 if (IS_IPC(conn)) {
8347 switch (tran_call) {
8348 /* List the allowed trans2 calls on IPC$ */
8349 case TRANSACT2_OPEN:
8350 case TRANSACT2_GET_DFS_REFERRAL:
8351 case TRANSACT2_QFILEINFO:
8352 case TRANSACT2_QFSINFO:
8353 case TRANSACT2_SETFSINFO:
8354 break;
8355 default:
8356 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8357 END_PROFILE(SMBtrans2);
8358 return;
8362 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8363 DEBUG(0, ("talloc failed\n"));
8364 reply_nterror(req, NT_STATUS_NO_MEMORY);
8365 END_PROFILE(SMBtrans2);
8366 return;
8369 state->cmd = SMBtrans2;
8371 state->mid = req->mid;
8372 state->vuid = req->vuid;
8373 state->setup_count = SVAL(req->vwv+13, 0);
8374 state->setup = NULL;
8375 state->total_param = SVAL(req->vwv+0, 0);
8376 state->param = NULL;
8377 state->total_data = SVAL(req->vwv+1, 0);
8378 state->data = NULL;
8379 state->max_param_return = SVAL(req->vwv+2, 0);
8380 state->max_data_return = SVAL(req->vwv+3, 0);
8381 state->max_setup_return = SVAL(req->vwv+4, 0);
8382 state->close_on_completion = BITSETW(req->vwv+5, 0);
8383 state->one_way = BITSETW(req->vwv+5, 1);
8385 state->call = tran_call;
8387 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8388 is so as a sanity check */
8389 if (state->setup_count != 1) {
8391 * Need to have rc=0 for ioctl to get job id for OS/2.
8392 * Network printing will fail if function is not successful.
8393 * Similar function in reply.c will be used if protocol
8394 * is LANMAN1.0 instead of LM1.2X002.
8395 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8396 * outbuf doesn't have to be set(only job id is used).
8398 if ( (state->setup_count == 4)
8399 && (tran_call == TRANSACT2_IOCTL)
8400 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8401 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8402 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8403 } else {
8404 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8405 DEBUG(2,("Transaction is %d\n",tran_call));
8406 TALLOC_FREE(state);
8407 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8408 END_PROFILE(SMBtrans2);
8409 return;
8413 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8414 goto bad_param;
8416 if (state->total_data) {
8418 if (trans_oob(state->total_data, 0, dscnt)
8419 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8420 goto bad_param;
8423 /* Can't use talloc here, the core routines do realloc on the
8424 * params and data. */
8425 state->data = (char *)SMB_MALLOC(state->total_data);
8426 if (state->data == NULL) {
8427 DEBUG(0,("reply_trans2: data malloc fail for %u "
8428 "bytes !\n", (unsigned int)state->total_data));
8429 TALLOC_FREE(state);
8430 reply_nterror(req, NT_STATUS_NO_MEMORY);
8431 END_PROFILE(SMBtrans2);
8432 return;
8435 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8438 if (state->total_param) {
8440 if (trans_oob(state->total_param, 0, pscnt)
8441 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8442 goto bad_param;
8445 /* Can't use talloc here, the core routines do realloc on the
8446 * params and data. */
8447 state->param = (char *)SMB_MALLOC(state->total_param);
8448 if (state->param == NULL) {
8449 DEBUG(0,("reply_trans: param malloc fail for %u "
8450 "bytes !\n", (unsigned int)state->total_param));
8451 SAFE_FREE(state->data);
8452 TALLOC_FREE(state);
8453 reply_nterror(req, NT_STATUS_NO_MEMORY);
8454 END_PROFILE(SMBtrans2);
8455 return;
8458 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8461 state->received_data = dscnt;
8462 state->received_param = pscnt;
8464 if ((state->received_param == state->total_param) &&
8465 (state->received_data == state->total_data)) {
8467 handle_trans2(conn, req, state);
8469 SAFE_FREE(state->data);
8470 SAFE_FREE(state->param);
8471 TALLOC_FREE(state);
8472 END_PROFILE(SMBtrans2);
8473 return;
8476 DLIST_ADD(conn->pending_trans, state);
8478 /* We need to send an interim response then receive the rest
8479 of the parameter/data bytes */
8480 reply_outbuf(req, 0, 0);
8481 show_msg((char *)req->outbuf);
8482 END_PROFILE(SMBtrans2);
8483 return;
8485 bad_param:
8487 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8488 SAFE_FREE(state->data);
8489 SAFE_FREE(state->param);
8490 TALLOC_FREE(state);
8491 END_PROFILE(SMBtrans2);
8492 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8496 /****************************************************************************
8497 Reply to a SMBtranss2
8498 ****************************************************************************/
8500 void reply_transs2(struct smb_request *req)
8502 connection_struct *conn = req->conn;
8503 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8504 struct trans_state *state;
8506 START_PROFILE(SMBtranss2);
8508 show_msg((char *)req->inbuf);
8510 if (req->wct < 8) {
8511 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8512 END_PROFILE(SMBtranss2);
8513 return;
8516 for (state = conn->pending_trans; state != NULL;
8517 state = state->next) {
8518 if (state->mid == req->mid) {
8519 break;
8523 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8524 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8525 END_PROFILE(SMBtranss2);
8526 return;
8529 /* Revise state->total_param and state->total_data in case they have
8530 changed downwards */
8532 if (SVAL(req->vwv+0, 0) < state->total_param)
8533 state->total_param = SVAL(req->vwv+0, 0);
8534 if (SVAL(req->vwv+1, 0) < state->total_data)
8535 state->total_data = SVAL(req->vwv+1, 0);
8537 pcnt = SVAL(req->vwv+2, 0);
8538 poff = SVAL(req->vwv+3, 0);
8539 pdisp = SVAL(req->vwv+4, 0);
8541 dcnt = SVAL(req->vwv+5, 0);
8542 doff = SVAL(req->vwv+6, 0);
8543 ddisp = SVAL(req->vwv+7, 0);
8545 state->received_param += pcnt;
8546 state->received_data += dcnt;
8548 if ((state->received_data > state->total_data) ||
8549 (state->received_param > state->total_param))
8550 goto bad_param;
8552 if (pcnt) {
8553 if (trans_oob(state->total_param, pdisp, pcnt)
8554 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8555 goto bad_param;
8557 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8560 if (dcnt) {
8561 if (trans_oob(state->total_data, ddisp, dcnt)
8562 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8563 goto bad_param;
8565 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8568 if ((state->received_param < state->total_param) ||
8569 (state->received_data < state->total_data)) {
8570 END_PROFILE(SMBtranss2);
8571 return;
8574 handle_trans2(conn, req, state);
8576 DLIST_REMOVE(conn->pending_trans, state);
8577 SAFE_FREE(state->data);
8578 SAFE_FREE(state->param);
8579 TALLOC_FREE(state);
8581 END_PROFILE(SMBtranss2);
8582 return;
8584 bad_param:
8586 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8587 DLIST_REMOVE(conn->pending_trans, state);
8588 SAFE_FREE(state->data);
8589 SAFE_FREE(state->param);
8590 TALLOC_FREE(state);
8591 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8592 END_PROFILE(SMBtranss2);
8593 return;