s3:librpc/gen_ndr: regen after wbint.idl changes
[Samba.git] / source3 / smbd / trans2.c
blob0d144213e0323f924ef1a45751489614f244b119
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "version.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 #define DIR_ENTRY_SAFETY_MARGIN 4096
33 static char *store_file_unix_basic(connection_struct *conn,
34 char *pdata,
35 files_struct *fsp,
36 const SMB_STRUCT_STAT *psbuf);
38 static char *store_file_unix_basic_info2(connection_struct *conn,
39 char *pdata,
40 files_struct *fsp,
41 const SMB_STRUCT_STAT *psbuf);
43 /********************************************************************
44 Roundup a value to the nearest allocation roundup size boundary.
45 Only do this for Windows clients.
46 ********************************************************************/
48 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
50 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
52 /* Only roundup for Windows clients. */
53 enum remote_arch_types ra_type = get_remote_arch();
54 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
55 val = SMB_ROUNDUP(val,rval);
57 return val;
60 /********************************************************************
61 Create a 64 bit FileIndex. If the file is on the same device as
62 the root of the share, just return the 64-bit inode. If it isn't,
63 mangle as we used to do.
64 ********************************************************************/
66 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
68 uint64_t file_index;
69 if (conn->base_share_dev == psbuf->st_ex_dev) {
70 return (uint64_t)psbuf->st_ex_ino;
72 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
73 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
74 return file_index;
77 /****************************************************************************
78 Utility functions for dealing with extended attributes.
79 ****************************************************************************/
81 /****************************************************************************
82 Refuse to allow clients to overwrite our private xattrs.
83 ****************************************************************************/
85 static bool samba_private_attr_name(const char *unix_ea_name)
87 static const char * const prohibited_ea_names[] = {
88 SAMBA_POSIX_INHERITANCE_EA_NAME,
89 SAMBA_XATTR_DOS_ATTRIB,
90 SAMBA_XATTR_MARKER,
91 XATTR_NTACL_NAME,
92 NULL
95 int i;
97 for (i = 0; prohibited_ea_names[i]; i++) {
98 if (strequal( prohibited_ea_names[i], unix_ea_name))
99 return true;
101 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
102 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
103 return true;
105 return false;
108 /****************************************************************************
109 Get one EA value. Fill in a struct ea_struct.
110 ****************************************************************************/
112 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
113 files_struct *fsp, const char *fname,
114 const char *ea_name, struct ea_struct *pea)
116 /* Get the value of this xattr. Max size is 64k. */
117 size_t attr_size = 256;
118 char *val = NULL;
119 ssize_t sizeret;
121 again:
123 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
124 if (!val) {
125 return NT_STATUS_NO_MEMORY;
128 if (fsp && fsp->fh->fd != -1) {
129 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
130 } else {
131 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
134 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
135 attr_size = 65536;
136 goto again;
139 if (sizeret == -1) {
140 return map_nt_error_from_unix(errno);
143 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
144 dump_data(10, (uint8 *)val, sizeret);
146 pea->flags = 0;
147 if (strnequal(ea_name, "user.", 5)) {
148 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
149 } else {
150 pea->name = talloc_strdup(mem_ctx, ea_name);
152 if (pea->name == NULL) {
153 TALLOC_FREE(val);
154 return NT_STATUS_NO_MEMORY;
156 pea->value.data = (unsigned char *)val;
157 pea->value.length = (size_t)sizeret;
158 return NT_STATUS_OK;
161 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
162 files_struct *fsp, const char *fname,
163 char ***pnames, size_t *pnum_names)
165 /* Get a list of all xattrs. Max namesize is 64k. */
166 size_t ea_namelist_size = 1024;
167 char *ea_namelist = NULL;
169 char *p;
170 char **names, **tmp;
171 size_t num_names;
172 ssize_t sizeret = -1;
174 if (!lp_ea_support(SNUM(conn))) {
175 if (pnames) {
176 *pnames = NULL;
178 *pnum_names = 0;
179 return NT_STATUS_OK;
183 * TALLOC the result early to get the talloc hierarchy right.
186 names = TALLOC_ARRAY(mem_ctx, char *, 1);
187 if (names == NULL) {
188 DEBUG(0, ("talloc failed\n"));
189 return NT_STATUS_NO_MEMORY;
192 while (ea_namelist_size <= 65536) {
194 ea_namelist = TALLOC_REALLOC_ARRAY(
195 names, ea_namelist, char, ea_namelist_size);
196 if (ea_namelist == NULL) {
197 DEBUG(0, ("talloc failed\n"));
198 TALLOC_FREE(names);
199 return NT_STATUS_NO_MEMORY;
202 if (fsp && fsp->fh->fd != -1) {
203 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
204 ea_namelist_size);
205 } else {
206 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
207 ea_namelist_size);
210 if ((sizeret == -1) && (errno == ERANGE)) {
211 ea_namelist_size *= 2;
213 else {
214 break;
218 if (sizeret == -1) {
219 TALLOC_FREE(names);
220 return map_nt_error_from_unix(errno);
223 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
224 (unsigned int)sizeret));
226 if (sizeret == 0) {
227 TALLOC_FREE(names);
228 if (pnames) {
229 *pnames = NULL;
231 *pnum_names = 0;
232 return NT_STATUS_OK;
236 * Ensure the result is 0-terminated
239 if (ea_namelist[sizeret-1] != '\0') {
240 TALLOC_FREE(names);
241 return NT_STATUS_INTERNAL_ERROR;
245 * count the names
247 num_names = 0;
249 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
250 num_names += 1;
253 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
254 if (tmp == NULL) {
255 DEBUG(0, ("talloc failed\n"));
256 TALLOC_FREE(names);
257 return NT_STATUS_NO_MEMORY;
260 names = tmp;
261 num_names = 0;
263 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
264 names[num_names++] = p;
267 if (pnames) {
268 *pnames = names;
269 } else {
270 TALLOC_FREE(names);
272 *pnum_names = num_names;
273 return NT_STATUS_OK;
276 /****************************************************************************
277 Return a linked list of the total EA's. Plus the total size
278 ****************************************************************************/
280 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
281 const char *fname, size_t *pea_total_len)
283 /* Get a list of all xattrs. Max namesize is 64k. */
284 size_t i, num_names;
285 char **names;
286 struct ea_list *ea_list_head = NULL;
287 NTSTATUS status;
289 *pea_total_len = 0;
291 if (!lp_ea_support(SNUM(conn))) {
292 return NULL;
295 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
296 &names, &num_names);
298 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
299 return NULL;
302 for (i=0; i<num_names; i++) {
303 struct ea_list *listp;
304 fstring dos_ea_name;
306 if (strnequal(names[i], "system.", 7)
307 || samba_private_attr_name(names[i]))
308 continue;
310 listp = TALLOC_P(mem_ctx, struct ea_list);
311 if (listp == NULL) {
312 return NULL;
315 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
316 fname, names[i],
317 &listp->ea))) {
318 return NULL;
321 push_ascii_fstring(dos_ea_name, listp->ea.name);
323 *pea_total_len +=
324 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
326 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
327 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
328 (unsigned int)listp->ea.value.length));
330 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
334 /* Add on 4 for total length. */
335 if (*pea_total_len) {
336 *pea_total_len += 4;
339 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
340 (unsigned int)*pea_total_len));
342 return ea_list_head;
345 /****************************************************************************
346 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
347 that was filled.
348 ****************************************************************************/
350 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
351 connection_struct *conn, struct ea_list *ea_list)
353 unsigned int ret_data_size = 4;
354 char *p = pdata;
356 SMB_ASSERT(total_data_size >= 4);
358 if (!lp_ea_support(SNUM(conn))) {
359 SIVAL(pdata,4,0);
360 return 4;
363 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
364 size_t dos_namelen;
365 fstring dos_ea_name;
366 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
367 dos_namelen = strlen(dos_ea_name);
368 if (dos_namelen > 255 || dos_namelen == 0) {
369 break;
371 if (ea_list->ea.value.length > 65535) {
372 break;
374 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
375 break;
378 /* We know we have room. */
379 SCVAL(p,0,ea_list->ea.flags);
380 SCVAL(p,1,dos_namelen);
381 SSVAL(p,2,ea_list->ea.value.length);
382 fstrcpy(p+4, dos_ea_name);
383 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
385 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
386 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
389 ret_data_size = PTR_DIFF(p, pdata);
390 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
391 SIVAL(pdata,0,ret_data_size);
392 return ret_data_size;
395 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
396 char *pdata,
397 unsigned int total_data_size,
398 unsigned int *ret_data_size,
399 connection_struct *conn,
400 struct ea_list *ea_list)
402 uint8_t *p = (uint8_t *)pdata;
403 uint8_t *last_start = NULL;
405 *ret_data_size = 0;
407 if (!lp_ea_support(SNUM(conn))) {
408 return NT_STATUS_NO_EAS_ON_FILE;
411 for (; ea_list; ea_list = ea_list->next) {
412 size_t dos_namelen;
413 fstring dos_ea_name;
414 size_t this_size;
416 if (last_start) {
417 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
419 last_start = p;
421 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
422 dos_namelen = strlen(dos_ea_name);
423 if (dos_namelen > 255 || dos_namelen == 0) {
424 return NT_STATUS_INTERNAL_ERROR;
426 if (ea_list->ea.value.length > 65535) {
427 return NT_STATUS_INTERNAL_ERROR;
430 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
432 if (ea_list->next) {
433 size_t pad = 4 - (this_size % 4);
434 this_size += pad;
437 if (this_size > total_data_size) {
438 return NT_STATUS_INFO_LENGTH_MISMATCH;
441 /* We know we have room. */
442 SIVAL(p, 0x00, 0); /* next offset */
443 SCVAL(p, 0x04, ea_list->ea.flags);
444 SCVAL(p, 0x05, dos_namelen);
445 SSVAL(p, 0x06, ea_list->ea.value.length);
446 fstrcpy((char *)(p+0x08), dos_ea_name);
447 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
449 total_data_size -= this_size;
450 p += this_size;
453 *ret_data_size = PTR_DIFF(p, pdata);
454 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
455 return NT_STATUS_OK;
458 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
460 size_t total_ea_len = 0;
461 TALLOC_CTX *mem_ctx = NULL;
463 if (!lp_ea_support(SNUM(conn))) {
464 return 0;
466 mem_ctx = talloc_tos();
467 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
468 return total_ea_len;
471 /****************************************************************************
472 Ensure the EA name is case insensitive by matching any existing EA name.
473 ****************************************************************************/
475 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
477 size_t total_ea_len;
478 TALLOC_CTX *mem_ctx = talloc_tos();
479 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
481 for (; ea_list; ea_list = ea_list->next) {
482 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
483 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
484 &unix_ea_name[5], ea_list->ea.name));
485 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
486 break;
491 /****************************************************************************
492 Set or delete an extended attribute.
493 ****************************************************************************/
495 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
496 const struct smb_filename *smb_fname, struct ea_list *ea_list)
498 char *fname = NULL;
500 if (!lp_ea_support(SNUM(conn))) {
501 return NT_STATUS_EAS_NOT_SUPPORTED;
504 /* For now setting EAs on streams isn't supported. */
505 fname = smb_fname->base_name;
507 for (;ea_list; ea_list = ea_list->next) {
508 int ret;
509 fstring unix_ea_name;
511 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
512 fstrcat(unix_ea_name, ea_list->ea.name);
514 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
516 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
518 if (samba_private_attr_name(unix_ea_name)) {
519 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
520 return NT_STATUS_ACCESS_DENIED;
523 if (ea_list->ea.value.length == 0) {
524 /* Remove the attribute. */
525 if (fsp && (fsp->fh->fd != -1)) {
526 DEBUG(10,("set_ea: deleting ea name %s on "
527 "file %s by file descriptor.\n",
528 unix_ea_name, fsp_str_dbg(fsp)));
529 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
530 } else {
531 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
532 unix_ea_name, fname));
533 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
535 #ifdef ENOATTR
536 /* Removing a non existent attribute always succeeds. */
537 if (ret == -1 && errno == ENOATTR) {
538 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
539 unix_ea_name));
540 ret = 0;
542 #endif
543 } else {
544 if (fsp && (fsp->fh->fd != -1)) {
545 DEBUG(10,("set_ea: setting ea name %s on file "
546 "%s by file descriptor.\n",
547 unix_ea_name, fsp_str_dbg(fsp)));
548 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
549 ea_list->ea.value.data, ea_list->ea.value.length, 0);
550 } else {
551 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
552 unix_ea_name, fname));
553 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
554 ea_list->ea.value.data, ea_list->ea.value.length, 0);
558 if (ret == -1) {
559 #ifdef ENOTSUP
560 if (errno == ENOTSUP) {
561 return NT_STATUS_EAS_NOT_SUPPORTED;
563 #endif
564 return map_nt_error_from_unix(errno);
568 return NT_STATUS_OK;
570 /****************************************************************************
571 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
572 ****************************************************************************/
574 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
576 struct ea_list *ea_list_head = NULL;
577 size_t converted_size, offset = 0;
579 while (offset + 2 < data_size) {
580 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
581 unsigned int namelen = CVAL(pdata,offset);
583 offset++; /* Go past the namelen byte. */
585 /* integer wrap paranioa. */
586 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
587 (offset > data_size) || (namelen > data_size) ||
588 (offset + namelen >= data_size)) {
589 break;
591 /* Ensure the name is null terminated. */
592 if (pdata[offset + namelen] != '\0') {
593 return NULL;
595 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
596 &converted_size)) {
597 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
598 "failed: %s", strerror(errno)));
600 if (!eal->ea.name) {
601 return NULL;
604 offset += (namelen + 1); /* Go past the name + terminating zero. */
605 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
606 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
609 return ea_list_head;
612 /****************************************************************************
613 Read one EA list entry from the buffer.
614 ****************************************************************************/
616 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
618 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
619 uint16 val_len;
620 unsigned int namelen;
621 size_t converted_size;
623 if (!eal) {
624 return NULL;
627 if (data_size < 6) {
628 return NULL;
631 eal->ea.flags = CVAL(pdata,0);
632 namelen = CVAL(pdata,1);
633 val_len = SVAL(pdata,2);
635 if (4 + namelen + 1 + val_len > data_size) {
636 return NULL;
639 /* Ensure the name is null terminated. */
640 if (pdata[namelen + 4] != '\0') {
641 return NULL;
643 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
644 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
645 strerror(errno)));
647 if (!eal->ea.name) {
648 return NULL;
651 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
652 if (!eal->ea.value.data) {
653 return NULL;
656 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
658 /* Ensure we're null terminated just in case we print the value. */
659 eal->ea.value.data[val_len] = '\0';
660 /* But don't count the null. */
661 eal->ea.value.length--;
663 if (pbytes_used) {
664 *pbytes_used = 4 + namelen + 1 + val_len;
667 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
668 dump_data(10, eal->ea.value.data, eal->ea.value.length);
670 return eal;
673 /****************************************************************************
674 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
675 ****************************************************************************/
677 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
679 struct ea_list *ea_list_head = NULL;
680 size_t offset = 0;
681 size_t bytes_used = 0;
683 while (offset < data_size) {
684 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
686 if (!eal) {
687 return NULL;
690 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
691 offset += bytes_used;
694 return ea_list_head;
697 /****************************************************************************
698 Count the total EA size needed.
699 ****************************************************************************/
701 static size_t ea_list_size(struct ea_list *ealist)
703 fstring dos_ea_name;
704 struct ea_list *listp;
705 size_t ret = 0;
707 for (listp = ealist; listp; listp = listp->next) {
708 push_ascii_fstring(dos_ea_name, listp->ea.name);
709 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
711 /* Add on 4 for total length. */
712 if (ret) {
713 ret += 4;
716 return ret;
719 /****************************************************************************
720 Return a union of EA's from a file list and a list of names.
721 The TALLOC context for the two lists *MUST* be identical as we steal
722 memory from one list to add to another. JRA.
723 ****************************************************************************/
725 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
727 struct ea_list *nlistp, *flistp;
729 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
730 for (flistp = file_list; flistp; flistp = flistp->next) {
731 if (strequal(nlistp->ea.name, flistp->ea.name)) {
732 break;
736 if (flistp) {
737 /* Copy the data from this entry. */
738 nlistp->ea.flags = flistp->ea.flags;
739 nlistp->ea.value = flistp->ea.value;
740 } else {
741 /* Null entry. */
742 nlistp->ea.flags = 0;
743 ZERO_STRUCT(nlistp->ea.value);
747 *total_ea_len = ea_list_size(name_list);
748 return name_list;
751 /****************************************************************************
752 Send the required number of replies back.
753 We assume all fields other than the data fields are
754 set correctly for the type of call.
755 HACK ! Always assumes smb_setup field is zero.
756 ****************************************************************************/
758 void send_trans2_replies(connection_struct *conn,
759 struct smb_request *req,
760 const char *params,
761 int paramsize,
762 const char *pdata,
763 int datasize,
764 int max_data_bytes)
766 /* As we are using a protocol > LANMAN1 then the max_send
767 variable must have been set in the sessetupX call.
768 This takes precedence over the max_xmit field in the
769 global struct. These different max_xmit variables should
770 be merged as this is now too confusing */
772 int data_to_send = datasize;
773 int params_to_send = paramsize;
774 int useable_space;
775 const char *pp = params;
776 const char *pd = pdata;
777 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
778 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
779 int data_alignment_offset = 0;
780 bool overflow = False;
781 struct smbd_server_connection *sconn = smbd_server_conn;
782 int max_send = sconn->smb1.sessions.max_send;
784 /* Modify the data_to_send and datasize and set the error if
785 we're trying to send more than max_data_bytes. We still send
786 the part of the packet(s) that fit. Strange, but needed
787 for OS/2. */
789 if (max_data_bytes > 0 && datasize > max_data_bytes) {
790 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
791 max_data_bytes, datasize ));
792 datasize = data_to_send = max_data_bytes;
793 overflow = True;
796 /* If there genuinely are no parameters or data to send just send the empty packet */
798 if(params_to_send == 0 && data_to_send == 0) {
799 reply_outbuf(req, 10, 0);
800 show_msg((char *)req->outbuf);
801 if (!srv_send_smb(smbd_server_fd(),
802 (char *)req->outbuf,
803 true, req->seqnum+1,
804 IS_CONN_ENCRYPTED(conn),
805 &req->pcd)) {
806 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
808 TALLOC_FREE(req->outbuf);
809 return;
812 /* When sending params and data ensure that both are nicely aligned */
813 /* Only do this alignment when there is also data to send - else
814 can cause NT redirector problems. */
816 if (((params_to_send % 4) != 0) && (data_to_send != 0))
817 data_alignment_offset = 4 - (params_to_send % 4);
819 /* Space is bufsize minus Netbios over TCP header minus SMB header */
820 /* The alignment_offset is to align the param bytes on an even byte
821 boundary. NT 4.0 Beta needs this to work correctly. */
823 useable_space = max_send - (smb_size
824 + 2 * 10 /* wct */
825 + alignment_offset
826 + data_alignment_offset);
828 if (useable_space < 0) {
829 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
830 "= %d!!!", useable_space));
831 exit_server_cleanly("send_trans2_replies: Not enough space");
834 while (params_to_send || data_to_send) {
835 /* Calculate whether we will totally or partially fill this packet */
837 total_sent_thistime = params_to_send + data_to_send;
839 /* We can never send more than useable_space */
841 * Note that 'useable_space' does not include the alignment offsets,
842 * but we must include the alignment offsets in the calculation of
843 * the length of the data we send over the wire, as the alignment offsets
844 * are sent here. Fix from Marc_Jacobsen@hp.com.
847 total_sent_thistime = MIN(total_sent_thistime, useable_space);
849 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
850 + data_alignment_offset);
853 * We might have SMBtrans2s in req which was transferred to
854 * the outbuf, fix that.
856 SCVAL(req->outbuf, smb_com, SMBtrans2);
858 /* Set total params and data to be sent */
859 SSVAL(req->outbuf,smb_tprcnt,paramsize);
860 SSVAL(req->outbuf,smb_tdrcnt,datasize);
862 /* Calculate how many parameters and data we can fit into
863 * this packet. Parameters get precedence
866 params_sent_thistime = MIN(params_to_send,useable_space);
867 data_sent_thistime = useable_space - params_sent_thistime;
868 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
870 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
872 /* smb_proff is the offset from the start of the SMB header to the
873 parameter bytes, however the first 4 bytes of outbuf are
874 the Netbios over TCP header. Thus use smb_base() to subtract
875 them from the calculation */
877 SSVAL(req->outbuf,smb_proff,
878 ((smb_buf(req->outbuf)+alignment_offset)
879 - smb_base(req->outbuf)));
881 if(params_sent_thistime == 0)
882 SSVAL(req->outbuf,smb_prdisp,0);
883 else
884 /* Absolute displacement of param bytes sent in this packet */
885 SSVAL(req->outbuf,smb_prdisp,pp - params);
887 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
888 if(data_sent_thistime == 0) {
889 SSVAL(req->outbuf,smb_droff,0);
890 SSVAL(req->outbuf,smb_drdisp, 0);
891 } else {
892 /* The offset of the data bytes is the offset of the
893 parameter bytes plus the number of parameters being sent this time */
894 SSVAL(req->outbuf, smb_droff,
895 ((smb_buf(req->outbuf)+alignment_offset)
896 - smb_base(req->outbuf))
897 + params_sent_thistime + data_alignment_offset);
898 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
901 /* Initialize the padding for alignment */
903 if (alignment_offset != 0) {
904 memset(smb_buf(req->outbuf), 0, alignment_offset);
907 /* Copy the param bytes into the packet */
909 if(params_sent_thistime) {
910 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
911 params_sent_thistime);
914 /* Copy in the data bytes */
915 if(data_sent_thistime) {
916 if (data_alignment_offset != 0) {
917 memset((smb_buf(req->outbuf)+alignment_offset+
918 params_sent_thistime), 0,
919 data_alignment_offset);
921 memcpy(smb_buf(req->outbuf)+alignment_offset
922 +params_sent_thistime+data_alignment_offset,
923 pd,data_sent_thistime);
926 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
927 params_sent_thistime, data_sent_thistime, useable_space));
928 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
929 params_to_send, data_to_send, paramsize, datasize));
931 if (overflow) {
932 error_packet_set((char *)req->outbuf,
933 ERRDOS,ERRbufferoverflow,
934 STATUS_BUFFER_OVERFLOW,
935 __LINE__,__FILE__);
938 /* Send the packet */
939 show_msg((char *)req->outbuf);
940 if (!srv_send_smb(smbd_server_fd(),
941 (char *)req->outbuf,
942 true, req->seqnum+1,
943 IS_CONN_ENCRYPTED(conn),
944 &req->pcd))
945 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
947 TALLOC_FREE(req->outbuf);
949 pp += params_sent_thistime;
950 pd += data_sent_thistime;
952 params_to_send -= params_sent_thistime;
953 data_to_send -= data_sent_thistime;
955 /* Sanity check */
956 if(params_to_send < 0 || data_to_send < 0) {
957 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
958 params_to_send, data_to_send));
959 return;
963 return;
966 /****************************************************************************
967 Reply to a TRANSACT2_OPEN.
968 ****************************************************************************/
970 static void call_trans2open(connection_struct *conn,
971 struct smb_request *req,
972 char **pparams, int total_params,
973 char **ppdata, int total_data,
974 unsigned int max_data_bytes)
976 struct smb_filename *smb_fname = NULL;
977 char *params = *pparams;
978 char *pdata = *ppdata;
979 int deny_mode;
980 int32 open_attr;
981 bool oplock_request;
982 #if 0
983 bool return_additional_info;
984 int16 open_sattr;
985 time_t open_time;
986 #endif
987 int open_ofun;
988 uint32 open_size;
989 char *pname;
990 char *fname = NULL;
991 SMB_OFF_T size=0;
992 int fattr=0,mtime=0;
993 SMB_INO_T inode = 0;
994 int smb_action = 0;
995 files_struct *fsp;
996 struct ea_list *ea_list = NULL;
997 uint16 flags = 0;
998 NTSTATUS status;
999 uint32 access_mask;
1000 uint32 share_mode;
1001 uint32 create_disposition;
1002 uint32 create_options = 0;
1003 TALLOC_CTX *ctx = talloc_tos();
1006 * Ensure we have enough parameters to perform the operation.
1009 if (total_params < 29) {
1010 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1011 goto out;
1014 flags = SVAL(params, 0);
1015 deny_mode = SVAL(params, 2);
1016 open_attr = SVAL(params,6);
1017 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1018 if (oplock_request) {
1019 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1022 #if 0
1023 return_additional_info = BITSETW(params,0);
1024 open_sattr = SVAL(params, 4);
1025 open_time = make_unix_date3(params+8);
1026 #endif
1027 open_ofun = SVAL(params,12);
1028 open_size = IVAL(params,14);
1029 pname = &params[28];
1031 if (IS_IPC(conn)) {
1032 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1033 goto out;
1036 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1037 total_params - 28, STR_TERMINATE,
1038 &status);
1039 if (!NT_STATUS_IS_OK(status)) {
1040 reply_nterror(req, status);
1041 goto out;
1044 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1045 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1046 (unsigned int)open_ofun, open_size));
1048 status = filename_convert(ctx,
1049 conn,
1050 req->flags2 & FLAGS2_DFS_PATHNAMES,
1051 fname,
1053 NULL,
1054 &smb_fname);
1055 if (!NT_STATUS_IS_OK(status)) {
1056 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1057 reply_botherror(req,
1058 NT_STATUS_PATH_NOT_COVERED,
1059 ERRSRV, ERRbadpath);
1060 goto out;
1062 reply_nterror(req, status);
1063 goto out;
1066 if (open_ofun == 0) {
1067 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1068 goto out;
1071 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1072 &access_mask, &share_mode,
1073 &create_disposition,
1074 &create_options)) {
1075 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1076 goto out;
1079 /* Any data in this call is an EA list. */
1080 if (total_data && (total_data != 4)) {
1081 if (total_data < 10) {
1082 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1083 goto out;
1086 if (IVAL(pdata,0) > total_data) {
1087 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1088 IVAL(pdata,0), (unsigned int)total_data));
1089 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1090 goto out;
1093 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1094 total_data - 4);
1095 if (!ea_list) {
1096 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1097 goto out;
1100 if (!lp_ea_support(SNUM(conn))) {
1101 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1102 goto out;
1106 status = SMB_VFS_CREATE_FILE(
1107 conn, /* conn */
1108 req, /* req */
1109 0, /* root_dir_fid */
1110 smb_fname, /* fname */
1111 access_mask, /* access_mask */
1112 share_mode, /* share_access */
1113 create_disposition, /* create_disposition*/
1114 create_options, /* create_options */
1115 open_attr, /* file_attributes */
1116 oplock_request, /* oplock_request */
1117 open_size, /* allocation_size */
1118 NULL, /* sd */
1119 ea_list, /* ea_list */
1120 &fsp, /* result */
1121 &smb_action); /* psbuf */
1123 if (!NT_STATUS_IS_OK(status)) {
1124 if (open_was_deferred(req->mid)) {
1125 /* We have re-scheduled this call. */
1126 goto out;
1128 reply_openerror(req, status);
1129 goto out;
1132 size = get_file_size_stat(&smb_fname->st);
1133 fattr = dos_mode(conn, smb_fname);
1134 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1135 inode = smb_fname->st.st_ex_ino;
1136 if (fattr & aDIR) {
1137 close_file(req, fsp, ERROR_CLOSE);
1138 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1139 goto out;
1142 /* Realloc the size of parameters and data we will return */
1143 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1144 if(*pparams == NULL ) {
1145 reply_nterror(req, NT_STATUS_NO_MEMORY);
1146 goto out;
1148 params = *pparams;
1150 SSVAL(params,0,fsp->fnum);
1151 SSVAL(params,2,fattr);
1152 srv_put_dos_date2(params,4, mtime);
1153 SIVAL(params,8, (uint32)size);
1154 SSVAL(params,12,deny_mode);
1155 SSVAL(params,14,0); /* open_type - file or directory. */
1156 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1158 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1159 smb_action |= EXTENDED_OPLOCK_GRANTED;
1162 SSVAL(params,18,smb_action);
1165 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1167 SIVAL(params,20,inode);
1168 SSVAL(params,24,0); /* Padding. */
1169 if (flags & 8) {
1170 uint32 ea_size = estimate_ea_size(conn, fsp,
1171 fsp->fsp_name->base_name);
1172 SIVAL(params, 26, ea_size);
1173 } else {
1174 SIVAL(params, 26, 0);
1177 /* Send the required number of replies */
1178 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1179 out:
1180 TALLOC_FREE(smb_fname);
1183 /*********************************************************
1184 Routine to check if a given string matches exactly.
1185 as a special case a mask of "." does NOT match. That
1186 is required for correct wildcard semantics
1187 Case can be significant or not.
1188 **********************************************************/
1190 static bool exact_match(bool has_wild,
1191 bool case_sensitive,
1192 const char *str,
1193 const char *mask)
1195 if (mask[0] == '.' && mask[1] == 0) {
1196 return false;
1199 if (has_wild) {
1200 return false;
1203 if (case_sensitive) {
1204 return strcmp(str,mask)==0;
1205 } else {
1206 return StrCaseCmp(str,mask) == 0;
1210 /****************************************************************************
1211 Return the filetype for UNIX extensions.
1212 ****************************************************************************/
1214 static uint32 unix_filetype(mode_t mode)
1216 if(S_ISREG(mode))
1217 return UNIX_TYPE_FILE;
1218 else if(S_ISDIR(mode))
1219 return UNIX_TYPE_DIR;
1220 #ifdef S_ISLNK
1221 else if(S_ISLNK(mode))
1222 return UNIX_TYPE_SYMLINK;
1223 #endif
1224 #ifdef S_ISCHR
1225 else if(S_ISCHR(mode))
1226 return UNIX_TYPE_CHARDEV;
1227 #endif
1228 #ifdef S_ISBLK
1229 else if(S_ISBLK(mode))
1230 return UNIX_TYPE_BLKDEV;
1231 #endif
1232 #ifdef S_ISFIFO
1233 else if(S_ISFIFO(mode))
1234 return UNIX_TYPE_FIFO;
1235 #endif
1236 #ifdef S_ISSOCK
1237 else if(S_ISSOCK(mode))
1238 return UNIX_TYPE_SOCKET;
1239 #endif
1241 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1242 return UNIX_TYPE_UNKNOWN;
1245 /****************************************************************************
1246 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1247 ****************************************************************************/
1249 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1251 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1252 const SMB_STRUCT_STAT *psbuf,
1253 uint32 perms,
1254 enum perm_type ptype,
1255 mode_t *ret_perms)
1257 mode_t ret = 0;
1259 if (perms == SMB_MODE_NO_CHANGE) {
1260 if (!VALID_STAT(*psbuf)) {
1261 return NT_STATUS_INVALID_PARAMETER;
1262 } else {
1263 *ret_perms = psbuf->st_ex_mode;
1264 return NT_STATUS_OK;
1268 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1269 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1270 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1271 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1272 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1273 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1274 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1275 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1276 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1277 #ifdef S_ISVTX
1278 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1279 #endif
1280 #ifdef S_ISGID
1281 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1282 #endif
1283 #ifdef S_ISUID
1284 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1285 #endif
1287 switch (ptype) {
1288 case PERM_NEW_FILE:
1289 /* Apply mode mask */
1290 ret &= lp_create_mask(SNUM(conn));
1291 /* Add in force bits */
1292 ret |= lp_force_create_mode(SNUM(conn));
1293 break;
1294 case PERM_NEW_DIR:
1295 ret &= lp_dir_mask(SNUM(conn));
1296 /* Add in force bits */
1297 ret |= lp_force_dir_mode(SNUM(conn));
1298 break;
1299 case PERM_EXISTING_FILE:
1300 /* Apply mode mask */
1301 ret &= lp_security_mask(SNUM(conn));
1302 /* Add in force bits */
1303 ret |= lp_force_security_mode(SNUM(conn));
1304 break;
1305 case PERM_EXISTING_DIR:
1306 /* Apply mode mask */
1307 ret &= lp_dir_security_mask(SNUM(conn));
1308 /* Add in force bits */
1309 ret |= lp_force_dir_security_mode(SNUM(conn));
1310 break;
1313 *ret_perms = ret;
1314 return NT_STATUS_OK;
1317 /****************************************************************************
1318 Needed to show the msdfs symlinks as directories. Modifies psbuf
1319 to be a directory if it's a msdfs link.
1320 ****************************************************************************/
1322 static bool check_msdfs_link(connection_struct *conn,
1323 const char *pathname,
1324 SMB_STRUCT_STAT *psbuf)
1326 int saved_errno = errno;
1327 if(lp_host_msdfs() &&
1328 lp_msdfs_root(SNUM(conn)) &&
1329 is_msdfs_link(conn, pathname, psbuf)) {
1331 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1332 "as a directory\n",
1333 pathname));
1334 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1335 errno = saved_errno;
1336 return true;
1338 errno = saved_errno;
1339 return false;
1343 /****************************************************************************
1344 Get a level dependent lanman2 dir entry.
1345 ****************************************************************************/
1347 struct smbd_dirptr_lanman2_state {
1348 connection_struct *conn;
1349 uint32_t info_level;
1350 bool check_mangled_names;
1351 bool has_wild;
1352 bool got_exact_match;
1355 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1356 void *private_data,
1357 const char *dname,
1358 const char *mask,
1359 char **_fname)
1361 struct smbd_dirptr_lanman2_state *state =
1362 (struct smbd_dirptr_lanman2_state *)private_data;
1363 bool ok;
1364 char mangled_name[13]; /* mangled 8.3 name. */
1365 bool got_match;
1366 const char *fname;
1368 /* Mangle fname if it's an illegal name. */
1369 if (mangle_must_mangle(dname, state->conn->params)) {
1370 ok = name_to_8_3(dname, mangled_name,
1371 true, state->conn->params);
1372 if (!ok) {
1373 return false;
1375 fname = mangled_name;
1376 } else {
1377 fname = dname;
1380 got_match = exact_match(state->has_wild,
1381 state->conn->case_sensitive,
1382 fname, mask);
1383 state->got_exact_match = got_match;
1384 if (!got_match) {
1385 got_match = mask_match(fname, mask,
1386 state->conn->case_sensitive);
1389 if(!got_match && state->check_mangled_names &&
1390 !mangle_is_8_3(fname, false, state->conn->params)) {
1392 * It turns out that NT matches wildcards against
1393 * both long *and* short names. This may explain some
1394 * of the wildcard wierdness from old DOS clients
1395 * that some people have been seeing.... JRA.
1397 /* Force the mangling into 8.3. */
1398 ok = name_to_8_3(fname, mangled_name,
1399 false, state->conn->params);
1400 if (!ok) {
1401 return false;
1404 got_match = exact_match(state->has_wild,
1405 state->conn->case_sensitive,
1406 mangled_name, mask);
1407 state->got_exact_match = got_match;
1408 if (!got_match) {
1409 got_match = mask_match(mangled_name, mask,
1410 state->conn->case_sensitive);
1414 if (!got_match) {
1415 return false;
1418 *_fname = talloc_strdup(ctx, fname);
1419 if (*_fname == NULL) {
1420 return false;
1423 return true;
1426 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1427 void *private_data,
1428 struct smb_filename *smb_fname,
1429 uint32_t *_mode)
1431 struct smbd_dirptr_lanman2_state *state =
1432 (struct smbd_dirptr_lanman2_state *)private_data;
1433 bool ms_dfs_link = false;
1434 uint32_t mode = 0;
1436 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1437 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1438 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1439 "Couldn't lstat [%s] (%s)\n",
1440 smb_fname_str_dbg(smb_fname),
1441 strerror(errno)));
1442 return false;
1444 } else if (!VALID_STAT(smb_fname->st) &&
1445 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1446 /* Needed to show the msdfs symlinks as
1447 * directories */
1449 ms_dfs_link = check_msdfs_link(state->conn,
1450 smb_fname->base_name,
1451 &smb_fname->st);
1452 if (!ms_dfs_link) {
1453 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1454 "Couldn't stat [%s] (%s)\n",
1455 smb_fname_str_dbg(smb_fname),
1456 strerror(errno)));
1457 return false;
1461 if (ms_dfs_link) {
1462 mode = dos_mode_msdfs(state->conn, smb_fname);
1463 } else {
1464 mode = dos_mode(state->conn, smb_fname);
1467 *_mode = mode;
1468 return true;
1471 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1472 connection_struct *conn,
1473 uint16_t flags2,
1474 uint32_t info_level,
1475 struct ea_list *name_list,
1476 bool check_mangled_names,
1477 bool requires_resume_key,
1478 uint32_t mode,
1479 const char *fname,
1480 const struct smb_filename *smb_fname,
1481 uint64_t space_remaining,
1482 uint8_t align,
1483 bool do_pad,
1484 char *base_data,
1485 char **ppdata,
1486 char *end_data,
1487 bool *out_of_space,
1488 uint64_t *last_entry_off)
1490 char *p, *q, *pdata = *ppdata;
1491 uint32_t reskey=0;
1492 uint64_t file_size = 0;
1493 uint64_t allocation_size = 0;
1494 uint64_t file_index = 0;
1495 uint32_t len;
1496 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1497 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1498 time_t c_date = (time_t)0;
1499 char *nameptr;
1500 char *last_entry_ptr;
1501 bool was_8_3;
1502 off_t off;
1503 off_t pad = 0;
1505 *out_of_space = false;
1507 ZERO_STRUCT(mdate_ts);
1508 ZERO_STRUCT(adate_ts);
1509 ZERO_STRUCT(create_date_ts);
1510 ZERO_STRUCT(cdate_ts);
1512 if (!(mode & aDIR)) {
1513 file_size = get_file_size_stat(&smb_fname->st);
1515 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1517 file_index = get_FileIndex(conn, &smb_fname->st);
1519 mdate_ts = smb_fname->st.st_ex_mtime;
1520 adate_ts = smb_fname->st.st_ex_atime;
1521 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1522 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1524 if (lp_dos_filetime_resolution(SNUM(conn))) {
1525 dos_filetime_timespec(&create_date_ts);
1526 dos_filetime_timespec(&mdate_ts);
1527 dos_filetime_timespec(&adate_ts);
1528 dos_filetime_timespec(&cdate_ts);
1531 create_date = convert_timespec_to_time_t(create_date_ts);
1532 mdate = convert_timespec_to_time_t(mdate_ts);
1533 adate = convert_timespec_to_time_t(adate_ts);
1534 c_date = convert_timespec_to_time_t(cdate_ts);
1536 /* align the record */
1537 off = PTR_DIFF(pdata, base_data);
1538 pad = (off + (align-1)) & ~(align-1);
1539 pad -= off;
1540 off += pad;
1541 /* initialize padding to 0 */
1542 if (pad) {
1543 memset(pdata, 0, pad);
1545 space_remaining -= pad;
1547 pdata += pad;
1548 p = pdata;
1549 last_entry_ptr = p;
1551 pad = 0;
1552 off = 0;
1554 switch (info_level) {
1555 case SMB_FIND_INFO_STANDARD:
1556 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1557 if(requires_resume_key) {
1558 SIVAL(p,0,reskey);
1559 p += 4;
1561 srv_put_dos_date2(p,0,create_date);
1562 srv_put_dos_date2(p,4,adate);
1563 srv_put_dos_date2(p,8,mdate);
1564 SIVAL(p,12,(uint32)file_size);
1565 SIVAL(p,16,(uint32)allocation_size);
1566 SSVAL(p,20,mode);
1567 p += 23;
1568 nameptr = p;
1569 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1570 p += ucs2_align(base_data, p, 0);
1572 len = srvstr_push(base_data, flags2, p,
1573 fname, PTR_DIFF(end_data, p),
1574 STR_TERMINATE);
1575 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1576 if (len > 2) {
1577 SCVAL(nameptr, -1, len - 2);
1578 } else {
1579 SCVAL(nameptr, -1, 0);
1581 } else {
1582 if (len > 1) {
1583 SCVAL(nameptr, -1, len - 1);
1584 } else {
1585 SCVAL(nameptr, -1, 0);
1588 p += len;
1589 break;
1591 case SMB_FIND_EA_SIZE:
1592 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1593 if (requires_resume_key) {
1594 SIVAL(p,0,reskey);
1595 p += 4;
1597 srv_put_dos_date2(p,0,create_date);
1598 srv_put_dos_date2(p,4,adate);
1599 srv_put_dos_date2(p,8,mdate);
1600 SIVAL(p,12,(uint32)file_size);
1601 SIVAL(p,16,(uint32)allocation_size);
1602 SSVAL(p,20,mode);
1604 unsigned int ea_size = estimate_ea_size(conn, NULL,
1605 smb_fname->base_name);
1606 SIVAL(p,22,ea_size); /* Extended attributes */
1608 p += 27;
1609 nameptr = p - 1;
1610 len = srvstr_push(base_data, flags2,
1611 p, fname, PTR_DIFF(end_data, p),
1612 STR_TERMINATE | STR_NOALIGN);
1613 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1614 if (len > 2) {
1615 len -= 2;
1616 } else {
1617 len = 0;
1619 } else {
1620 if (len > 1) {
1621 len -= 1;
1622 } else {
1623 len = 0;
1626 SCVAL(nameptr,0,len);
1627 p += len;
1628 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1629 break;
1631 case SMB_FIND_EA_LIST:
1633 struct ea_list *file_list = NULL;
1634 size_t ea_len = 0;
1636 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1637 if (!name_list) {
1638 return false;
1640 if (requires_resume_key) {
1641 SIVAL(p,0,reskey);
1642 p += 4;
1644 srv_put_dos_date2(p,0,create_date);
1645 srv_put_dos_date2(p,4,adate);
1646 srv_put_dos_date2(p,8,mdate);
1647 SIVAL(p,12,(uint32)file_size);
1648 SIVAL(p,16,(uint32)allocation_size);
1649 SSVAL(p,20,mode);
1650 p += 22; /* p now points to the EA area. */
1652 file_list = get_ea_list_from_file(ctx, conn, NULL,
1653 smb_fname->base_name,
1654 &ea_len);
1655 name_list = ea_list_union(name_list, file_list, &ea_len);
1657 /* We need to determine if this entry will fit in the space available. */
1658 /* Max string size is 255 bytes. */
1659 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1660 *out_of_space = true;
1661 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1662 return False; /* Not finished - just out of space */
1665 /* Push the ea_data followed by the name. */
1666 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1667 nameptr = p;
1668 len = srvstr_push(base_data, flags2,
1669 p + 1, fname, PTR_DIFF(end_data, p+1),
1670 STR_TERMINATE | STR_NOALIGN);
1671 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1672 if (len > 2) {
1673 len -= 2;
1674 } else {
1675 len = 0;
1677 } else {
1678 if (len > 1) {
1679 len -= 1;
1680 } else {
1681 len = 0;
1684 SCVAL(nameptr,0,len);
1685 p += len + 1;
1686 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1687 break;
1690 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1691 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1692 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1693 p += 4;
1694 SIVAL(p,0,reskey); p += 4;
1695 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1696 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1697 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1698 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1699 SOFF_T(p,0,file_size); p += 8;
1700 SOFF_T(p,0,allocation_size); p += 8;
1701 SIVAL(p,0,mode); p += 4;
1702 q = p; p += 4; /* q is placeholder for name length. */
1704 unsigned int ea_size = estimate_ea_size(conn, NULL,
1705 smb_fname->base_name);
1706 SIVAL(p,0,ea_size); /* Extended attributes */
1707 p += 4;
1709 /* Clear the short name buffer. This is
1710 * IMPORTANT as not doing so will trigger
1711 * a Win2k client bug. JRA.
1713 if (!was_8_3 && check_mangled_names) {
1714 char mangled_name[13]; /* mangled 8.3 name. */
1715 if (!name_to_8_3(fname,mangled_name,True,
1716 conn->params)) {
1717 /* Error - mangle failed ! */
1718 memset(mangled_name,'\0',12);
1720 mangled_name[12] = 0;
1721 len = srvstr_push(base_data, flags2,
1722 p+2, mangled_name, 24,
1723 STR_UPPER|STR_UNICODE);
1724 if (len < 24) {
1725 memset(p + 2 + len,'\0',24 - len);
1727 SSVAL(p, 0, len);
1728 } else {
1729 memset(p,'\0',26);
1731 p += 2 + 24;
1732 len = srvstr_push(base_data, flags2, p,
1733 fname, PTR_DIFF(end_data, p),
1734 STR_TERMINATE_ASCII);
1735 SIVAL(q,0,len);
1736 p += len;
1738 len = PTR_DIFF(p, pdata);
1739 pad = (len + (align-1)) & ~(align-1);
1741 * offset to the next entry, the caller
1742 * will overwrite it for the last entry
1743 * that's why we always include the padding
1745 SIVAL(pdata,0,pad);
1747 * set padding to zero
1749 if (do_pad) {
1750 memset(p, 0, pad - len);
1751 p = pdata + pad;
1752 } else {
1753 p = pdata + len;
1755 break;
1757 case SMB_FIND_FILE_DIRECTORY_INFO:
1758 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1759 p += 4;
1760 SIVAL(p,0,reskey); p += 4;
1761 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1762 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1763 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1764 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1765 SOFF_T(p,0,file_size); p += 8;
1766 SOFF_T(p,0,allocation_size); p += 8;
1767 SIVAL(p,0,mode); p += 4;
1768 len = srvstr_push(base_data, flags2,
1769 p + 4, fname, PTR_DIFF(end_data, p+4),
1770 STR_TERMINATE_ASCII);
1771 SIVAL(p,0,len);
1772 p += 4 + len;
1774 len = PTR_DIFF(p, pdata);
1775 pad = (len + (align-1)) & ~(align-1);
1777 * offset to the next entry, the caller
1778 * will overwrite it for the last entry
1779 * that's why we always include the padding
1781 SIVAL(pdata,0,pad);
1783 * set padding to zero
1785 if (do_pad) {
1786 memset(p, 0, pad - len);
1787 p = pdata + pad;
1788 } else {
1789 p = pdata + len;
1791 break;
1793 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1794 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1795 p += 4;
1796 SIVAL(p,0,reskey); p += 4;
1797 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1798 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1799 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1800 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1801 SOFF_T(p,0,file_size); p += 8;
1802 SOFF_T(p,0,allocation_size); p += 8;
1803 SIVAL(p,0,mode); p += 4;
1804 q = p; p += 4; /* q is placeholder for name length. */
1806 unsigned int ea_size = estimate_ea_size(conn, NULL,
1807 smb_fname->base_name);
1808 SIVAL(p,0,ea_size); /* Extended attributes */
1809 p +=4;
1811 len = srvstr_push(base_data, flags2, p,
1812 fname, PTR_DIFF(end_data, p),
1813 STR_TERMINATE_ASCII);
1814 SIVAL(q, 0, len);
1815 p += len;
1817 len = PTR_DIFF(p, pdata);
1818 pad = (len + (align-1)) & ~(align-1);
1820 * offset to the next entry, the caller
1821 * will overwrite it for the last entry
1822 * that's why we always include the padding
1824 SIVAL(pdata,0,pad);
1826 * set padding to zero
1828 if (do_pad) {
1829 memset(p, 0, pad - len);
1830 p = pdata + pad;
1831 } else {
1832 p = pdata + len;
1834 break;
1836 case SMB_FIND_FILE_NAMES_INFO:
1837 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1838 p += 4;
1839 SIVAL(p,0,reskey); p += 4;
1840 p += 4;
1841 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1842 acl on a dir (tridge) */
1843 len = srvstr_push(base_data, flags2, p,
1844 fname, PTR_DIFF(end_data, p),
1845 STR_TERMINATE_ASCII);
1846 SIVAL(p, -4, len);
1847 p += len;
1849 len = PTR_DIFF(p, pdata);
1850 pad = (len + (align-1)) & ~(align-1);
1852 * offset to the next entry, the caller
1853 * will overwrite it for the last entry
1854 * that's why we always include the padding
1856 SIVAL(pdata,0,pad);
1858 * set padding to zero
1860 if (do_pad) {
1861 memset(p, 0, pad - len);
1862 p = pdata + pad;
1863 } else {
1864 p = pdata + len;
1866 break;
1868 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1869 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1870 p += 4;
1871 SIVAL(p,0,reskey); p += 4;
1872 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1873 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1874 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1875 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1876 SOFF_T(p,0,file_size); p += 8;
1877 SOFF_T(p,0,allocation_size); p += 8;
1878 SIVAL(p,0,mode); p += 4;
1879 q = p; p += 4; /* q is placeholder for name length. */
1881 unsigned int ea_size = estimate_ea_size(conn, NULL,
1882 smb_fname->base_name);
1883 SIVAL(p,0,ea_size); /* Extended attributes */
1884 p +=4;
1886 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1887 SBVAL(p,0,file_index); p += 8;
1888 len = srvstr_push(base_data, flags2, p,
1889 fname, PTR_DIFF(end_data, p),
1890 STR_TERMINATE_ASCII);
1891 SIVAL(q, 0, len);
1892 p += len;
1894 len = PTR_DIFF(p, pdata);
1895 pad = (len + (align-1)) & ~(align-1);
1897 * offset to the next entry, the caller
1898 * will overwrite it for the last entry
1899 * that's why we always include the padding
1901 SIVAL(pdata,0,pad);
1903 * set padding to zero
1905 if (do_pad) {
1906 memset(p, 0, pad - len);
1907 p = pdata + pad;
1908 } else {
1909 p = pdata + len;
1911 break;
1913 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1914 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1915 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1916 p += 4;
1917 SIVAL(p,0,reskey); p += 4;
1918 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1919 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1920 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1921 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1922 SOFF_T(p,0,file_size); p += 8;
1923 SOFF_T(p,0,allocation_size); p += 8;
1924 SIVAL(p,0,mode); p += 4;
1925 q = p; p += 4; /* q is placeholder for name length */
1927 unsigned int ea_size = estimate_ea_size(conn, NULL,
1928 smb_fname->base_name);
1929 SIVAL(p,0,ea_size); /* Extended attributes */
1930 p +=4;
1932 /* Clear the short name buffer. This is
1933 * IMPORTANT as not doing so will trigger
1934 * a Win2k client bug. JRA.
1936 if (!was_8_3 && check_mangled_names) {
1937 char mangled_name[13]; /* mangled 8.3 name. */
1938 if (!name_to_8_3(fname,mangled_name,True,
1939 conn->params)) {
1940 /* Error - mangle failed ! */
1941 memset(mangled_name,'\0',12);
1943 mangled_name[12] = 0;
1944 len = srvstr_push(base_data, flags2,
1945 p+2, mangled_name, 24,
1946 STR_UPPER|STR_UNICODE);
1947 SSVAL(p, 0, len);
1948 if (len < 24) {
1949 memset(p + 2 + len,'\0',24 - len);
1951 SSVAL(p, 0, len);
1952 } else {
1953 memset(p,'\0',26);
1955 p += 26;
1956 SSVAL(p,0,0); p += 2; /* Reserved ? */
1957 SBVAL(p,0,file_index); p += 8;
1958 len = srvstr_push(base_data, flags2, p,
1959 fname, PTR_DIFF(end_data, p),
1960 STR_TERMINATE_ASCII);
1961 SIVAL(q,0,len);
1962 p += len;
1964 len = PTR_DIFF(p, pdata);
1965 pad = (len + (align-1)) & ~(align-1);
1967 * offset to the next entry, the caller
1968 * will overwrite it for the last entry
1969 * that's why we always include the padding
1971 SIVAL(pdata,0,pad);
1973 * set padding to zero
1975 if (do_pad) {
1976 memset(p, 0, pad - len);
1977 p = pdata + pad;
1978 } else {
1979 p = pdata + len;
1981 break;
1983 /* CIFS UNIX Extension. */
1985 case SMB_FIND_FILE_UNIX:
1986 case SMB_FIND_FILE_UNIX_INFO2:
1987 p+= 4;
1988 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1990 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1992 if (info_level == SMB_FIND_FILE_UNIX) {
1993 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1994 p = store_file_unix_basic(conn, p,
1995 NULL, &smb_fname->st);
1996 len = srvstr_push(base_data, flags2, p,
1997 fname, PTR_DIFF(end_data, p),
1998 STR_TERMINATE);
1999 } else {
2000 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2001 p = store_file_unix_basic_info2(conn, p,
2002 NULL, &smb_fname->st);
2003 nameptr = p;
2004 p += 4;
2005 len = srvstr_push(base_data, flags2, p, fname,
2006 PTR_DIFF(end_data, p), 0);
2007 SIVAL(nameptr, 0, len);
2010 p += len;
2012 len = PTR_DIFF(p, pdata);
2013 pad = (len + (align-1)) & ~(align-1);
2015 * offset to the next entry, the caller
2016 * will overwrite it for the last entry
2017 * that's why we always include the padding
2019 SIVAL(pdata,0,pad);
2021 * set padding to zero
2023 if (do_pad) {
2024 memset(p, 0, pad - len);
2025 p = pdata + pad;
2026 } else {
2027 p = pdata + len;
2029 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2031 break;
2033 default:
2034 return false;
2037 if (PTR_DIFF(p,pdata) > space_remaining) {
2038 *out_of_space = true;
2039 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2040 return false; /* Not finished - just out of space */
2043 /* Setup the last entry pointer, as an offset from base_data */
2044 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2045 /* Advance the data pointer to the next slot */
2046 *ppdata = p;
2048 return true;
2051 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2052 connection_struct *conn,
2053 struct dptr_struct *dirptr,
2054 uint16 flags2,
2055 const char *path_mask,
2056 uint32 dirtype,
2057 int info_level,
2058 int requires_resume_key,
2059 bool dont_descend,
2060 bool ask_sharemode,
2061 uint8_t align,
2062 bool do_pad,
2063 char **ppdata,
2064 char *base_data,
2065 char *end_data,
2066 int space_remaining,
2067 bool *out_of_space,
2068 bool *got_exact_match,
2069 int *_last_entry_off,
2070 struct ea_list *name_list)
2072 const char *p;
2073 const char *mask = NULL;
2074 long prev_dirpos = 0;
2075 uint32_t mode = 0;
2076 char *fname = NULL;
2077 struct smb_filename *smb_fname = NULL;
2078 struct smbd_dirptr_lanman2_state state;
2079 bool ok;
2080 uint64_t last_entry_off = 0;
2082 ZERO_STRUCT(state);
2083 state.conn = conn;
2084 state.info_level = info_level;
2085 state.check_mangled_names = lp_manglednames(conn->params);
2086 state.has_wild = dptr_has_wild(dirptr);
2087 state.got_exact_match = false;
2089 *out_of_space = false;
2090 *got_exact_match = false;
2092 p = strrchr_m(path_mask,'/');
2093 if(p != NULL) {
2094 if(p[1] == '\0') {
2095 mask = "*.*";
2096 } else {
2097 mask = p+1;
2099 } else {
2100 mask = path_mask;
2103 ok = smbd_dirptr_get_entry(ctx,
2104 dirptr,
2105 mask,
2106 dirtype,
2107 dont_descend,
2108 ask_sharemode,
2109 smbd_dirptr_lanman2_match_fn,
2110 smbd_dirptr_lanman2_mode_fn,
2111 &state,
2112 &fname,
2113 &smb_fname,
2114 &mode,
2115 &prev_dirpos);
2116 if (!ok) {
2117 return false;
2120 *got_exact_match = state.got_exact_match;
2122 ok = smbd_marshall_dir_entry(ctx,
2123 conn,
2124 flags2,
2125 info_level,
2126 name_list,
2127 state.check_mangled_names,
2128 requires_resume_key,
2129 mode,
2130 fname,
2131 smb_fname,
2132 space_remaining,
2133 align,
2134 do_pad,
2135 base_data,
2136 ppdata,
2137 end_data,
2138 out_of_space,
2139 &last_entry_off);
2140 TALLOC_FREE(fname);
2141 TALLOC_FREE(smb_fname);
2142 if (*out_of_space) {
2143 dptr_SeekDir(dirptr, prev_dirpos);
2144 return false;
2146 if (!ok) {
2147 return false;
2150 *_last_entry_off = last_entry_off;
2151 return true;
2154 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2155 connection_struct *conn,
2156 struct dptr_struct *dirptr,
2157 uint16 flags2,
2158 const char *path_mask,
2159 uint32 dirtype,
2160 int info_level,
2161 bool requires_resume_key,
2162 bool dont_descend,
2163 bool ask_sharemode,
2164 char **ppdata,
2165 char *base_data,
2166 char *end_data,
2167 int space_remaining,
2168 bool *out_of_space,
2169 bool *got_exact_match,
2170 int *last_entry_off,
2171 struct ea_list *name_list)
2173 uint8_t align = 4;
2174 const bool do_pad = true;
2176 if (info_level >= 1 && info_level <= 3) {
2177 /* No alignment on earlier info levels. */
2178 align = 1;
2181 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2182 path_mask, dirtype, info_level,
2183 requires_resume_key, dont_descend, ask_sharemode,
2184 align, do_pad,
2185 ppdata, base_data, end_data,
2186 space_remaining,
2187 out_of_space, got_exact_match,
2188 last_entry_off, name_list);
2191 /****************************************************************************
2192 Reply to a TRANS2_FINDFIRST.
2193 ****************************************************************************/
2195 static void call_trans2findfirst(connection_struct *conn,
2196 struct smb_request *req,
2197 char **pparams, int total_params,
2198 char **ppdata, int total_data,
2199 unsigned int max_data_bytes)
2201 /* We must be careful here that we don't return more than the
2202 allowed number of data bytes. If this means returning fewer than
2203 maxentries then so be it. We assume that the redirector has
2204 enough room for the fixed number of parameter bytes it has
2205 requested. */
2206 struct smb_filename *smb_dname = NULL;
2207 char *params = *pparams;
2208 char *pdata = *ppdata;
2209 char *data_end;
2210 uint32 dirtype;
2211 int maxentries;
2212 uint16 findfirst_flags;
2213 bool close_after_first;
2214 bool close_if_end;
2215 bool requires_resume_key;
2216 int info_level;
2217 char *directory = NULL;
2218 char *mask = NULL;
2219 char *p;
2220 int last_entry_off=0;
2221 int dptr_num = -1;
2222 int numentries = 0;
2223 int i;
2224 bool finished = False;
2225 bool dont_descend = False;
2226 bool out_of_space = False;
2227 int space_remaining;
2228 bool mask_contains_wcard = False;
2229 struct ea_list *ea_list = NULL;
2230 NTSTATUS ntstatus = NT_STATUS_OK;
2231 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2232 TALLOC_CTX *ctx = talloc_tos();
2233 struct dptr_struct *dirptr = NULL;
2234 struct smbd_server_connection *sconn = smbd_server_conn;
2236 if (total_params < 13) {
2237 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2238 goto out;
2241 dirtype = SVAL(params,0);
2242 maxentries = SVAL(params,2);
2243 findfirst_flags = SVAL(params,4);
2244 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2245 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2246 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2247 info_level = SVAL(params,6);
2249 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2250 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2251 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2252 info_level, max_data_bytes));
2254 if (!maxentries) {
2255 /* W2K3 seems to treat zero as 1. */
2256 maxentries = 1;
2259 switch (info_level) {
2260 case SMB_FIND_INFO_STANDARD:
2261 case SMB_FIND_EA_SIZE:
2262 case SMB_FIND_EA_LIST:
2263 case SMB_FIND_FILE_DIRECTORY_INFO:
2264 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2265 case SMB_FIND_FILE_NAMES_INFO:
2266 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2267 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2268 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2269 break;
2270 case SMB_FIND_FILE_UNIX:
2271 case SMB_FIND_FILE_UNIX_INFO2:
2272 /* Always use filesystem for UNIX mtime query. */
2273 ask_sharemode = false;
2274 if (!lp_unix_extensions()) {
2275 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2276 goto out;
2278 break;
2279 default:
2280 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2281 goto out;
2284 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2285 params+12, total_params - 12,
2286 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2287 if (!NT_STATUS_IS_OK(ntstatus)) {
2288 reply_nterror(req, ntstatus);
2289 goto out;
2292 ntstatus = filename_convert(ctx, conn,
2293 req->flags2 & FLAGS2_DFS_PATHNAMES,
2294 directory,
2295 (UCF_SAVE_LCOMP |
2296 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2297 &mask_contains_wcard,
2298 &smb_dname);
2299 if (!NT_STATUS_IS_OK(ntstatus)) {
2300 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2301 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2302 ERRSRV, ERRbadpath);
2303 goto out;
2305 reply_nterror(req, ntstatus);
2306 goto out;
2309 mask = smb_dname->original_lcomp;
2311 directory = smb_dname->base_name;
2313 p = strrchr_m(directory,'/');
2314 if(p == NULL) {
2315 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2316 if((directory[0] == '.') && (directory[1] == '\0')) {
2317 mask = talloc_strdup(ctx,"*");
2318 if (!mask) {
2319 reply_nterror(req, NT_STATUS_NO_MEMORY);
2320 goto out;
2322 mask_contains_wcard = True;
2324 directory = talloc_strdup(talloc_tos(), "./");
2325 if (!directory) {
2326 reply_nterror(req, NT_STATUS_NO_MEMORY);
2327 goto out;
2329 } else {
2330 *p = 0;
2333 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2335 if (info_level == SMB_FIND_EA_LIST) {
2336 uint32 ea_size;
2338 if (total_data < 4) {
2339 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2340 goto out;
2343 ea_size = IVAL(pdata,0);
2344 if (ea_size != total_data) {
2345 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2346 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2347 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2348 goto out;
2351 if (!lp_ea_support(SNUM(conn))) {
2352 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2353 goto out;
2356 /* Pull out the list of names. */
2357 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2358 if (!ea_list) {
2359 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2360 goto out;
2364 *ppdata = (char *)SMB_REALLOC(
2365 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2366 if(*ppdata == NULL ) {
2367 reply_nterror(req, NT_STATUS_NO_MEMORY);
2368 goto out;
2370 pdata = *ppdata;
2371 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2373 /* Realloc the params space */
2374 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2375 if (*pparams == NULL) {
2376 reply_nterror(req, NT_STATUS_NO_MEMORY);
2377 goto out;
2379 params = *pparams;
2381 /* Save the wildcard match and attribs we are using on this directory -
2382 needed as lanman2 assumes these are being saved between calls */
2384 ntstatus = dptr_create(conn,
2385 directory,
2386 False,
2387 True,
2388 req->smbpid,
2389 mask,
2390 mask_contains_wcard,
2391 dirtype,
2392 &dirptr);
2394 if (!NT_STATUS_IS_OK(ntstatus)) {
2395 reply_nterror(req, ntstatus);
2396 goto out;
2399 dptr_num = dptr_dnum(dirptr);
2400 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2402 /* Initialize per TRANS2_FIND_FIRST operation data */
2403 dptr_init_search_op(dirptr);
2405 /* We don't need to check for VOL here as this is returned by
2406 a different TRANS2 call. */
2408 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2409 directory,lp_dontdescend(SNUM(conn))));
2410 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2411 dont_descend = True;
2413 p = pdata;
2414 space_remaining = max_data_bytes;
2415 out_of_space = False;
2417 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2418 bool got_exact_match = False;
2420 /* this is a heuristic to avoid seeking the dirptr except when
2421 absolutely necessary. It allows for a filename of about 40 chars */
2422 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2423 out_of_space = True;
2424 finished = False;
2425 } else {
2426 finished = !get_lanman2_dir_entry(ctx,
2427 conn,
2428 dirptr,
2429 req->flags2,
2430 mask,dirtype,info_level,
2431 requires_resume_key,dont_descend,
2432 ask_sharemode,
2433 &p,pdata,data_end,
2434 space_remaining, &out_of_space,
2435 &got_exact_match,
2436 &last_entry_off, ea_list);
2439 if (finished && out_of_space)
2440 finished = False;
2442 if (!finished && !out_of_space)
2443 numentries++;
2446 * As an optimisation if we know we aren't looking
2447 * for a wildcard name (ie. the name matches the wildcard exactly)
2448 * then we can finish on any (first) match.
2449 * This speeds up large directory searches. JRA.
2452 if(got_exact_match)
2453 finished = True;
2455 /* Ensure space_remaining never goes -ve. */
2456 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2457 space_remaining = 0;
2458 out_of_space = true;
2459 } else {
2460 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2464 /* Check if we can close the dirptr */
2465 if(close_after_first || (finished && close_if_end)) {
2466 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2467 dptr_close(sconn, &dptr_num);
2471 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2472 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2473 * the protocol level is less than NT1. Tested with smbclient. JRA.
2474 * This should fix the OS/2 client bug #2335.
2477 if(numentries == 0) {
2478 dptr_close(sconn, &dptr_num);
2479 if (get_Protocol() < PROTOCOL_NT1) {
2480 reply_force_doserror(req, ERRDOS, ERRnofiles);
2481 goto out;
2482 } else {
2483 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2484 ERRDOS, ERRbadfile);
2485 goto out;
2489 /* At this point pdata points to numentries directory entries. */
2491 /* Set up the return parameter block */
2492 SSVAL(params,0,dptr_num);
2493 SSVAL(params,2,numentries);
2494 SSVAL(params,4,finished);
2495 SSVAL(params,6,0); /* Never an EA error */
2496 SSVAL(params,8,last_entry_off);
2498 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2499 max_data_bytes);
2501 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2502 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2503 if (!directory) {
2504 reply_nterror(req, NT_STATUS_NO_MEMORY);
2508 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2509 smb_fn_name(req->cmd),
2510 mask, directory, dirtype, numentries ) );
2513 * Force a name mangle here to ensure that the
2514 * mask as an 8.3 name is top of the mangled cache.
2515 * The reasons for this are subtle. Don't remove
2516 * this code unless you know what you are doing
2517 * (see PR#13758). JRA.
2520 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2521 char mangled_name[13];
2522 name_to_8_3(mask, mangled_name, True, conn->params);
2524 out:
2525 TALLOC_FREE(smb_dname);
2526 return;
2529 /****************************************************************************
2530 Reply to a TRANS2_FINDNEXT.
2531 ****************************************************************************/
2533 static void call_trans2findnext(connection_struct *conn,
2534 struct smb_request *req,
2535 char **pparams, int total_params,
2536 char **ppdata, int total_data,
2537 unsigned int max_data_bytes)
2539 /* We must be careful here that we don't return more than the
2540 allowed number of data bytes. If this means returning fewer than
2541 maxentries then so be it. We assume that the redirector has
2542 enough room for the fixed number of parameter bytes it has
2543 requested. */
2544 char *params = *pparams;
2545 char *pdata = *ppdata;
2546 char *data_end;
2547 int dptr_num;
2548 int maxentries;
2549 uint16 info_level;
2550 uint32 resume_key;
2551 uint16 findnext_flags;
2552 bool close_after_request;
2553 bool close_if_end;
2554 bool requires_resume_key;
2555 bool continue_bit;
2556 bool mask_contains_wcard = False;
2557 char *resume_name = NULL;
2558 const char *mask = NULL;
2559 const char *directory = NULL;
2560 char *p = NULL;
2561 uint16 dirtype;
2562 int numentries = 0;
2563 int i, last_entry_off=0;
2564 bool finished = False;
2565 bool dont_descend = False;
2566 bool out_of_space = False;
2567 int space_remaining;
2568 struct ea_list *ea_list = NULL;
2569 NTSTATUS ntstatus = NT_STATUS_OK;
2570 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2571 TALLOC_CTX *ctx = talloc_tos();
2572 struct dptr_struct *dirptr;
2573 struct smbd_server_connection *sconn = smbd_server_conn;
2575 if (total_params < 13) {
2576 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2577 return;
2580 dptr_num = SVAL(params,0);
2581 maxentries = SVAL(params,2);
2582 info_level = SVAL(params,4);
2583 resume_key = IVAL(params,6);
2584 findnext_flags = SVAL(params,10);
2585 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2586 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2587 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2588 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2590 if (!continue_bit) {
2591 /* We only need resume_name if continue_bit is zero. */
2592 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2593 params+12,
2594 total_params - 12, STR_TERMINATE, &ntstatus,
2595 &mask_contains_wcard);
2596 if (!NT_STATUS_IS_OK(ntstatus)) {
2597 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2598 complain (it thinks we're asking for the directory above the shared
2599 path or an invalid name). Catch this as the resume name is only compared, never used in
2600 a file access. JRA. */
2601 srvstr_pull_talloc(ctx, params, req->flags2,
2602 &resume_name, params+12,
2603 total_params - 12,
2604 STR_TERMINATE);
2606 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2607 reply_nterror(req, ntstatus);
2608 return;
2613 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2614 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2615 resume_key = %d resume name = %s continue=%d level = %d\n",
2616 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2617 requires_resume_key, resume_key,
2618 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2620 if (!maxentries) {
2621 /* W2K3 seems to treat zero as 1. */
2622 maxentries = 1;
2625 switch (info_level) {
2626 case SMB_FIND_INFO_STANDARD:
2627 case SMB_FIND_EA_SIZE:
2628 case SMB_FIND_EA_LIST:
2629 case SMB_FIND_FILE_DIRECTORY_INFO:
2630 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2631 case SMB_FIND_FILE_NAMES_INFO:
2632 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2633 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2634 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2635 break;
2636 case SMB_FIND_FILE_UNIX:
2637 case SMB_FIND_FILE_UNIX_INFO2:
2638 /* Always use filesystem for UNIX mtime query. */
2639 ask_sharemode = false;
2640 if (!lp_unix_extensions()) {
2641 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2642 return;
2644 break;
2645 default:
2646 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2647 return;
2650 if (info_level == SMB_FIND_EA_LIST) {
2651 uint32 ea_size;
2653 if (total_data < 4) {
2654 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2655 return;
2658 ea_size = IVAL(pdata,0);
2659 if (ea_size != total_data) {
2660 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2661 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2662 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2663 return;
2666 if (!lp_ea_support(SNUM(conn))) {
2667 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2668 return;
2671 /* Pull out the list of names. */
2672 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2673 if (!ea_list) {
2674 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2675 return;
2679 *ppdata = (char *)SMB_REALLOC(
2680 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2681 if(*ppdata == NULL) {
2682 reply_nterror(req, NT_STATUS_NO_MEMORY);
2683 return;
2686 pdata = *ppdata;
2687 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2689 /* Realloc the params space */
2690 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2691 if(*pparams == NULL ) {
2692 reply_nterror(req, NT_STATUS_NO_MEMORY);
2693 return;
2696 params = *pparams;
2698 /* Check that the dptr is valid */
2699 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2700 reply_nterror(req, STATUS_NO_MORE_FILES);
2701 return;
2704 directory = dptr_path(sconn, dptr_num);
2706 /* Get the wildcard mask from the dptr */
2707 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2708 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2709 reply_nterror(req, STATUS_NO_MORE_FILES);
2710 return;
2713 mask = p;
2715 /* Get the attr mask from the dptr */
2716 dirtype = dptr_attr(sconn, dptr_num);
2718 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2719 dptr_num, mask, dirtype,
2720 (long)dirptr,
2721 dptr_TellDir(dirptr)));
2723 /* Initialize per TRANS2_FIND_NEXT operation data */
2724 dptr_init_search_op(dirptr);
2726 /* We don't need to check for VOL here as this is returned by
2727 a different TRANS2 call. */
2729 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2730 directory,lp_dontdescend(SNUM(conn))));
2731 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2732 dont_descend = True;
2734 p = pdata;
2735 space_remaining = max_data_bytes;
2736 out_of_space = False;
2739 * Seek to the correct position. We no longer use the resume key but
2740 * depend on the last file name instead.
2743 if(!continue_bit && resume_name && *resume_name) {
2744 SMB_STRUCT_STAT st;
2746 long current_pos = 0;
2748 * Remember, name_to_8_3 is called by
2749 * get_lanman2_dir_entry(), so the resume name
2750 * could be mangled. Ensure we check the unmangled name.
2753 if (mangle_is_mangled(resume_name, conn->params)) {
2754 char *new_resume_name = NULL;
2755 mangle_lookup_name_from_8_3(ctx,
2756 resume_name,
2757 &new_resume_name,
2758 conn->params);
2759 if (new_resume_name) {
2760 resume_name = new_resume_name;
2765 * Fix for NT redirector problem triggered by resume key indexes
2766 * changing between directory scans. We now return a resume key of 0
2767 * and instead look for the filename to continue from (also given
2768 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2769 * findfirst/findnext (as is usual) then the directory pointer
2770 * should already be at the correct place.
2773 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2774 } /* end if resume_name && !continue_bit */
2776 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2777 bool got_exact_match = False;
2779 /* this is a heuristic to avoid seeking the dirptr except when
2780 absolutely necessary. It allows for a filename of about 40 chars */
2781 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2782 out_of_space = True;
2783 finished = False;
2784 } else {
2785 finished = !get_lanman2_dir_entry(ctx,
2786 conn,
2787 dirptr,
2788 req->flags2,
2789 mask,dirtype,info_level,
2790 requires_resume_key,dont_descend,
2791 ask_sharemode,
2792 &p,pdata,data_end,
2793 space_remaining, &out_of_space,
2794 &got_exact_match,
2795 &last_entry_off, ea_list);
2798 if (finished && out_of_space)
2799 finished = False;
2801 if (!finished && !out_of_space)
2802 numentries++;
2805 * As an optimisation if we know we aren't looking
2806 * for a wildcard name (ie. the name matches the wildcard exactly)
2807 * then we can finish on any (first) match.
2808 * This speeds up large directory searches. JRA.
2811 if(got_exact_match)
2812 finished = True;
2814 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2817 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2818 smb_fn_name(req->cmd),
2819 mask, directory, dirtype, numentries ) );
2821 /* Check if we can close the dirptr */
2822 if(close_after_request || (finished && close_if_end)) {
2823 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2824 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2827 /* Set up the return parameter block */
2828 SSVAL(params,0,numentries);
2829 SSVAL(params,2,finished);
2830 SSVAL(params,4,0); /* Never an EA error */
2831 SSVAL(params,6,last_entry_off);
2833 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2834 max_data_bytes);
2836 return;
2839 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2841 E_md4hash(lp_servicename(SNUM(conn)),objid);
2842 return objid;
2845 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2847 SMB_ASSERT(extended_info != NULL);
2849 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2850 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2851 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2852 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2853 #ifdef SAMBA_VERSION_REVISION
2854 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2855 #endif
2856 extended_info->samba_subversion = 0;
2857 #ifdef SAMBA_VERSION_RC_RELEASE
2858 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2859 #else
2860 #ifdef SAMBA_VERSION_PRE_RELEASE
2861 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2862 #endif
2863 #endif
2864 #ifdef SAMBA_VERSION_VENDOR_PATCH
2865 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2866 #endif
2867 extended_info->samba_gitcommitdate = 0;
2868 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2869 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2870 #endif
2872 memset(extended_info->samba_version_string, 0,
2873 sizeof(extended_info->samba_version_string));
2875 snprintf (extended_info->samba_version_string,
2876 sizeof(extended_info->samba_version_string),
2877 "%s", samba_version_string());
2880 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2881 TALLOC_CTX *mem_ctx,
2882 uint16_t info_level,
2883 uint16_t flags2,
2884 unsigned int max_data_bytes,
2885 char **ppdata,
2886 int *ret_data_len)
2888 char *pdata, *end_data;
2889 int data_len = 0, len;
2890 const char *vname = volume_label(SNUM(conn));
2891 int snum = SNUM(conn);
2892 char *fstype = lp_fstype(SNUM(conn));
2893 uint32 additional_flags = 0;
2894 struct smb_filename smb_fname_dot;
2895 SMB_STRUCT_STAT st;
2897 if (IS_IPC(conn)) {
2898 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2899 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2900 "info level (0x%x) on IPC$.\n",
2901 (unsigned int)info_level));
2902 return NT_STATUS_ACCESS_DENIED;
2906 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2908 ZERO_STRUCT(smb_fname_dot);
2909 smb_fname_dot.base_name = discard_const_p(char, ".");
2911 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2912 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2913 return map_nt_error_from_unix(errno);
2916 st = smb_fname_dot.st;
2918 *ppdata = (char *)SMB_REALLOC(
2919 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2920 if (*ppdata == NULL) {
2921 return NT_STATUS_NO_MEMORY;
2924 pdata = *ppdata;
2925 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2926 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2928 switch (info_level) {
2929 case SMB_INFO_ALLOCATION:
2931 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2932 data_len = 18;
2933 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2934 return map_nt_error_from_unix(errno);
2937 block_size = lp_block_size(snum);
2938 if (bsize < block_size) {
2939 uint64_t factor = block_size/bsize;
2940 bsize = block_size;
2941 dsize /= factor;
2942 dfree /= factor;
2944 if (bsize > block_size) {
2945 uint64_t factor = bsize/block_size;
2946 bsize = block_size;
2947 dsize *= factor;
2948 dfree *= factor;
2950 bytes_per_sector = 512;
2951 sectors_per_unit = bsize/bytes_per_sector;
2953 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2954 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2955 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2957 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2958 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2959 SIVAL(pdata,l1_cUnit,dsize);
2960 SIVAL(pdata,l1_cUnitAvail,dfree);
2961 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2962 break;
2965 case SMB_INFO_VOLUME:
2966 /* Return volume name */
2968 * Add volume serial number - hash of a combination of
2969 * the called hostname and the service name.
2971 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2973 * Win2k3 and previous mess this up by sending a name length
2974 * one byte short. I believe only older clients (OS/2 Win9x) use
2975 * this call so try fixing this by adding a terminating null to
2976 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2978 len = srvstr_push(
2979 pdata, flags2,
2980 pdata+l2_vol_szVolLabel, vname,
2981 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2982 STR_NOALIGN|STR_TERMINATE);
2983 SCVAL(pdata,l2_vol_cch,len);
2984 data_len = l2_vol_szVolLabel + len;
2985 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2986 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2987 len, vname));
2988 break;
2990 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2991 case SMB_FS_ATTRIBUTE_INFORMATION:
2993 additional_flags = 0;
2994 #if defined(HAVE_SYS_QUOTAS)
2995 additional_flags |= FILE_VOLUME_QUOTAS;
2996 #endif
2998 if(lp_nt_acl_support(SNUM(conn))) {
2999 additional_flags |= FILE_PERSISTENT_ACLS;
3002 /* Capabilities are filled in at connection time through STATVFS call */
3003 additional_flags |= conn->fs_capabilities;
3004 additional_flags |= lp_parm_int(conn->params->service,
3005 "share", "fake_fscaps",
3008 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3009 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3010 additional_flags); /* FS ATTRIBUTES */
3012 SIVAL(pdata,4,255); /* Max filename component length */
3013 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3014 and will think we can't do long filenames */
3015 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3016 PTR_DIFF(end_data, pdata+12),
3017 STR_UNICODE);
3018 SIVAL(pdata,8,len);
3019 data_len = 12 + len;
3020 break;
3022 case SMB_QUERY_FS_LABEL_INFO:
3023 case SMB_FS_LABEL_INFORMATION:
3024 len = srvstr_push(pdata, flags2, pdata+4, vname,
3025 PTR_DIFF(end_data, pdata+4), 0);
3026 data_len = 4 + len;
3027 SIVAL(pdata,0,len);
3028 break;
3030 case SMB_QUERY_FS_VOLUME_INFO:
3031 case SMB_FS_VOLUME_INFORMATION:
3034 * Add volume serial number - hash of a combination of
3035 * the called hostname and the service name.
3037 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3038 (str_checksum(get_local_machine_name())<<16));
3040 /* Max label len is 32 characters. */
3041 len = srvstr_push(pdata, flags2, pdata+18, vname,
3042 PTR_DIFF(end_data, pdata+18),
3043 STR_UNICODE);
3044 SIVAL(pdata,12,len);
3045 data_len = 18+len;
3047 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3048 (int)strlen(vname),vname, lp_servicename(snum)));
3049 break;
3051 case SMB_QUERY_FS_SIZE_INFO:
3052 case SMB_FS_SIZE_INFORMATION:
3054 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3055 data_len = 24;
3056 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3057 return map_nt_error_from_unix(errno);
3059 block_size = lp_block_size(snum);
3060 if (bsize < block_size) {
3061 uint64_t factor = block_size/bsize;
3062 bsize = block_size;
3063 dsize /= factor;
3064 dfree /= factor;
3066 if (bsize > block_size) {
3067 uint64_t factor = bsize/block_size;
3068 bsize = block_size;
3069 dsize *= factor;
3070 dfree *= factor;
3072 bytes_per_sector = 512;
3073 sectors_per_unit = bsize/bytes_per_sector;
3074 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3075 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3076 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3077 SBIG_UINT(pdata,0,dsize);
3078 SBIG_UINT(pdata,8,dfree);
3079 SIVAL(pdata,16,sectors_per_unit);
3080 SIVAL(pdata,20,bytes_per_sector);
3081 break;
3084 case SMB_FS_FULL_SIZE_INFORMATION:
3086 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3087 data_len = 32;
3088 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3089 return map_nt_error_from_unix(errno);
3091 block_size = lp_block_size(snum);
3092 if (bsize < block_size) {
3093 uint64_t factor = block_size/bsize;
3094 bsize = block_size;
3095 dsize /= factor;
3096 dfree /= factor;
3098 if (bsize > block_size) {
3099 uint64_t factor = bsize/block_size;
3100 bsize = block_size;
3101 dsize *= factor;
3102 dfree *= factor;
3104 bytes_per_sector = 512;
3105 sectors_per_unit = bsize/bytes_per_sector;
3106 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3107 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3108 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3109 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3110 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3111 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3112 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3113 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3114 break;
3117 case SMB_QUERY_FS_DEVICE_INFO:
3118 case SMB_FS_DEVICE_INFORMATION:
3119 data_len = 8;
3120 SIVAL(pdata,0,0); /* dev type */
3121 SIVAL(pdata,4,0); /* characteristics */
3122 break;
3124 #ifdef HAVE_SYS_QUOTAS
3125 case SMB_FS_QUOTA_INFORMATION:
3127 * what we have to send --metze:
3129 * Unknown1: 24 NULL bytes
3130 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3131 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3132 * Quota Flags: 2 byte :
3133 * Unknown3: 6 NULL bytes
3135 * 48 bytes total
3137 * details for Quota Flags:
3139 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3140 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3141 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3142 * 0x0001 Enable Quotas: enable quota for this fs
3146 /* we need to fake up a fsp here,
3147 * because its not send in this call
3149 files_struct fsp;
3150 SMB_NTQUOTA_STRUCT quotas;
3152 ZERO_STRUCT(fsp);
3153 ZERO_STRUCT(quotas);
3155 fsp.conn = conn;
3156 fsp.fnum = -1;
3158 /* access check */
3159 if (conn->server_info->utok.uid != sec_initial_uid() &&
3160 !conn->admin_user) {
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()) && !conn->admin_user)
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 /* First take care of O_CREAT|O_EXCL interactions. */
7049 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7050 case (SMB_O_CREAT | SMB_O_EXCL):
7051 /* File exists fail. File not exist create. */
7052 create_disp = FILE_CREATE;
7053 break;
7054 case SMB_O_CREAT:
7055 /* File exists open. File not exist create. */
7056 create_disp = FILE_OPEN_IF;
7057 break;
7058 case 0:
7059 /* File exists open. File not exist fail. */
7060 create_disp = FILE_OPEN;
7061 break;
7062 case SMB_O_EXCL:
7063 /* O_EXCL on its own without O_CREAT is undefined. */
7064 default:
7065 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7066 (unsigned int)wire_open_mode ));
7067 return NT_STATUS_INVALID_PARAMETER;
7070 /* Next factor in the effects of O_TRUNC. */
7071 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7073 if (wire_open_mode & SMB_O_TRUNC) {
7074 switch (create_disp) {
7075 case FILE_CREATE:
7076 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7077 /* Leave create_disp alone as
7078 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7080 /* File exists fail. File not exist create. */
7081 break;
7082 case FILE_OPEN_IF:
7083 /* SMB_O_CREAT | SMB_O_TRUNC */
7084 /* File exists overwrite. File not exist create. */
7085 create_disp = FILE_OVERWRITE_IF;
7086 break;
7087 case FILE_OPEN:
7088 /* SMB_O_TRUNC */
7089 /* File exists overwrite. File not exist fail. */
7090 create_disp = FILE_OVERWRITE;
7091 break;
7092 default:
7093 /* Cannot get here. */
7094 smb_panic("smb_posix_open: logic error");
7095 return NT_STATUS_INVALID_PARAMETER;
7099 raw_unixmode = IVAL(pdata,8);
7100 /* Next 4 bytes are not yet defined. */
7102 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7103 (VALID_STAT(smb_fname->st) ?
7104 PERM_EXISTING_FILE : PERM_NEW_FILE),
7105 &unixmode);
7107 if (!NT_STATUS_IS_OK(status)) {
7108 return status;
7111 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7113 if (wire_open_mode & SMB_O_SYNC) {
7114 create_options |= FILE_WRITE_THROUGH;
7116 if (wire_open_mode & SMB_O_APPEND) {
7117 access_mask |= FILE_APPEND_DATA;
7119 if (wire_open_mode & SMB_O_DIRECT) {
7120 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7123 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7124 smb_fname_str_dbg(smb_fname),
7125 (unsigned int)wire_open_mode,
7126 (unsigned int)unixmode ));
7128 status = SMB_VFS_CREATE_FILE(
7129 conn, /* conn */
7130 req, /* req */
7131 0, /* root_dir_fid */
7132 smb_fname, /* fname */
7133 access_mask, /* access_mask */
7134 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7135 FILE_SHARE_DELETE),
7136 create_disp, /* create_disposition*/
7137 FILE_NON_DIRECTORY_FILE, /* create_options */
7138 mod_unixmode, /* file_attributes */
7139 oplock_request, /* oplock_request */
7140 0, /* allocation_size */
7141 NULL, /* sd */
7142 NULL, /* ea_list */
7143 &fsp, /* result */
7144 &info); /* pinfo */
7146 if (!NT_STATUS_IS_OK(status)) {
7147 return status;
7150 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7151 extended_oplock_granted = True;
7154 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7155 extended_oplock_granted = True;
7158 info_level_return = SVAL(pdata,16);
7160 /* Allocate the correct return size. */
7162 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7163 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7164 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7165 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7166 } else {
7167 *pdata_return_size = 12;
7170 /* Realloc the data size */
7171 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7172 if (*ppdata == NULL) {
7173 close_file(req, fsp, ERROR_CLOSE);
7174 *pdata_return_size = 0;
7175 return NT_STATUS_NO_MEMORY;
7177 pdata = *ppdata;
7179 if (extended_oplock_granted) {
7180 if (flags & REQUEST_BATCH_OPLOCK) {
7181 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7182 } else {
7183 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7185 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7186 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7187 } else {
7188 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7191 SSVAL(pdata,2,fsp->fnum);
7192 SIVAL(pdata,4,info); /* Was file created etc. */
7194 switch (info_level_return) {
7195 case SMB_QUERY_FILE_UNIX_BASIC:
7196 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7197 SSVAL(pdata,10,0); /* padding. */
7198 store_file_unix_basic(conn, pdata + 12, fsp,
7199 &smb_fname->st);
7200 break;
7201 case SMB_QUERY_FILE_UNIX_INFO2:
7202 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7203 SSVAL(pdata,10,0); /* padding. */
7204 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7205 &smb_fname->st);
7206 break;
7207 default:
7208 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7209 SSVAL(pdata,10,0); /* padding. */
7210 break;
7212 return NT_STATUS_OK;
7215 /****************************************************************************
7216 Delete a file with POSIX semantics.
7217 ****************************************************************************/
7219 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7220 struct smb_request *req,
7221 const char *pdata,
7222 int total_data,
7223 struct smb_filename *smb_fname)
7225 NTSTATUS status = NT_STATUS_OK;
7226 files_struct *fsp = NULL;
7227 uint16 flags = 0;
7228 char del = 1;
7229 int info = 0;
7230 int create_options = 0;
7231 int i;
7232 struct share_mode_lock *lck = NULL;
7234 if (total_data < 2) {
7235 return NT_STATUS_INVALID_PARAMETER;
7238 flags = SVAL(pdata,0);
7240 if (!VALID_STAT(smb_fname->st)) {
7241 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7244 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7245 !VALID_STAT_OF_DIR(smb_fname->st)) {
7246 return NT_STATUS_NOT_A_DIRECTORY;
7249 DEBUG(10,("smb_posix_unlink: %s %s\n",
7250 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7251 smb_fname_str_dbg(smb_fname)));
7253 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7254 create_options |= FILE_DIRECTORY_FILE;
7257 status = SMB_VFS_CREATE_FILE(
7258 conn, /* conn */
7259 req, /* req */
7260 0, /* root_dir_fid */
7261 smb_fname, /* fname */
7262 DELETE_ACCESS, /* access_mask */
7263 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7264 FILE_SHARE_DELETE),
7265 FILE_OPEN, /* create_disposition*/
7266 create_options, /* create_options */
7267 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7268 0, /* oplock_request */
7269 0, /* allocation_size */
7270 NULL, /* sd */
7271 NULL, /* ea_list */
7272 &fsp, /* result */
7273 &info); /* pinfo */
7275 if (!NT_STATUS_IS_OK(status)) {
7276 return status;
7280 * Don't lie to client. If we can't really delete due to
7281 * non-POSIX opens return SHARING_VIOLATION.
7284 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7285 NULL);
7286 if (lck == NULL) {
7287 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7288 "lock for file %s\n", fsp_str_dbg(fsp)));
7289 close_file(req, fsp, NORMAL_CLOSE);
7290 return NT_STATUS_INVALID_PARAMETER;
7294 * See if others still have the file open. If this is the case, then
7295 * don't delete. If all opens are POSIX delete we can set the delete
7296 * on close disposition.
7298 for (i=0; i<lck->num_share_modes; i++) {
7299 struct share_mode_entry *e = &lck->share_modes[i];
7300 if (is_valid_share_mode_entry(e)) {
7301 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7302 continue;
7304 /* Fail with sharing violation. */
7305 close_file(req, fsp, NORMAL_CLOSE);
7306 TALLOC_FREE(lck);
7307 return NT_STATUS_SHARING_VIOLATION;
7312 * Set the delete on close.
7314 status = smb_set_file_disposition_info(conn,
7315 &del,
7317 fsp,
7318 smb_fname);
7320 if (!NT_STATUS_IS_OK(status)) {
7321 close_file(req, fsp, NORMAL_CLOSE);
7322 TALLOC_FREE(lck);
7323 return status;
7325 TALLOC_FREE(lck);
7326 return close_file(req, fsp, NORMAL_CLOSE);
7329 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7330 struct smb_request *req,
7331 TALLOC_CTX *mem_ctx,
7332 uint16_t info_level,
7333 files_struct *fsp,
7334 struct smb_filename *smb_fname,
7335 char **ppdata, int total_data,
7336 int *ret_data_size)
7338 char *pdata = *ppdata;
7339 NTSTATUS status = NT_STATUS_OK;
7340 int data_return_size = 0;
7342 *ret_data_size = 0;
7344 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7345 return NT_STATUS_INVALID_LEVEL;
7348 if (!CAN_WRITE(conn)) {
7349 /* Allow POSIX opens. The open path will deny
7350 * any non-readonly opens. */
7351 if (info_level != SMB_POSIX_PATH_OPEN) {
7352 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7356 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7357 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7358 fsp ? fsp->fnum : -1, info_level, total_data));
7360 switch (info_level) {
7362 case SMB_INFO_STANDARD:
7364 status = smb_set_info_standard(conn,
7365 pdata,
7366 total_data,
7367 fsp,
7368 smb_fname);
7369 break;
7372 case SMB_INFO_SET_EA:
7374 status = smb_info_set_ea(conn,
7375 pdata,
7376 total_data,
7377 fsp,
7378 smb_fname);
7379 break;
7382 case SMB_SET_FILE_BASIC_INFO:
7383 case SMB_FILE_BASIC_INFORMATION:
7385 status = smb_set_file_basic_info(conn,
7386 pdata,
7387 total_data,
7388 fsp,
7389 smb_fname);
7390 break;
7393 case SMB_FILE_ALLOCATION_INFORMATION:
7394 case SMB_SET_FILE_ALLOCATION_INFO:
7396 status = smb_set_file_allocation_info(conn, req,
7397 pdata,
7398 total_data,
7399 fsp,
7400 smb_fname);
7401 break;
7404 case SMB_FILE_END_OF_FILE_INFORMATION:
7405 case SMB_SET_FILE_END_OF_FILE_INFO:
7408 * XP/Win7 both fail after the createfile with
7409 * SMB_SET_FILE_END_OF_FILE_INFO but not
7410 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7411 * The level is known here, so pass it down
7412 * appropriately.
7414 bool should_fail =
7415 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7417 status = smb_set_file_end_of_file_info(conn, req,
7418 pdata,
7419 total_data,
7420 fsp,
7421 smb_fname,
7422 should_fail);
7423 break;
7426 case SMB_FILE_DISPOSITION_INFORMATION:
7427 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7429 #if 0
7430 /* JRA - We used to just ignore this on a path ?
7431 * Shouldn't this be invalid level on a pathname
7432 * based call ?
7434 if (tran_call != TRANSACT2_SETFILEINFO) {
7435 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7437 #endif
7438 status = smb_set_file_disposition_info(conn,
7439 pdata,
7440 total_data,
7441 fsp,
7442 smb_fname);
7443 break;
7446 case SMB_FILE_POSITION_INFORMATION:
7448 status = smb_file_position_information(conn,
7449 pdata,
7450 total_data,
7451 fsp);
7452 break;
7455 case SMB_FILE_FULL_EA_INFORMATION:
7457 status = smb_set_file_full_ea_info(conn,
7458 pdata,
7459 total_data,
7460 fsp);
7461 break;
7464 /* From tridge Samba4 :
7465 * MODE_INFORMATION in setfileinfo (I have no
7466 * idea what "mode information" on a file is - it takes a value of 0,
7467 * 2, 4 or 6. What could it be?).
7470 case SMB_FILE_MODE_INFORMATION:
7472 status = smb_file_mode_information(conn,
7473 pdata,
7474 total_data);
7475 break;
7479 * CIFS UNIX extensions.
7482 case SMB_SET_FILE_UNIX_BASIC:
7484 status = smb_set_file_unix_basic(conn, req,
7485 pdata,
7486 total_data,
7487 fsp,
7488 smb_fname);
7489 break;
7492 case SMB_SET_FILE_UNIX_INFO2:
7494 status = smb_set_file_unix_info2(conn, req,
7495 pdata,
7496 total_data,
7497 fsp,
7498 smb_fname);
7499 break;
7502 case SMB_SET_FILE_UNIX_LINK:
7504 if (fsp) {
7505 /* We must have a pathname for this. */
7506 return NT_STATUS_INVALID_LEVEL;
7508 status = smb_set_file_unix_link(conn, req, pdata,
7509 total_data, smb_fname);
7510 break;
7513 case SMB_SET_FILE_UNIX_HLINK:
7515 if (fsp) {
7516 /* We must have a pathname for this. */
7517 return NT_STATUS_INVALID_LEVEL;
7519 status = smb_set_file_unix_hlink(conn, req,
7520 pdata, total_data,
7521 smb_fname);
7522 break;
7525 case SMB_FILE_RENAME_INFORMATION:
7527 status = smb_file_rename_information(conn, req,
7528 pdata, total_data,
7529 fsp, smb_fname);
7530 break;
7533 #if defined(HAVE_POSIX_ACLS)
7534 case SMB_SET_POSIX_ACL:
7536 status = smb_set_posix_acl(conn,
7537 pdata,
7538 total_data,
7539 fsp,
7540 smb_fname);
7541 break;
7543 #endif
7545 case SMB_SET_POSIX_LOCK:
7547 if (!fsp) {
7548 return NT_STATUS_INVALID_LEVEL;
7550 status = smb_set_posix_lock(conn, req,
7551 pdata, total_data, fsp);
7552 break;
7555 case SMB_POSIX_PATH_OPEN:
7557 if (fsp) {
7558 /* We must have a pathname for this. */
7559 return NT_STATUS_INVALID_LEVEL;
7562 status = smb_posix_open(conn, req,
7563 ppdata,
7564 total_data,
7565 smb_fname,
7566 &data_return_size);
7567 break;
7570 case SMB_POSIX_PATH_UNLINK:
7572 if (fsp) {
7573 /* We must have a pathname for this. */
7574 return NT_STATUS_INVALID_LEVEL;
7577 status = smb_posix_unlink(conn, req,
7578 pdata,
7579 total_data,
7580 smb_fname);
7581 break;
7584 default:
7585 return NT_STATUS_INVALID_LEVEL;
7588 if (!NT_STATUS_IS_OK(status)) {
7589 return status;
7592 *ret_data_size = data_return_size;
7593 return NT_STATUS_OK;
7596 /****************************************************************************
7597 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7598 ****************************************************************************/
7600 static void call_trans2setfilepathinfo(connection_struct *conn,
7601 struct smb_request *req,
7602 unsigned int tran_call,
7603 char **pparams, int total_params,
7604 char **ppdata, int total_data,
7605 unsigned int max_data_bytes)
7607 char *params = *pparams;
7608 char *pdata = *ppdata;
7609 uint16 info_level;
7610 struct smb_filename *smb_fname = NULL;
7611 files_struct *fsp = NULL;
7612 NTSTATUS status = NT_STATUS_OK;
7613 int data_return_size = 0;
7615 if (!params) {
7616 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7617 return;
7620 if (tran_call == TRANSACT2_SETFILEINFO) {
7621 if (total_params < 4) {
7622 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7623 return;
7626 fsp = file_fsp(req, SVAL(params,0));
7627 /* Basic check for non-null fsp. */
7628 if (!check_fsp_open(conn, req, fsp)) {
7629 return;
7631 info_level = SVAL(params,2);
7633 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7634 &smb_fname);
7635 if (!NT_STATUS_IS_OK(status)) {
7636 reply_nterror(req, status);
7637 return;
7640 if(fsp->is_directory || fsp->fh->fd == -1) {
7642 * This is actually a SETFILEINFO on a directory
7643 * handle (returned from an NT SMB). NT5.0 seems
7644 * to do this call. JRA.
7646 if (INFO_LEVEL_IS_UNIX(info_level)) {
7647 /* Always do lstat for UNIX calls. */
7648 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7649 DEBUG(3,("call_trans2setfilepathinfo: "
7650 "SMB_VFS_LSTAT of %s failed "
7651 "(%s)\n",
7652 smb_fname_str_dbg(smb_fname),
7653 strerror(errno)));
7654 reply_nterror(req, map_nt_error_from_unix(errno));
7655 return;
7657 } else {
7658 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7659 DEBUG(3,("call_trans2setfilepathinfo: "
7660 "fileinfo of %s failed (%s)\n",
7661 smb_fname_str_dbg(smb_fname),
7662 strerror(errno)));
7663 reply_nterror(req, map_nt_error_from_unix(errno));
7664 return;
7667 } else if (fsp->print_file) {
7669 * Doing a DELETE_ON_CLOSE should cancel a print job.
7671 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7672 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7674 DEBUG(3,("call_trans2setfilepathinfo: "
7675 "Cancelling print job (%s)\n",
7676 fsp_str_dbg(fsp)));
7678 SSVAL(params,0,0);
7679 send_trans2_replies(conn, req, params, 2,
7680 *ppdata, 0,
7681 max_data_bytes);
7682 return;
7683 } else {
7684 reply_nterror(req,
7685 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7686 return;
7688 } else {
7690 * Original code - this is an open file.
7692 if (!check_fsp(conn, req, fsp)) {
7693 return;
7696 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7697 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7698 "of fnum %d failed (%s)\n", fsp->fnum,
7699 strerror(errno)));
7700 reply_nterror(req, map_nt_error_from_unix(errno));
7701 return;
7704 } else {
7705 char *fname = NULL;
7707 /* set path info */
7708 if (total_params < 7) {
7709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7710 return;
7713 info_level = SVAL(params,0);
7714 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7715 total_params - 6, STR_TERMINATE,
7716 &status);
7717 if (!NT_STATUS_IS_OK(status)) {
7718 reply_nterror(req, status);
7719 return;
7722 status = filename_convert(req, conn,
7723 req->flags2 & FLAGS2_DFS_PATHNAMES,
7724 fname,
7726 NULL,
7727 &smb_fname);
7728 if (!NT_STATUS_IS_OK(status)) {
7729 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7730 reply_botherror(req,
7731 NT_STATUS_PATH_NOT_COVERED,
7732 ERRSRV, ERRbadpath);
7733 return;
7735 reply_nterror(req, status);
7736 return;
7739 if (INFO_LEVEL_IS_UNIX(info_level)) {
7741 * For CIFS UNIX extensions the target name may not exist.
7744 /* Always do lstat for UNIX calls. */
7745 SMB_VFS_LSTAT(conn, smb_fname);
7747 } else if (!VALID_STAT(smb_fname->st) &&
7748 SMB_VFS_STAT(conn, smb_fname)) {
7749 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7750 "%s failed (%s)\n",
7751 smb_fname_str_dbg(smb_fname),
7752 strerror(errno)));
7753 reply_nterror(req, map_nt_error_from_unix(errno));
7754 return;
7758 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7759 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7760 fsp ? fsp->fnum : -1, info_level,total_data));
7762 /* Realloc the parameter size */
7763 *pparams = (char *)SMB_REALLOC(*pparams,2);
7764 if (*pparams == NULL) {
7765 reply_nterror(req, NT_STATUS_NO_MEMORY);
7766 return;
7768 params = *pparams;
7770 SSVAL(params,0,0);
7772 status = smbd_do_setfilepathinfo(conn, req, req,
7773 info_level,
7774 fsp,
7775 smb_fname,
7776 ppdata, total_data,
7777 &data_return_size);
7778 if (!NT_STATUS_IS_OK(status)) {
7779 if (open_was_deferred(req->mid)) {
7780 /* We have re-scheduled this call. */
7781 return;
7783 if (blocking_lock_was_deferred(req->mid)) {
7784 /* We have re-scheduled this call. */
7785 return;
7787 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7788 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7789 ERRSRV, ERRbadpath);
7790 return;
7792 if (info_level == SMB_POSIX_PATH_OPEN) {
7793 reply_openerror(req, status);
7794 return;
7797 reply_nterror(req, status);
7798 return;
7801 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7802 max_data_bytes);
7804 return;
7807 /****************************************************************************
7808 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7809 ****************************************************************************/
7811 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7812 char **pparams, int total_params,
7813 char **ppdata, int total_data,
7814 unsigned int max_data_bytes)
7816 struct smb_filename *smb_dname = NULL;
7817 char *params = *pparams;
7818 char *pdata = *ppdata;
7819 char *directory = NULL;
7820 NTSTATUS status = NT_STATUS_OK;
7821 struct ea_list *ea_list = NULL;
7822 TALLOC_CTX *ctx = talloc_tos();
7824 if (!CAN_WRITE(conn)) {
7825 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7826 return;
7829 if (total_params < 5) {
7830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7831 return;
7834 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7835 total_params - 4, STR_TERMINATE,
7836 &status);
7837 if (!NT_STATUS_IS_OK(status)) {
7838 reply_nterror(req, status);
7839 return;
7842 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7844 status = filename_convert(ctx,
7845 conn,
7846 req->flags2 & FLAGS2_DFS_PATHNAMES,
7847 directory,
7849 NULL,
7850 &smb_dname);
7852 if (!NT_STATUS_IS_OK(status)) {
7853 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7854 reply_botherror(req,
7855 NT_STATUS_PATH_NOT_COVERED,
7856 ERRSRV, ERRbadpath);
7857 return;
7859 reply_nterror(req, status);
7860 return;
7864 * OS/2 workplace shell seems to send SET_EA requests of "null"
7865 * length (4 bytes containing IVAL 4).
7866 * They seem to have no effect. Bug #3212. JRA.
7869 if (total_data && (total_data != 4)) {
7870 /* Any data in this call is an EA list. */
7871 if (total_data < 10) {
7872 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7873 goto out;
7876 if (IVAL(pdata,0) > total_data) {
7877 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7878 IVAL(pdata,0), (unsigned int)total_data));
7879 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7880 goto out;
7883 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7884 total_data - 4);
7885 if (!ea_list) {
7886 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7887 goto out;
7890 if (!lp_ea_support(SNUM(conn))) {
7891 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7892 goto out;
7895 /* If total_data == 4 Windows doesn't care what values
7896 * are placed in that field, it just ignores them.
7897 * The System i QNTC IBM SMB client puts bad values here,
7898 * so ignore them. */
7900 status = create_directory(conn, req, smb_dname);
7902 if (!NT_STATUS_IS_OK(status)) {
7903 reply_nterror(req, status);
7904 goto out;
7907 /* Try and set any given EA. */
7908 if (ea_list) {
7909 status = set_ea(conn, NULL, smb_dname, ea_list);
7910 if (!NT_STATUS_IS_OK(status)) {
7911 reply_nterror(req, status);
7912 goto out;
7916 /* Realloc the parameter and data sizes */
7917 *pparams = (char *)SMB_REALLOC(*pparams,2);
7918 if(*pparams == NULL) {
7919 reply_nterror(req, NT_STATUS_NO_MEMORY);
7920 goto out;
7922 params = *pparams;
7924 SSVAL(params,0,0);
7926 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7928 out:
7929 TALLOC_FREE(smb_dname);
7930 return;
7933 /****************************************************************************
7934 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7935 We don't actually do this - we just send a null response.
7936 ****************************************************************************/
7938 static void call_trans2findnotifyfirst(connection_struct *conn,
7939 struct smb_request *req,
7940 char **pparams, int total_params,
7941 char **ppdata, int total_data,
7942 unsigned int max_data_bytes)
7944 char *params = *pparams;
7945 uint16 info_level;
7947 if (total_params < 6) {
7948 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7949 return;
7952 info_level = SVAL(params,4);
7953 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7955 switch (info_level) {
7956 case 1:
7957 case 2:
7958 break;
7959 default:
7960 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7961 return;
7964 /* Realloc the parameter and data sizes */
7965 *pparams = (char *)SMB_REALLOC(*pparams,6);
7966 if (*pparams == NULL) {
7967 reply_nterror(req, NT_STATUS_NO_MEMORY);
7968 return;
7970 params = *pparams;
7972 SSVAL(params,0,fnf_handle);
7973 SSVAL(params,2,0); /* No changes */
7974 SSVAL(params,4,0); /* No EA errors */
7976 fnf_handle++;
7978 if(fnf_handle == 0)
7979 fnf_handle = 257;
7981 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7983 return;
7986 /****************************************************************************
7987 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7988 changes). Currently this does nothing.
7989 ****************************************************************************/
7991 static void call_trans2findnotifynext(connection_struct *conn,
7992 struct smb_request *req,
7993 char **pparams, int total_params,
7994 char **ppdata, int total_data,
7995 unsigned int max_data_bytes)
7997 char *params = *pparams;
7999 DEBUG(3,("call_trans2findnotifynext\n"));
8001 /* Realloc the parameter and data sizes */
8002 *pparams = (char *)SMB_REALLOC(*pparams,4);
8003 if (*pparams == NULL) {
8004 reply_nterror(req, NT_STATUS_NO_MEMORY);
8005 return;
8007 params = *pparams;
8009 SSVAL(params,0,0); /* No changes */
8010 SSVAL(params,2,0); /* No EA errors */
8012 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8014 return;
8017 /****************************************************************************
8018 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8019 ****************************************************************************/
8021 static void call_trans2getdfsreferral(connection_struct *conn,
8022 struct smb_request *req,
8023 char **pparams, int total_params,
8024 char **ppdata, int total_data,
8025 unsigned int max_data_bytes)
8027 char *params = *pparams;
8028 char *pathname = NULL;
8029 int reply_size = 0;
8030 int max_referral_level;
8031 NTSTATUS status = NT_STATUS_OK;
8032 TALLOC_CTX *ctx = talloc_tos();
8034 DEBUG(10,("call_trans2getdfsreferral\n"));
8036 if (total_params < 3) {
8037 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8038 return;
8041 max_referral_level = SVAL(params,0);
8043 if(!lp_host_msdfs()) {
8044 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8045 return;
8048 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8049 total_params - 2, STR_TERMINATE);
8050 if (!pathname) {
8051 reply_nterror(req, NT_STATUS_NOT_FOUND);
8052 return;
8054 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8055 ppdata,&status)) < 0) {
8056 reply_nterror(req, status);
8057 return;
8060 SSVAL(req->inbuf, smb_flg2,
8061 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8062 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8064 return;
8067 #define LMCAT_SPL 0x53
8068 #define LMFUNC_GETJOBID 0x60
8070 /****************************************************************************
8071 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8072 ****************************************************************************/
8074 static void call_trans2ioctl(connection_struct *conn,
8075 struct smb_request *req,
8076 char **pparams, int total_params,
8077 char **ppdata, int total_data,
8078 unsigned int max_data_bytes)
8080 char *pdata = *ppdata;
8081 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8083 /* check for an invalid fid before proceeding */
8085 if (!fsp) {
8086 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8087 return;
8090 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8091 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8092 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8093 if (*ppdata == NULL) {
8094 reply_nterror(req, NT_STATUS_NO_MEMORY);
8095 return;
8097 pdata = *ppdata;
8099 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8100 CAN ACCEPT THIS IN UNICODE. JRA. */
8102 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8103 srvstr_push(pdata, req->flags2, pdata + 2,
8104 global_myname(), 15,
8105 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8106 srvstr_push(pdata, req->flags2, pdata+18,
8107 lp_servicename(SNUM(conn)), 13,
8108 STR_ASCII|STR_TERMINATE); /* Service name */
8109 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8110 max_data_bytes);
8111 return;
8114 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8115 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8118 /****************************************************************************
8119 Reply to a SMBfindclose (stop trans2 directory search).
8120 ****************************************************************************/
8122 void reply_findclose(struct smb_request *req)
8124 int dptr_num;
8125 struct smbd_server_connection *sconn = smbd_server_conn;
8127 START_PROFILE(SMBfindclose);
8129 if (req->wct < 1) {
8130 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8131 END_PROFILE(SMBfindclose);
8132 return;
8135 dptr_num = SVALS(req->vwv+0, 0);
8137 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8139 dptr_close(sconn, &dptr_num);
8141 reply_outbuf(req, 0, 0);
8143 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8145 END_PROFILE(SMBfindclose);
8146 return;
8149 /****************************************************************************
8150 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8151 ****************************************************************************/
8153 void reply_findnclose(struct smb_request *req)
8155 int dptr_num;
8157 START_PROFILE(SMBfindnclose);
8159 if (req->wct < 1) {
8160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8161 END_PROFILE(SMBfindnclose);
8162 return;
8165 dptr_num = SVAL(req->vwv+0, 0);
8167 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8169 /* We never give out valid handles for a
8170 findnotifyfirst - so any dptr_num is ok here.
8171 Just ignore it. */
8173 reply_outbuf(req, 0, 0);
8175 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8177 END_PROFILE(SMBfindnclose);
8178 return;
8181 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8182 struct trans_state *state)
8184 if (get_Protocol() >= PROTOCOL_NT1) {
8185 req->flags2 |= 0x40; /* IS_LONG_NAME */
8186 SSVAL(req->inbuf,smb_flg2,req->flags2);
8189 if (conn->encrypt_level == Required && !req->encrypted) {
8190 if (state->call != TRANSACT2_QFSINFO &&
8191 state->call != TRANSACT2_SETFSINFO) {
8192 DEBUG(0,("handle_trans2: encryption required "
8193 "with call 0x%x\n",
8194 (unsigned int)state->call));
8195 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8196 return;
8200 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8202 /* Now we must call the relevant TRANS2 function */
8203 switch(state->call) {
8204 case TRANSACT2_OPEN:
8206 START_PROFILE(Trans2_open);
8207 call_trans2open(conn, req,
8208 &state->param, state->total_param,
8209 &state->data, state->total_data,
8210 state->max_data_return);
8211 END_PROFILE(Trans2_open);
8212 break;
8215 case TRANSACT2_FINDFIRST:
8217 START_PROFILE(Trans2_findfirst);
8218 call_trans2findfirst(conn, req,
8219 &state->param, state->total_param,
8220 &state->data, state->total_data,
8221 state->max_data_return);
8222 END_PROFILE(Trans2_findfirst);
8223 break;
8226 case TRANSACT2_FINDNEXT:
8228 START_PROFILE(Trans2_findnext);
8229 call_trans2findnext(conn, req,
8230 &state->param, state->total_param,
8231 &state->data, state->total_data,
8232 state->max_data_return);
8233 END_PROFILE(Trans2_findnext);
8234 break;
8237 case TRANSACT2_QFSINFO:
8239 START_PROFILE(Trans2_qfsinfo);
8240 call_trans2qfsinfo(conn, req,
8241 &state->param, state->total_param,
8242 &state->data, state->total_data,
8243 state->max_data_return);
8244 END_PROFILE(Trans2_qfsinfo);
8245 break;
8248 case TRANSACT2_SETFSINFO:
8250 START_PROFILE(Trans2_setfsinfo);
8251 call_trans2setfsinfo(conn, req,
8252 &state->param, state->total_param,
8253 &state->data, state->total_data,
8254 state->max_data_return);
8255 END_PROFILE(Trans2_setfsinfo);
8256 break;
8259 case TRANSACT2_QPATHINFO:
8260 case TRANSACT2_QFILEINFO:
8262 START_PROFILE(Trans2_qpathinfo);
8263 call_trans2qfilepathinfo(conn, req, state->call,
8264 &state->param, state->total_param,
8265 &state->data, state->total_data,
8266 state->max_data_return);
8267 END_PROFILE(Trans2_qpathinfo);
8268 break;
8271 case TRANSACT2_SETPATHINFO:
8272 case TRANSACT2_SETFILEINFO:
8274 START_PROFILE(Trans2_setpathinfo);
8275 call_trans2setfilepathinfo(conn, req, state->call,
8276 &state->param, state->total_param,
8277 &state->data, state->total_data,
8278 state->max_data_return);
8279 END_PROFILE(Trans2_setpathinfo);
8280 break;
8283 case TRANSACT2_FINDNOTIFYFIRST:
8285 START_PROFILE(Trans2_findnotifyfirst);
8286 call_trans2findnotifyfirst(conn, req,
8287 &state->param, state->total_param,
8288 &state->data, state->total_data,
8289 state->max_data_return);
8290 END_PROFILE(Trans2_findnotifyfirst);
8291 break;
8294 case TRANSACT2_FINDNOTIFYNEXT:
8296 START_PROFILE(Trans2_findnotifynext);
8297 call_trans2findnotifynext(conn, req,
8298 &state->param, state->total_param,
8299 &state->data, state->total_data,
8300 state->max_data_return);
8301 END_PROFILE(Trans2_findnotifynext);
8302 break;
8305 case TRANSACT2_MKDIR:
8307 START_PROFILE(Trans2_mkdir);
8308 call_trans2mkdir(conn, req,
8309 &state->param, state->total_param,
8310 &state->data, state->total_data,
8311 state->max_data_return);
8312 END_PROFILE(Trans2_mkdir);
8313 break;
8316 case TRANSACT2_GET_DFS_REFERRAL:
8318 START_PROFILE(Trans2_get_dfs_referral);
8319 call_trans2getdfsreferral(conn, req,
8320 &state->param, state->total_param,
8321 &state->data, state->total_data,
8322 state->max_data_return);
8323 END_PROFILE(Trans2_get_dfs_referral);
8324 break;
8327 case TRANSACT2_IOCTL:
8329 START_PROFILE(Trans2_ioctl);
8330 call_trans2ioctl(conn, req,
8331 &state->param, state->total_param,
8332 &state->data, state->total_data,
8333 state->max_data_return);
8334 END_PROFILE(Trans2_ioctl);
8335 break;
8338 default:
8339 /* Error in request */
8340 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8341 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8345 /****************************************************************************
8346 Reply to a SMBtrans2.
8347 ****************************************************************************/
8349 void reply_trans2(struct smb_request *req)
8351 connection_struct *conn = req->conn;
8352 unsigned int dsoff;
8353 unsigned int dscnt;
8354 unsigned int psoff;
8355 unsigned int pscnt;
8356 unsigned int tran_call;
8357 struct trans_state *state;
8358 NTSTATUS result;
8360 START_PROFILE(SMBtrans2);
8362 if (req->wct < 14) {
8363 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8364 END_PROFILE(SMBtrans2);
8365 return;
8368 dsoff = SVAL(req->vwv+12, 0);
8369 dscnt = SVAL(req->vwv+11, 0);
8370 psoff = SVAL(req->vwv+10, 0);
8371 pscnt = SVAL(req->vwv+9, 0);
8372 tran_call = SVAL(req->vwv+14, 0);
8374 result = allow_new_trans(conn->pending_trans, req->mid);
8375 if (!NT_STATUS_IS_OK(result)) {
8376 DEBUG(2, ("Got invalid trans2 request: %s\n",
8377 nt_errstr(result)));
8378 reply_nterror(req, result);
8379 END_PROFILE(SMBtrans2);
8380 return;
8383 if (IS_IPC(conn)) {
8384 switch (tran_call) {
8385 /* List the allowed trans2 calls on IPC$ */
8386 case TRANSACT2_OPEN:
8387 case TRANSACT2_GET_DFS_REFERRAL:
8388 case TRANSACT2_QFILEINFO:
8389 case TRANSACT2_QFSINFO:
8390 case TRANSACT2_SETFSINFO:
8391 break;
8392 default:
8393 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8394 END_PROFILE(SMBtrans2);
8395 return;
8399 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8400 DEBUG(0, ("talloc failed\n"));
8401 reply_nterror(req, NT_STATUS_NO_MEMORY);
8402 END_PROFILE(SMBtrans2);
8403 return;
8406 state->cmd = SMBtrans2;
8408 state->mid = req->mid;
8409 state->vuid = req->vuid;
8410 state->setup_count = SVAL(req->vwv+13, 0);
8411 state->setup = NULL;
8412 state->total_param = SVAL(req->vwv+0, 0);
8413 state->param = NULL;
8414 state->total_data = SVAL(req->vwv+1, 0);
8415 state->data = NULL;
8416 state->max_param_return = SVAL(req->vwv+2, 0);
8417 state->max_data_return = SVAL(req->vwv+3, 0);
8418 state->max_setup_return = SVAL(req->vwv+4, 0);
8419 state->close_on_completion = BITSETW(req->vwv+5, 0);
8420 state->one_way = BITSETW(req->vwv+5, 1);
8422 state->call = tran_call;
8424 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8425 is so as a sanity check */
8426 if (state->setup_count != 1) {
8428 * Need to have rc=0 for ioctl to get job id for OS/2.
8429 * Network printing will fail if function is not successful.
8430 * Similar function in reply.c will be used if protocol
8431 * is LANMAN1.0 instead of LM1.2X002.
8432 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8433 * outbuf doesn't have to be set(only job id is used).
8435 if ( (state->setup_count == 4)
8436 && (tran_call == TRANSACT2_IOCTL)
8437 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8438 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8439 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8440 } else {
8441 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8442 DEBUG(2,("Transaction is %d\n",tran_call));
8443 TALLOC_FREE(state);
8444 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8445 END_PROFILE(SMBtrans2);
8446 return;
8450 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8451 goto bad_param;
8453 if (state->total_data) {
8455 if (trans_oob(state->total_data, 0, dscnt)
8456 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8457 goto bad_param;
8460 /* Can't use talloc here, the core routines do realloc on the
8461 * params and data. */
8462 state->data = (char *)SMB_MALLOC(state->total_data);
8463 if (state->data == NULL) {
8464 DEBUG(0,("reply_trans2: data malloc fail for %u "
8465 "bytes !\n", (unsigned int)state->total_data));
8466 TALLOC_FREE(state);
8467 reply_nterror(req, NT_STATUS_NO_MEMORY);
8468 END_PROFILE(SMBtrans2);
8469 return;
8472 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8475 if (state->total_param) {
8477 if (trans_oob(state->total_param, 0, pscnt)
8478 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8479 goto bad_param;
8482 /* Can't use talloc here, the core routines do realloc on the
8483 * params and data. */
8484 state->param = (char *)SMB_MALLOC(state->total_param);
8485 if (state->param == NULL) {
8486 DEBUG(0,("reply_trans: param malloc fail for %u "
8487 "bytes !\n", (unsigned int)state->total_param));
8488 SAFE_FREE(state->data);
8489 TALLOC_FREE(state);
8490 reply_nterror(req, NT_STATUS_NO_MEMORY);
8491 END_PROFILE(SMBtrans2);
8492 return;
8495 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8498 state->received_data = dscnt;
8499 state->received_param = pscnt;
8501 if ((state->received_param == state->total_param) &&
8502 (state->received_data == state->total_data)) {
8504 handle_trans2(conn, req, state);
8506 SAFE_FREE(state->data);
8507 SAFE_FREE(state->param);
8508 TALLOC_FREE(state);
8509 END_PROFILE(SMBtrans2);
8510 return;
8513 DLIST_ADD(conn->pending_trans, state);
8515 /* We need to send an interim response then receive the rest
8516 of the parameter/data bytes */
8517 reply_outbuf(req, 0, 0);
8518 show_msg((char *)req->outbuf);
8519 END_PROFILE(SMBtrans2);
8520 return;
8522 bad_param:
8524 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8525 SAFE_FREE(state->data);
8526 SAFE_FREE(state->param);
8527 TALLOC_FREE(state);
8528 END_PROFILE(SMBtrans2);
8529 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8533 /****************************************************************************
8534 Reply to a SMBtranss2
8535 ****************************************************************************/
8537 void reply_transs2(struct smb_request *req)
8539 connection_struct *conn = req->conn;
8540 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8541 struct trans_state *state;
8543 START_PROFILE(SMBtranss2);
8545 show_msg((char *)req->inbuf);
8547 if (req->wct < 8) {
8548 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8549 END_PROFILE(SMBtranss2);
8550 return;
8553 for (state = conn->pending_trans; state != NULL;
8554 state = state->next) {
8555 if (state->mid == req->mid) {
8556 break;
8560 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8561 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8562 END_PROFILE(SMBtranss2);
8563 return;
8566 /* Revise state->total_param and state->total_data in case they have
8567 changed downwards */
8569 if (SVAL(req->vwv+0, 0) < state->total_param)
8570 state->total_param = SVAL(req->vwv+0, 0);
8571 if (SVAL(req->vwv+1, 0) < state->total_data)
8572 state->total_data = SVAL(req->vwv+1, 0);
8574 pcnt = SVAL(req->vwv+2, 0);
8575 poff = SVAL(req->vwv+3, 0);
8576 pdisp = SVAL(req->vwv+4, 0);
8578 dcnt = SVAL(req->vwv+5, 0);
8579 doff = SVAL(req->vwv+6, 0);
8580 ddisp = SVAL(req->vwv+7, 0);
8582 state->received_param += pcnt;
8583 state->received_data += dcnt;
8585 if ((state->received_data > state->total_data) ||
8586 (state->received_param > state->total_param))
8587 goto bad_param;
8589 if (pcnt) {
8590 if (trans_oob(state->total_param, pdisp, pcnt)
8591 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8592 goto bad_param;
8594 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8597 if (dcnt) {
8598 if (trans_oob(state->total_data, ddisp, dcnt)
8599 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8600 goto bad_param;
8602 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8605 if ((state->received_param < state->total_param) ||
8606 (state->received_data < state->total_data)) {
8607 END_PROFILE(SMBtranss2);
8608 return;
8611 handle_trans2(conn, req, state);
8613 DLIST_REMOVE(conn->pending_trans, state);
8614 SAFE_FREE(state->data);
8615 SAFE_FREE(state->param);
8616 TALLOC_FREE(state);
8618 END_PROFILE(SMBtranss2);
8619 return;
8621 bad_param:
8623 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8624 DLIST_REMOVE(conn->pending_trans, state);
8625 SAFE_FREE(state->data);
8626 SAFE_FREE(state->param);
8627 TALLOC_FREE(state);
8628 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8629 END_PROFILE(SMBtranss2);
8630 return;