SMB2: Fix rename on Windows 7.
[Samba/gebeck_regimport.git] / source3 / smbd / trans2.c
blobf69cefe66b54d73e89d5901100876a7cb046205d
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "version.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
30 #include "../librpc/gen_ndr/xattr.h"
31 #include "../librpc/gen_ndr/ndr_security.h"
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
36 char *pdata,
37 files_struct *fsp,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
41 char *pdata,
42 files_struct *fsp,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
59 return val;
62 /********************************************************************
63 Create a 64 bit FileIndex. If the file is on the same device as
64 the root of the share, just return the 64-bit inode. If it isn't,
65 mangle as we used to do.
66 ********************************************************************/
68 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
70 uint64_t file_index;
71 if (conn->base_share_dev == psbuf->st_ex_dev) {
72 return (uint64_t)psbuf->st_ex_ino;
74 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
75 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
76 return file_index;
79 /****************************************************************************
80 Utility functions for dealing with extended attributes.
81 ****************************************************************************/
83 /****************************************************************************
84 Refuse to allow clients to overwrite our private xattrs.
85 ****************************************************************************/
87 static bool samba_private_attr_name(const char *unix_ea_name)
89 static const char * const prohibited_ea_names[] = {
90 SAMBA_POSIX_INHERITANCE_EA_NAME,
91 SAMBA_XATTR_DOS_ATTRIB,
92 SAMBA_XATTR_MARKER,
93 XATTR_NTACL_NAME,
94 NULL
97 int i;
99 for (i = 0; prohibited_ea_names[i]; i++) {
100 if (strequal( prohibited_ea_names[i], unix_ea_name))
101 return true;
103 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
104 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
105 return true;
107 return false;
110 /****************************************************************************
111 Get one EA value. Fill in a struct ea_struct.
112 ****************************************************************************/
114 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
115 files_struct *fsp, const char *fname,
116 const char *ea_name, struct ea_struct *pea)
118 /* Get the value of this xattr. Max size is 64k. */
119 size_t attr_size = 256;
120 char *val = NULL;
121 ssize_t sizeret;
123 again:
125 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
126 if (!val) {
127 return NT_STATUS_NO_MEMORY;
130 if (fsp && fsp->fh->fd != -1) {
131 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
132 } else {
133 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
136 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
137 attr_size = 65536;
138 goto again;
141 if (sizeret == -1) {
142 return map_nt_error_from_unix(errno);
145 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
146 dump_data(10, (uint8 *)val, sizeret);
148 pea->flags = 0;
149 if (strnequal(ea_name, "user.", 5)) {
150 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
151 } else {
152 pea->name = talloc_strdup(mem_ctx, ea_name);
154 if (pea->name == NULL) {
155 TALLOC_FREE(val);
156 return NT_STATUS_NO_MEMORY;
158 pea->value.data = (unsigned char *)val;
159 pea->value.length = (size_t)sizeret;
160 return NT_STATUS_OK;
163 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
164 files_struct *fsp, const char *fname,
165 char ***pnames, size_t *pnum_names)
167 /* Get a list of all xattrs. Max namesize is 64k. */
168 size_t ea_namelist_size = 1024;
169 char *ea_namelist = NULL;
171 char *p;
172 char **names, **tmp;
173 size_t num_names;
174 ssize_t sizeret = -1;
176 if (!lp_ea_support(SNUM(conn))) {
177 if (pnames) {
178 *pnames = NULL;
180 *pnum_names = 0;
181 return NT_STATUS_OK;
185 * TALLOC the result early to get the talloc hierarchy right.
188 names = TALLOC_ARRAY(mem_ctx, char *, 1);
189 if (names == NULL) {
190 DEBUG(0, ("talloc failed\n"));
191 return NT_STATUS_NO_MEMORY;
194 while (ea_namelist_size <= 65536) {
196 ea_namelist = TALLOC_REALLOC_ARRAY(
197 names, ea_namelist, char, ea_namelist_size);
198 if (ea_namelist == NULL) {
199 DEBUG(0, ("talloc failed\n"));
200 TALLOC_FREE(names);
201 return NT_STATUS_NO_MEMORY;
204 if (fsp && fsp->fh->fd != -1) {
205 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
206 ea_namelist_size);
207 } else {
208 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
209 ea_namelist_size);
212 if ((sizeret == -1) && (errno == ERANGE)) {
213 ea_namelist_size *= 2;
215 else {
216 break;
220 if (sizeret == -1) {
221 TALLOC_FREE(names);
222 return map_nt_error_from_unix(errno);
225 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
226 (unsigned int)sizeret));
228 if (sizeret == 0) {
229 TALLOC_FREE(names);
230 if (pnames) {
231 *pnames = NULL;
233 *pnum_names = 0;
234 return NT_STATUS_OK;
238 * Ensure the result is 0-terminated
241 if (ea_namelist[sizeret-1] != '\0') {
242 TALLOC_FREE(names);
243 return NT_STATUS_INTERNAL_ERROR;
247 * count the names
249 num_names = 0;
251 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
252 num_names += 1;
255 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
256 if (tmp == NULL) {
257 DEBUG(0, ("talloc failed\n"));
258 TALLOC_FREE(names);
259 return NT_STATUS_NO_MEMORY;
262 names = tmp;
263 num_names = 0;
265 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
266 names[num_names++] = p;
269 if (pnames) {
270 *pnames = names;
271 } else {
272 TALLOC_FREE(names);
274 *pnum_names = num_names;
275 return NT_STATUS_OK;
278 /****************************************************************************
279 Return a linked list of the total EA's. Plus the total size
280 ****************************************************************************/
282 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
283 const char *fname, size_t *pea_total_len)
285 /* Get a list of all xattrs. Max namesize is 64k. */
286 size_t i, num_names;
287 char **names;
288 struct ea_list *ea_list_head = NULL;
289 NTSTATUS status;
291 *pea_total_len = 0;
293 if (!lp_ea_support(SNUM(conn))) {
294 return NULL;
297 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
298 &names, &num_names);
300 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
301 return NULL;
304 for (i=0; i<num_names; i++) {
305 struct ea_list *listp;
306 fstring dos_ea_name;
308 if (strnequal(names[i], "system.", 7)
309 || samba_private_attr_name(names[i]))
310 continue;
312 listp = TALLOC_P(mem_ctx, struct ea_list);
313 if (listp == NULL) {
314 return NULL;
317 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
318 fname, names[i],
319 &listp->ea))) {
320 return NULL;
323 push_ascii_fstring(dos_ea_name, listp->ea.name);
325 *pea_total_len +=
326 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
328 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
329 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
330 (unsigned int)listp->ea.value.length));
332 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
336 /* Add on 4 for total length. */
337 if (*pea_total_len) {
338 *pea_total_len += 4;
341 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
342 (unsigned int)*pea_total_len));
344 return ea_list_head;
347 /****************************************************************************
348 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
349 that was filled.
350 ****************************************************************************/
352 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
353 connection_struct *conn, struct ea_list *ea_list)
355 unsigned int ret_data_size = 4;
356 char *p = pdata;
358 SMB_ASSERT(total_data_size >= 4);
360 if (!lp_ea_support(SNUM(conn))) {
361 SIVAL(pdata,4,0);
362 return 4;
365 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
366 size_t dos_namelen;
367 fstring dos_ea_name;
368 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
369 dos_namelen = strlen(dos_ea_name);
370 if (dos_namelen > 255 || dos_namelen == 0) {
371 break;
373 if (ea_list->ea.value.length > 65535) {
374 break;
376 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
377 break;
380 /* We know we have room. */
381 SCVAL(p,0,ea_list->ea.flags);
382 SCVAL(p,1,dos_namelen);
383 SSVAL(p,2,ea_list->ea.value.length);
384 fstrcpy(p+4, dos_ea_name);
385 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
387 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
388 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
391 ret_data_size = PTR_DIFF(p, pdata);
392 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
393 SIVAL(pdata,0,ret_data_size);
394 return ret_data_size;
397 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
398 char *pdata,
399 unsigned int total_data_size,
400 unsigned int *ret_data_size,
401 connection_struct *conn,
402 struct ea_list *ea_list)
404 uint8_t *p = (uint8_t *)pdata;
405 uint8_t *last_start = NULL;
407 *ret_data_size = 0;
409 if (!lp_ea_support(SNUM(conn))) {
410 return NT_STATUS_NO_EAS_ON_FILE;
413 for (; ea_list; ea_list = ea_list->next) {
414 size_t dos_namelen;
415 fstring dos_ea_name;
416 size_t this_size;
418 if (last_start) {
419 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
421 last_start = p;
423 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
424 dos_namelen = strlen(dos_ea_name);
425 if (dos_namelen > 255 || dos_namelen == 0) {
426 return NT_STATUS_INTERNAL_ERROR;
428 if (ea_list->ea.value.length > 65535) {
429 return NT_STATUS_INTERNAL_ERROR;
432 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
434 if (ea_list->next) {
435 size_t pad = 4 - (this_size % 4);
436 this_size += pad;
439 if (this_size > total_data_size) {
440 return NT_STATUS_INFO_LENGTH_MISMATCH;
443 /* We know we have room. */
444 SIVAL(p, 0x00, 0); /* next offset */
445 SCVAL(p, 0x04, ea_list->ea.flags);
446 SCVAL(p, 0x05, dos_namelen);
447 SSVAL(p, 0x06, ea_list->ea.value.length);
448 fstrcpy((char *)(p+0x08), dos_ea_name);
449 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
451 total_data_size -= this_size;
452 p += this_size;
455 *ret_data_size = PTR_DIFF(p, pdata);
456 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
457 return NT_STATUS_OK;
460 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
462 size_t total_ea_len = 0;
463 TALLOC_CTX *mem_ctx = NULL;
465 if (!lp_ea_support(SNUM(conn))) {
466 return 0;
468 mem_ctx = talloc_tos();
469 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
470 return total_ea_len;
473 /****************************************************************************
474 Ensure the EA name is case insensitive by matching any existing EA name.
475 ****************************************************************************/
477 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
479 size_t total_ea_len;
480 TALLOC_CTX *mem_ctx = talloc_tos();
481 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
483 for (; ea_list; ea_list = ea_list->next) {
484 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
485 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
486 &unix_ea_name[5], ea_list->ea.name));
487 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
488 break;
493 /****************************************************************************
494 Set or delete an extended attribute.
495 ****************************************************************************/
497 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
498 const struct smb_filename *smb_fname, struct ea_list *ea_list)
500 char *fname = NULL;
502 if (!lp_ea_support(SNUM(conn))) {
503 return NT_STATUS_EAS_NOT_SUPPORTED;
506 /* For now setting EAs on streams isn't supported. */
507 fname = smb_fname->base_name;
509 for (;ea_list; ea_list = ea_list->next) {
510 int ret;
511 fstring unix_ea_name;
513 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
514 fstrcat(unix_ea_name, ea_list->ea.name);
516 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
518 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
520 if (samba_private_attr_name(unix_ea_name)) {
521 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
522 return NT_STATUS_ACCESS_DENIED;
525 if (ea_list->ea.value.length == 0) {
526 /* Remove the attribute. */
527 if (fsp && (fsp->fh->fd != -1)) {
528 DEBUG(10,("set_ea: deleting ea name %s on "
529 "file %s by file descriptor.\n",
530 unix_ea_name, fsp_str_dbg(fsp)));
531 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
532 } else {
533 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
534 unix_ea_name, fname));
535 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
537 #ifdef ENOATTR
538 /* Removing a non existent attribute always succeeds. */
539 if (ret == -1 && errno == ENOATTR) {
540 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
541 unix_ea_name));
542 ret = 0;
544 #endif
545 } else {
546 if (fsp && (fsp->fh->fd != -1)) {
547 DEBUG(10,("set_ea: setting ea name %s on file "
548 "%s by file descriptor.\n",
549 unix_ea_name, fsp_str_dbg(fsp)));
550 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
551 ea_list->ea.value.data, ea_list->ea.value.length, 0);
552 } else {
553 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
554 unix_ea_name, fname));
555 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
556 ea_list->ea.value.data, ea_list->ea.value.length, 0);
560 if (ret == -1) {
561 #ifdef ENOTSUP
562 if (errno == ENOTSUP) {
563 return NT_STATUS_EAS_NOT_SUPPORTED;
565 #endif
566 return map_nt_error_from_unix(errno);
570 return NT_STATUS_OK;
572 /****************************************************************************
573 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
574 ****************************************************************************/
576 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
578 struct ea_list *ea_list_head = NULL;
579 size_t converted_size, offset = 0;
581 while (offset + 2 < data_size) {
582 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
583 unsigned int namelen = CVAL(pdata,offset);
585 offset++; /* Go past the namelen byte. */
587 /* integer wrap paranioa. */
588 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
589 (offset > data_size) || (namelen > data_size) ||
590 (offset + namelen >= data_size)) {
591 break;
593 /* Ensure the name is null terminated. */
594 if (pdata[offset + namelen] != '\0') {
595 return NULL;
597 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
598 &converted_size)) {
599 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
600 "failed: %s", strerror(errno)));
602 if (!eal->ea.name) {
603 return NULL;
606 offset += (namelen + 1); /* Go past the name + terminating zero. */
607 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
608 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
611 return ea_list_head;
614 /****************************************************************************
615 Read one EA list entry from the buffer.
616 ****************************************************************************/
618 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
620 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
621 uint16 val_len;
622 unsigned int namelen;
623 size_t converted_size;
625 if (!eal) {
626 return NULL;
629 if (data_size < 6) {
630 return NULL;
633 eal->ea.flags = CVAL(pdata,0);
634 namelen = CVAL(pdata,1);
635 val_len = SVAL(pdata,2);
637 if (4 + namelen + 1 + val_len > data_size) {
638 return NULL;
641 /* Ensure the name is null terminated. */
642 if (pdata[namelen + 4] != '\0') {
643 return NULL;
645 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
646 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
647 strerror(errno)));
649 if (!eal->ea.name) {
650 return NULL;
653 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
654 if (!eal->ea.value.data) {
655 return NULL;
658 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
660 /* Ensure we're null terminated just in case we print the value. */
661 eal->ea.value.data[val_len] = '\0';
662 /* But don't count the null. */
663 eal->ea.value.length--;
665 if (pbytes_used) {
666 *pbytes_used = 4 + namelen + 1 + val_len;
669 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
670 dump_data(10, eal->ea.value.data, eal->ea.value.length);
672 return eal;
675 /****************************************************************************
676 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
677 ****************************************************************************/
679 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
681 struct ea_list *ea_list_head = NULL;
682 size_t offset = 0;
683 size_t bytes_used = 0;
685 while (offset < data_size) {
686 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
688 if (!eal) {
689 return NULL;
692 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
693 offset += bytes_used;
696 return ea_list_head;
699 /****************************************************************************
700 Count the total EA size needed.
701 ****************************************************************************/
703 static size_t ea_list_size(struct ea_list *ealist)
705 fstring dos_ea_name;
706 struct ea_list *listp;
707 size_t ret = 0;
709 for (listp = ealist; listp; listp = listp->next) {
710 push_ascii_fstring(dos_ea_name, listp->ea.name);
711 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
713 /* Add on 4 for total length. */
714 if (ret) {
715 ret += 4;
718 return ret;
721 /****************************************************************************
722 Return a union of EA's from a file list and a list of names.
723 The TALLOC context for the two lists *MUST* be identical as we steal
724 memory from one list to add to another. JRA.
725 ****************************************************************************/
727 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
729 struct ea_list *nlistp, *flistp;
731 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
732 for (flistp = file_list; flistp; flistp = flistp->next) {
733 if (strequal(nlistp->ea.name, flistp->ea.name)) {
734 break;
738 if (flistp) {
739 /* Copy the data from this entry. */
740 nlistp->ea.flags = flistp->ea.flags;
741 nlistp->ea.value = flistp->ea.value;
742 } else {
743 /* Null entry. */
744 nlistp->ea.flags = 0;
745 ZERO_STRUCT(nlistp->ea.value);
749 *total_ea_len = ea_list_size(name_list);
750 return name_list;
753 /****************************************************************************
754 Send the required number of replies back.
755 We assume all fields other than the data fields are
756 set correctly for the type of call.
757 HACK ! Always assumes smb_setup field is zero.
758 ****************************************************************************/
760 void send_trans2_replies(connection_struct *conn,
761 struct smb_request *req,
762 const char *params,
763 int paramsize,
764 const char *pdata,
765 int datasize,
766 int max_data_bytes)
768 /* As we are using a protocol > LANMAN1 then the max_send
769 variable must have been set in the sessetupX call.
770 This takes precedence over the max_xmit field in the
771 global struct. These different max_xmit variables should
772 be merged as this is now too confusing */
774 int data_to_send = datasize;
775 int params_to_send = paramsize;
776 int useable_space;
777 const char *pp = params;
778 const char *pd = pdata;
779 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
780 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
781 int data_alignment_offset = 0;
782 bool overflow = False;
783 struct smbd_server_connection *sconn = smbd_server_conn;
784 int max_send = sconn->smb1.sessions.max_send;
786 /* Modify the data_to_send and datasize and set the error if
787 we're trying to send more than max_data_bytes. We still send
788 the part of the packet(s) that fit. Strange, but needed
789 for OS/2. */
791 if (max_data_bytes > 0 && datasize > max_data_bytes) {
792 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
793 max_data_bytes, datasize ));
794 datasize = data_to_send = max_data_bytes;
795 overflow = True;
798 /* If there genuinely are no parameters or data to send just send the empty packet */
800 if(params_to_send == 0 && data_to_send == 0) {
801 reply_outbuf(req, 10, 0);
802 show_msg((char *)req->outbuf);
803 if (!srv_send_smb(smbd_server_fd(),
804 (char *)req->outbuf,
805 true, req->seqnum+1,
806 IS_CONN_ENCRYPTED(conn),
807 &req->pcd)) {
808 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
810 TALLOC_FREE(req->outbuf);
811 return;
814 /* When sending params and data ensure that both are nicely aligned */
815 /* Only do this alignment when there is also data to send - else
816 can cause NT redirector problems. */
818 if (((params_to_send % 4) != 0) && (data_to_send != 0))
819 data_alignment_offset = 4 - (params_to_send % 4);
821 /* Space is bufsize minus Netbios over TCP header minus SMB header */
822 /* The alignment_offset is to align the param bytes on an even byte
823 boundary. NT 4.0 Beta needs this to work correctly. */
825 useable_space = max_send - (smb_size
826 + 2 * 10 /* wct */
827 + alignment_offset
828 + data_alignment_offset);
830 if (useable_space < 0) {
831 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
832 "= %d!!!", useable_space));
833 exit_server_cleanly("send_trans2_replies: Not enough space");
836 while (params_to_send || data_to_send) {
837 /* Calculate whether we will totally or partially fill this packet */
839 total_sent_thistime = params_to_send + data_to_send;
841 /* We can never send more than useable_space */
843 * Note that 'useable_space' does not include the alignment offsets,
844 * but we must include the alignment offsets in the calculation of
845 * the length of the data we send over the wire, as the alignment offsets
846 * are sent here. Fix from Marc_Jacobsen@hp.com.
849 total_sent_thistime = MIN(total_sent_thistime, useable_space);
851 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
852 + data_alignment_offset);
855 * We might have SMBtrans2s in req which was transferred to
856 * the outbuf, fix that.
858 SCVAL(req->outbuf, smb_com, SMBtrans2);
860 /* Set total params and data to be sent */
861 SSVAL(req->outbuf,smb_tprcnt,paramsize);
862 SSVAL(req->outbuf,smb_tdrcnt,datasize);
864 /* Calculate how many parameters and data we can fit into
865 * this packet. Parameters get precedence
868 params_sent_thistime = MIN(params_to_send,useable_space);
869 data_sent_thistime = useable_space - params_sent_thistime;
870 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
872 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
874 /* smb_proff is the offset from the start of the SMB header to the
875 parameter bytes, however the first 4 bytes of outbuf are
876 the Netbios over TCP header. Thus use smb_base() to subtract
877 them from the calculation */
879 SSVAL(req->outbuf,smb_proff,
880 ((smb_buf(req->outbuf)+alignment_offset)
881 - smb_base(req->outbuf)));
883 if(params_sent_thistime == 0)
884 SSVAL(req->outbuf,smb_prdisp,0);
885 else
886 /* Absolute displacement of param bytes sent in this packet */
887 SSVAL(req->outbuf,smb_prdisp,pp - params);
889 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
890 if(data_sent_thistime == 0) {
891 SSVAL(req->outbuf,smb_droff,0);
892 SSVAL(req->outbuf,smb_drdisp, 0);
893 } else {
894 /* The offset of the data bytes is the offset of the
895 parameter bytes plus the number of parameters being sent this time */
896 SSVAL(req->outbuf, smb_droff,
897 ((smb_buf(req->outbuf)+alignment_offset)
898 - smb_base(req->outbuf))
899 + params_sent_thistime + data_alignment_offset);
900 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
903 /* Initialize the padding for alignment */
905 if (alignment_offset != 0) {
906 memset(smb_buf(req->outbuf), 0, alignment_offset);
909 /* Copy the param bytes into the packet */
911 if(params_sent_thistime) {
912 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
913 params_sent_thistime);
916 /* Copy in the data bytes */
917 if(data_sent_thistime) {
918 if (data_alignment_offset != 0) {
919 memset((smb_buf(req->outbuf)+alignment_offset+
920 params_sent_thistime), 0,
921 data_alignment_offset);
923 memcpy(smb_buf(req->outbuf)+alignment_offset
924 +params_sent_thistime+data_alignment_offset,
925 pd,data_sent_thistime);
928 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
929 params_sent_thistime, data_sent_thistime, useable_space));
930 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
931 params_to_send, data_to_send, paramsize, datasize));
933 if (overflow) {
934 error_packet_set((char *)req->outbuf,
935 ERRDOS,ERRbufferoverflow,
936 STATUS_BUFFER_OVERFLOW,
937 __LINE__,__FILE__);
940 /* Send the packet */
941 show_msg((char *)req->outbuf);
942 if (!srv_send_smb(smbd_server_fd(),
943 (char *)req->outbuf,
944 true, req->seqnum+1,
945 IS_CONN_ENCRYPTED(conn),
946 &req->pcd))
947 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
949 TALLOC_FREE(req->outbuf);
951 pp += params_sent_thistime;
952 pd += data_sent_thistime;
954 params_to_send -= params_sent_thistime;
955 data_to_send -= data_sent_thistime;
957 /* Sanity check */
958 if(params_to_send < 0 || data_to_send < 0) {
959 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
960 params_to_send, data_to_send));
961 return;
965 return;
968 /****************************************************************************
969 Reply to a TRANSACT2_OPEN.
970 ****************************************************************************/
972 static void call_trans2open(connection_struct *conn,
973 struct smb_request *req,
974 char **pparams, int total_params,
975 char **ppdata, int total_data,
976 unsigned int max_data_bytes)
978 struct smb_filename *smb_fname = NULL;
979 char *params = *pparams;
980 char *pdata = *ppdata;
981 int deny_mode;
982 int32 open_attr;
983 bool oplock_request;
984 #if 0
985 bool return_additional_info;
986 int16 open_sattr;
987 time_t open_time;
988 #endif
989 int open_ofun;
990 uint32 open_size;
991 char *pname;
992 char *fname = NULL;
993 SMB_OFF_T size=0;
994 int fattr=0,mtime=0;
995 SMB_INO_T inode = 0;
996 int smb_action = 0;
997 files_struct *fsp;
998 struct ea_list *ea_list = NULL;
999 uint16 flags = 0;
1000 NTSTATUS status;
1001 uint32 access_mask;
1002 uint32 share_mode;
1003 uint32 create_disposition;
1004 uint32 create_options = 0;
1005 uint32_t private_flags = 0;
1006 TALLOC_CTX *ctx = talloc_tos();
1009 * Ensure we have enough parameters to perform the operation.
1012 if (total_params < 29) {
1013 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1014 goto out;
1017 flags = SVAL(params, 0);
1018 deny_mode = SVAL(params, 2);
1019 open_attr = SVAL(params,6);
1020 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1021 if (oplock_request) {
1022 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1025 #if 0
1026 return_additional_info = BITSETW(params,0);
1027 open_sattr = SVAL(params, 4);
1028 open_time = make_unix_date3(params+8);
1029 #endif
1030 open_ofun = SVAL(params,12);
1031 open_size = IVAL(params,14);
1032 pname = &params[28];
1034 if (IS_IPC(conn)) {
1035 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1036 goto out;
1039 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1040 total_params - 28, STR_TERMINATE,
1041 &status);
1042 if (!NT_STATUS_IS_OK(status)) {
1043 reply_nterror(req, status);
1044 goto out;
1047 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1048 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1049 (unsigned int)open_ofun, open_size));
1051 status = filename_convert(ctx,
1052 conn,
1053 req->flags2 & FLAGS2_DFS_PATHNAMES,
1054 fname,
1056 NULL,
1057 &smb_fname);
1058 if (!NT_STATUS_IS_OK(status)) {
1059 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1060 reply_botherror(req,
1061 NT_STATUS_PATH_NOT_COVERED,
1062 ERRSRV, ERRbadpath);
1063 goto out;
1065 reply_nterror(req, status);
1066 goto out;
1069 if (open_ofun == 0) {
1070 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1071 goto out;
1074 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1075 &access_mask, &share_mode,
1076 &create_disposition,
1077 &create_options,
1078 &private_flags)) {
1079 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1080 goto out;
1083 /* Any data in this call is an EA list. */
1084 if (total_data && (total_data != 4)) {
1085 if (total_data < 10) {
1086 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1087 goto out;
1090 if (IVAL(pdata,0) > total_data) {
1091 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1092 IVAL(pdata,0), (unsigned int)total_data));
1093 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1094 goto out;
1097 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1098 total_data - 4);
1099 if (!ea_list) {
1100 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1101 goto out;
1104 if (!lp_ea_support(SNUM(conn))) {
1105 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1106 goto out;
1110 status = SMB_VFS_CREATE_FILE(
1111 conn, /* conn */
1112 req, /* req */
1113 0, /* root_dir_fid */
1114 smb_fname, /* fname */
1115 access_mask, /* access_mask */
1116 share_mode, /* share_access */
1117 create_disposition, /* create_disposition*/
1118 create_options, /* create_options */
1119 open_attr, /* file_attributes */
1120 oplock_request, /* oplock_request */
1121 open_size, /* allocation_size */
1122 private_flags,
1123 NULL, /* sd */
1124 ea_list, /* ea_list */
1125 &fsp, /* result */
1126 &smb_action); /* psbuf */
1128 if (!NT_STATUS_IS_OK(status)) {
1129 if (open_was_deferred(req->mid)) {
1130 /* We have re-scheduled this call. */
1131 goto out;
1133 reply_openerror(req, status);
1134 goto out;
1137 size = get_file_size_stat(&smb_fname->st);
1138 fattr = dos_mode(conn, smb_fname);
1139 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1140 inode = smb_fname->st.st_ex_ino;
1141 if (fattr & aDIR) {
1142 close_file(req, fsp, ERROR_CLOSE);
1143 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1144 goto out;
1147 /* Realloc the size of parameters and data we will return */
1148 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1149 if(*pparams == NULL ) {
1150 reply_nterror(req, NT_STATUS_NO_MEMORY);
1151 goto out;
1153 params = *pparams;
1155 SSVAL(params,0,fsp->fnum);
1156 SSVAL(params,2,fattr);
1157 srv_put_dos_date2(params,4, mtime);
1158 SIVAL(params,8, (uint32)size);
1159 SSVAL(params,12,deny_mode);
1160 SSVAL(params,14,0); /* open_type - file or directory. */
1161 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1163 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1164 smb_action |= EXTENDED_OPLOCK_GRANTED;
1167 SSVAL(params,18,smb_action);
1170 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1172 SIVAL(params,20,inode);
1173 SSVAL(params,24,0); /* Padding. */
1174 if (flags & 8) {
1175 uint32 ea_size = estimate_ea_size(conn, fsp,
1176 fsp->fsp_name->base_name);
1177 SIVAL(params, 26, ea_size);
1178 } else {
1179 SIVAL(params, 26, 0);
1182 /* Send the required number of replies */
1183 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1184 out:
1185 TALLOC_FREE(smb_fname);
1188 /*********************************************************
1189 Routine to check if a given string matches exactly.
1190 as a special case a mask of "." does NOT match. That
1191 is required for correct wildcard semantics
1192 Case can be significant or not.
1193 **********************************************************/
1195 static bool exact_match(bool has_wild,
1196 bool case_sensitive,
1197 const char *str,
1198 const char *mask)
1200 if (mask[0] == '.' && mask[1] == 0) {
1201 return false;
1204 if (has_wild) {
1205 return false;
1208 if (case_sensitive) {
1209 return strcmp(str,mask)==0;
1210 } else {
1211 return StrCaseCmp(str,mask) == 0;
1215 /****************************************************************************
1216 Return the filetype for UNIX extensions.
1217 ****************************************************************************/
1219 static uint32 unix_filetype(mode_t mode)
1221 if(S_ISREG(mode))
1222 return UNIX_TYPE_FILE;
1223 else if(S_ISDIR(mode))
1224 return UNIX_TYPE_DIR;
1225 #ifdef S_ISLNK
1226 else if(S_ISLNK(mode))
1227 return UNIX_TYPE_SYMLINK;
1228 #endif
1229 #ifdef S_ISCHR
1230 else if(S_ISCHR(mode))
1231 return UNIX_TYPE_CHARDEV;
1232 #endif
1233 #ifdef S_ISBLK
1234 else if(S_ISBLK(mode))
1235 return UNIX_TYPE_BLKDEV;
1236 #endif
1237 #ifdef S_ISFIFO
1238 else if(S_ISFIFO(mode))
1239 return UNIX_TYPE_FIFO;
1240 #endif
1241 #ifdef S_ISSOCK
1242 else if(S_ISSOCK(mode))
1243 return UNIX_TYPE_SOCKET;
1244 #endif
1246 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1247 return UNIX_TYPE_UNKNOWN;
1250 /****************************************************************************
1251 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1252 ****************************************************************************/
1254 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1256 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1257 const SMB_STRUCT_STAT *psbuf,
1258 uint32 perms,
1259 enum perm_type ptype,
1260 mode_t *ret_perms)
1262 mode_t ret = 0;
1264 if (perms == SMB_MODE_NO_CHANGE) {
1265 if (!VALID_STAT(*psbuf)) {
1266 return NT_STATUS_INVALID_PARAMETER;
1267 } else {
1268 *ret_perms = psbuf->st_ex_mode;
1269 return NT_STATUS_OK;
1273 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1274 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1275 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1276 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1277 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1278 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1279 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1280 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1281 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1282 #ifdef S_ISVTX
1283 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1284 #endif
1285 #ifdef S_ISGID
1286 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1287 #endif
1288 #ifdef S_ISUID
1289 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1290 #endif
1292 switch (ptype) {
1293 case PERM_NEW_FILE:
1294 /* Apply mode mask */
1295 ret &= lp_create_mask(SNUM(conn));
1296 /* Add in force bits */
1297 ret |= lp_force_create_mode(SNUM(conn));
1298 break;
1299 case PERM_NEW_DIR:
1300 ret &= lp_dir_mask(SNUM(conn));
1301 /* Add in force bits */
1302 ret |= lp_force_dir_mode(SNUM(conn));
1303 break;
1304 case PERM_EXISTING_FILE:
1305 /* Apply mode mask */
1306 ret &= lp_security_mask(SNUM(conn));
1307 /* Add in force bits */
1308 ret |= lp_force_security_mode(SNUM(conn));
1309 break;
1310 case PERM_EXISTING_DIR:
1311 /* Apply mode mask */
1312 ret &= lp_dir_security_mask(SNUM(conn));
1313 /* Add in force bits */
1314 ret |= lp_force_dir_security_mode(SNUM(conn));
1315 break;
1318 *ret_perms = ret;
1319 return NT_STATUS_OK;
1322 /****************************************************************************
1323 Needed to show the msdfs symlinks as directories. Modifies psbuf
1324 to be a directory if it's a msdfs link.
1325 ****************************************************************************/
1327 static bool check_msdfs_link(connection_struct *conn,
1328 const char *pathname,
1329 SMB_STRUCT_STAT *psbuf)
1331 int saved_errno = errno;
1332 if(lp_host_msdfs() &&
1333 lp_msdfs_root(SNUM(conn)) &&
1334 is_msdfs_link(conn, pathname, psbuf)) {
1336 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1337 "as a directory\n",
1338 pathname));
1339 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1340 errno = saved_errno;
1341 return true;
1343 errno = saved_errno;
1344 return false;
1348 /****************************************************************************
1349 Get a level dependent lanman2 dir entry.
1350 ****************************************************************************/
1352 struct smbd_dirptr_lanman2_state {
1353 connection_struct *conn;
1354 uint32_t info_level;
1355 bool check_mangled_names;
1356 bool has_wild;
1357 bool got_exact_match;
1360 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1361 void *private_data,
1362 const char *dname,
1363 const char *mask,
1364 char **_fname)
1366 struct smbd_dirptr_lanman2_state *state =
1367 (struct smbd_dirptr_lanman2_state *)private_data;
1368 bool ok;
1369 char mangled_name[13]; /* mangled 8.3 name. */
1370 bool got_match;
1371 const char *fname;
1373 /* Mangle fname if it's an illegal name. */
1374 if (mangle_must_mangle(dname, state->conn->params)) {
1375 ok = name_to_8_3(dname, mangled_name,
1376 true, state->conn->params);
1377 if (!ok) {
1378 return false;
1380 fname = mangled_name;
1381 } else {
1382 fname = dname;
1385 got_match = exact_match(state->has_wild,
1386 state->conn->case_sensitive,
1387 fname, mask);
1388 state->got_exact_match = got_match;
1389 if (!got_match) {
1390 got_match = mask_match(fname, mask,
1391 state->conn->case_sensitive);
1394 if(!got_match && state->check_mangled_names &&
1395 !mangle_is_8_3(fname, false, state->conn->params)) {
1397 * It turns out that NT matches wildcards against
1398 * both long *and* short names. This may explain some
1399 * of the wildcard wierdness from old DOS clients
1400 * that some people have been seeing.... JRA.
1402 /* Force the mangling into 8.3. */
1403 ok = name_to_8_3(fname, mangled_name,
1404 false, state->conn->params);
1405 if (!ok) {
1406 return false;
1409 got_match = exact_match(state->has_wild,
1410 state->conn->case_sensitive,
1411 mangled_name, mask);
1412 state->got_exact_match = got_match;
1413 if (!got_match) {
1414 got_match = mask_match(mangled_name, mask,
1415 state->conn->case_sensitive);
1419 if (!got_match) {
1420 return false;
1423 *_fname = talloc_strdup(ctx, fname);
1424 if (*_fname == NULL) {
1425 return false;
1428 return true;
1431 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1432 void *private_data,
1433 struct smb_filename *smb_fname,
1434 uint32_t *_mode)
1436 struct smbd_dirptr_lanman2_state *state =
1437 (struct smbd_dirptr_lanman2_state *)private_data;
1438 bool ms_dfs_link = false;
1439 uint32_t mode = 0;
1441 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1442 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1443 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1444 "Couldn't lstat [%s] (%s)\n",
1445 smb_fname_str_dbg(smb_fname),
1446 strerror(errno)));
1447 return false;
1449 } else if (!VALID_STAT(smb_fname->st) &&
1450 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1451 /* Needed to show the msdfs symlinks as
1452 * directories */
1454 ms_dfs_link = check_msdfs_link(state->conn,
1455 smb_fname->base_name,
1456 &smb_fname->st);
1457 if (!ms_dfs_link) {
1458 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1459 "Couldn't stat [%s] (%s)\n",
1460 smb_fname_str_dbg(smb_fname),
1461 strerror(errno)));
1462 return false;
1466 if (ms_dfs_link) {
1467 mode = dos_mode_msdfs(state->conn, smb_fname);
1468 } else {
1469 mode = dos_mode(state->conn, smb_fname);
1472 *_mode = mode;
1473 return true;
1476 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1477 connection_struct *conn,
1478 uint16_t flags2,
1479 uint32_t info_level,
1480 struct ea_list *name_list,
1481 bool check_mangled_names,
1482 bool requires_resume_key,
1483 uint32_t mode,
1484 const char *fname,
1485 const struct smb_filename *smb_fname,
1486 int space_remaining,
1487 uint8_t align,
1488 bool do_pad,
1489 char *base_data,
1490 char **ppdata,
1491 char *end_data,
1492 bool *out_of_space,
1493 uint64_t *last_entry_off)
1495 char *p, *q, *pdata = *ppdata;
1496 uint32_t reskey=0;
1497 uint64_t file_size = 0;
1498 uint64_t allocation_size = 0;
1499 uint64_t file_index = 0;
1500 uint32_t len;
1501 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1502 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1503 time_t c_date = (time_t)0;
1504 char *nameptr;
1505 char *last_entry_ptr;
1506 bool was_8_3;
1507 int off;
1508 int pad = 0;
1510 *out_of_space = false;
1512 ZERO_STRUCT(mdate_ts);
1513 ZERO_STRUCT(adate_ts);
1514 ZERO_STRUCT(create_date_ts);
1515 ZERO_STRUCT(cdate_ts);
1517 if (!(mode & aDIR)) {
1518 file_size = get_file_size_stat(&smb_fname->st);
1520 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1522 file_index = get_FileIndex(conn, &smb_fname->st);
1524 mdate_ts = smb_fname->st.st_ex_mtime;
1525 adate_ts = smb_fname->st.st_ex_atime;
1526 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1527 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1529 if (lp_dos_filetime_resolution(SNUM(conn))) {
1530 dos_filetime_timespec(&create_date_ts);
1531 dos_filetime_timespec(&mdate_ts);
1532 dos_filetime_timespec(&adate_ts);
1533 dos_filetime_timespec(&cdate_ts);
1536 create_date = convert_timespec_to_time_t(create_date_ts);
1537 mdate = convert_timespec_to_time_t(mdate_ts);
1538 adate = convert_timespec_to_time_t(adate_ts);
1539 c_date = convert_timespec_to_time_t(cdate_ts);
1541 /* align the record */
1542 SMB_ASSERT(align >= 1);
1544 off = (int)PTR_DIFF(pdata, base_data);
1545 pad = (off + (align-1)) & ~(align-1);
1546 pad -= off;
1548 if (pad && pad > space_remaining) {
1549 *out_of_space = true;
1550 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1551 "for padding (wanted %u, had %d)\n",
1552 (unsigned int)pad,
1553 space_remaining ));
1554 return false; /* Not finished - just out of space */
1557 off += pad;
1558 /* initialize padding to 0 */
1559 if (pad) {
1560 memset(pdata, 0, pad);
1562 space_remaining -= pad;
1564 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1565 space_remaining ));
1567 pdata += pad;
1568 p = pdata;
1569 last_entry_ptr = p;
1571 pad = 0;
1572 off = 0;
1574 switch (info_level) {
1575 case SMB_FIND_INFO_STANDARD:
1576 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1577 if(requires_resume_key) {
1578 SIVAL(p,0,reskey);
1579 p += 4;
1581 srv_put_dos_date2(p,0,create_date);
1582 srv_put_dos_date2(p,4,adate);
1583 srv_put_dos_date2(p,8,mdate);
1584 SIVAL(p,12,(uint32)file_size);
1585 SIVAL(p,16,(uint32)allocation_size);
1586 SSVAL(p,20,mode);
1587 p += 23;
1588 nameptr = p;
1589 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1590 p += ucs2_align(base_data, p, 0);
1592 len = srvstr_push(base_data, flags2, p,
1593 fname, PTR_DIFF(end_data, p),
1594 STR_TERMINATE);
1595 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1596 if (len > 2) {
1597 SCVAL(nameptr, -1, len - 2);
1598 } else {
1599 SCVAL(nameptr, -1, 0);
1601 } else {
1602 if (len > 1) {
1603 SCVAL(nameptr, -1, len - 1);
1604 } else {
1605 SCVAL(nameptr, -1, 0);
1608 p += len;
1609 break;
1611 case SMB_FIND_EA_SIZE:
1612 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1613 if (requires_resume_key) {
1614 SIVAL(p,0,reskey);
1615 p += 4;
1617 srv_put_dos_date2(p,0,create_date);
1618 srv_put_dos_date2(p,4,adate);
1619 srv_put_dos_date2(p,8,mdate);
1620 SIVAL(p,12,(uint32)file_size);
1621 SIVAL(p,16,(uint32)allocation_size);
1622 SSVAL(p,20,mode);
1624 unsigned int ea_size = estimate_ea_size(conn, NULL,
1625 smb_fname->base_name);
1626 SIVAL(p,22,ea_size); /* Extended attributes */
1628 p += 27;
1629 nameptr = p - 1;
1630 len = srvstr_push(base_data, flags2,
1631 p, fname, PTR_DIFF(end_data, p),
1632 STR_TERMINATE | STR_NOALIGN);
1633 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1634 if (len > 2) {
1635 len -= 2;
1636 } else {
1637 len = 0;
1639 } else {
1640 if (len > 1) {
1641 len -= 1;
1642 } else {
1643 len = 0;
1646 SCVAL(nameptr,0,len);
1647 p += len;
1648 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1649 break;
1651 case SMB_FIND_EA_LIST:
1653 struct ea_list *file_list = NULL;
1654 size_t ea_len = 0;
1656 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1657 if (!name_list) {
1658 return false;
1660 if (requires_resume_key) {
1661 SIVAL(p,0,reskey);
1662 p += 4;
1664 srv_put_dos_date2(p,0,create_date);
1665 srv_put_dos_date2(p,4,adate);
1666 srv_put_dos_date2(p,8,mdate);
1667 SIVAL(p,12,(uint32)file_size);
1668 SIVAL(p,16,(uint32)allocation_size);
1669 SSVAL(p,20,mode);
1670 p += 22; /* p now points to the EA area. */
1672 file_list = get_ea_list_from_file(ctx, conn, NULL,
1673 smb_fname->base_name,
1674 &ea_len);
1675 name_list = ea_list_union(name_list, file_list, &ea_len);
1677 /* We need to determine if this entry will fit in the space available. */
1678 /* Max string size is 255 bytes. */
1679 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1680 *out_of_space = true;
1681 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1682 "(wanted %u, had %d)\n",
1683 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1684 space_remaining ));
1685 return False; /* Not finished - just out of space */
1688 /* Push the ea_data followed by the name. */
1689 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1690 nameptr = p;
1691 len = srvstr_push(base_data, flags2,
1692 p + 1, fname, PTR_DIFF(end_data, p+1),
1693 STR_TERMINATE | STR_NOALIGN);
1694 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1695 if (len > 2) {
1696 len -= 2;
1697 } else {
1698 len = 0;
1700 } else {
1701 if (len > 1) {
1702 len -= 1;
1703 } else {
1704 len = 0;
1707 SCVAL(nameptr,0,len);
1708 p += len + 1;
1709 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1710 break;
1713 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1714 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1715 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1716 p += 4;
1717 SIVAL(p,0,reskey); p += 4;
1718 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1719 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1720 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1721 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1722 SOFF_T(p,0,file_size); p += 8;
1723 SOFF_T(p,0,allocation_size); p += 8;
1724 SIVAL(p,0,mode); p += 4;
1725 q = p; p += 4; /* q is placeholder for name length. */
1727 unsigned int ea_size = estimate_ea_size(conn, NULL,
1728 smb_fname->base_name);
1729 SIVAL(p,0,ea_size); /* Extended attributes */
1730 p += 4;
1732 /* Clear the short name buffer. This is
1733 * IMPORTANT as not doing so will trigger
1734 * a Win2k client bug. JRA.
1736 if (!was_8_3 && check_mangled_names) {
1737 char mangled_name[13]; /* mangled 8.3 name. */
1738 if (!name_to_8_3(fname,mangled_name,True,
1739 conn->params)) {
1740 /* Error - mangle failed ! */
1741 memset(mangled_name,'\0',12);
1743 mangled_name[12] = 0;
1744 len = srvstr_push(base_data, flags2,
1745 p+2, mangled_name, 24,
1746 STR_UPPER|STR_UNICODE);
1747 if (len < 24) {
1748 memset(p + 2 + len,'\0',24 - len);
1750 SSVAL(p, 0, len);
1751 } else {
1752 memset(p,'\0',26);
1754 p += 2 + 24;
1755 len = srvstr_push(base_data, flags2, p,
1756 fname, PTR_DIFF(end_data, p),
1757 STR_TERMINATE_ASCII);
1758 SIVAL(q,0,len);
1759 p += len;
1761 len = PTR_DIFF(p, pdata);
1762 pad = (len + (align-1)) & ~(align-1);
1764 * offset to the next entry, the caller
1765 * will overwrite it for the last entry
1766 * that's why we always include the padding
1768 SIVAL(pdata,0,pad);
1770 * set padding to zero
1772 if (do_pad) {
1773 memset(p, 0, pad - len);
1774 p = pdata + pad;
1775 } else {
1776 p = pdata + len;
1778 break;
1780 case SMB_FIND_FILE_DIRECTORY_INFO:
1781 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1782 p += 4;
1783 SIVAL(p,0,reskey); p += 4;
1784 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1785 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1786 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1787 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1788 SOFF_T(p,0,file_size); p += 8;
1789 SOFF_T(p,0,allocation_size); p += 8;
1790 SIVAL(p,0,mode); p += 4;
1791 len = srvstr_push(base_data, flags2,
1792 p + 4, fname, PTR_DIFF(end_data, p+4),
1793 STR_TERMINATE_ASCII);
1794 SIVAL(p,0,len);
1795 p += 4 + len;
1797 len = PTR_DIFF(p, pdata);
1798 pad = (len + (align-1)) & ~(align-1);
1800 * offset to the next entry, the caller
1801 * will overwrite it for the last entry
1802 * that's why we always include the padding
1804 SIVAL(pdata,0,pad);
1806 * set padding to zero
1808 if (do_pad) {
1809 memset(p, 0, pad - len);
1810 p = pdata + pad;
1811 } else {
1812 p = pdata + len;
1814 break;
1816 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1817 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1818 p += 4;
1819 SIVAL(p,0,reskey); p += 4;
1820 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1821 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1822 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1823 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1824 SOFF_T(p,0,file_size); p += 8;
1825 SOFF_T(p,0,allocation_size); p += 8;
1826 SIVAL(p,0,mode); p += 4;
1827 q = p; p += 4; /* q is placeholder for name length. */
1829 unsigned int ea_size = estimate_ea_size(conn, NULL,
1830 smb_fname->base_name);
1831 SIVAL(p,0,ea_size); /* Extended attributes */
1832 p +=4;
1834 len = srvstr_push(base_data, flags2, p,
1835 fname, PTR_DIFF(end_data, p),
1836 STR_TERMINATE_ASCII);
1837 SIVAL(q, 0, len);
1838 p += len;
1840 len = PTR_DIFF(p, pdata);
1841 pad = (len + (align-1)) & ~(align-1);
1843 * offset to the next entry, the caller
1844 * will overwrite it for the last entry
1845 * that's why we always include the padding
1847 SIVAL(pdata,0,pad);
1849 * set padding to zero
1851 if (do_pad) {
1852 memset(p, 0, pad - len);
1853 p = pdata + pad;
1854 } else {
1855 p = pdata + len;
1857 break;
1859 case SMB_FIND_FILE_NAMES_INFO:
1860 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1861 p += 4;
1862 SIVAL(p,0,reskey); p += 4;
1863 p += 4;
1864 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1865 acl on a dir (tridge) */
1866 len = srvstr_push(base_data, flags2, p,
1867 fname, PTR_DIFF(end_data, p),
1868 STR_TERMINATE_ASCII);
1869 SIVAL(p, -4, len);
1870 p += len;
1872 len = PTR_DIFF(p, pdata);
1873 pad = (len + (align-1)) & ~(align-1);
1875 * offset to the next entry, the caller
1876 * will overwrite it for the last entry
1877 * that's why we always include the padding
1879 SIVAL(pdata,0,pad);
1881 * set padding to zero
1883 if (do_pad) {
1884 memset(p, 0, pad - len);
1885 p = pdata + pad;
1886 } else {
1887 p = pdata + len;
1889 break;
1891 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1892 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1893 p += 4;
1894 SIVAL(p,0,reskey); p += 4;
1895 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1896 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1897 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1898 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1899 SOFF_T(p,0,file_size); p += 8;
1900 SOFF_T(p,0,allocation_size); p += 8;
1901 SIVAL(p,0,mode); p += 4;
1902 q = p; p += 4; /* q is placeholder for name length. */
1904 unsigned int ea_size = estimate_ea_size(conn, NULL,
1905 smb_fname->base_name);
1906 SIVAL(p,0,ea_size); /* Extended attributes */
1907 p +=4;
1909 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1910 SBVAL(p,0,file_index); p += 8;
1911 len = srvstr_push(base_data, flags2, p,
1912 fname, PTR_DIFF(end_data, p),
1913 STR_TERMINATE_ASCII);
1914 SIVAL(q, 0, len);
1915 p += len;
1917 len = PTR_DIFF(p, pdata);
1918 pad = (len + (align-1)) & ~(align-1);
1920 * offset to the next entry, the caller
1921 * will overwrite it for the last entry
1922 * that's why we always include the padding
1924 SIVAL(pdata,0,pad);
1926 * set padding to zero
1928 if (do_pad) {
1929 memset(p, 0, pad - len);
1930 p = pdata + pad;
1931 } else {
1932 p = pdata + len;
1934 break;
1936 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1937 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1938 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1939 p += 4;
1940 SIVAL(p,0,reskey); p += 4;
1941 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1942 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1943 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1944 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1945 SOFF_T(p,0,file_size); p += 8;
1946 SOFF_T(p,0,allocation_size); p += 8;
1947 SIVAL(p,0,mode); p += 4;
1948 q = p; p += 4; /* q is placeholder for name length */
1950 unsigned int ea_size = estimate_ea_size(conn, NULL,
1951 smb_fname->base_name);
1952 SIVAL(p,0,ea_size); /* Extended attributes */
1953 p +=4;
1955 /* Clear the short name buffer. This is
1956 * IMPORTANT as not doing so will trigger
1957 * a Win2k client bug. JRA.
1959 if (!was_8_3 && check_mangled_names) {
1960 char mangled_name[13]; /* mangled 8.3 name. */
1961 if (!name_to_8_3(fname,mangled_name,True,
1962 conn->params)) {
1963 /* Error - mangle failed ! */
1964 memset(mangled_name,'\0',12);
1966 mangled_name[12] = 0;
1967 len = srvstr_push(base_data, flags2,
1968 p+2, mangled_name, 24,
1969 STR_UPPER|STR_UNICODE);
1970 SSVAL(p, 0, len);
1971 if (len < 24) {
1972 memset(p + 2 + len,'\0',24 - len);
1974 SSVAL(p, 0, len);
1975 } else {
1976 memset(p,'\0',26);
1978 p += 26;
1979 SSVAL(p,0,0); p += 2; /* Reserved ? */
1980 SBVAL(p,0,file_index); p += 8;
1981 len = srvstr_push(base_data, flags2, p,
1982 fname, PTR_DIFF(end_data, p),
1983 STR_TERMINATE_ASCII);
1984 SIVAL(q,0,len);
1985 p += len;
1987 len = PTR_DIFF(p, pdata);
1988 pad = (len + (align-1)) & ~(align-1);
1990 * offset to the next entry, the caller
1991 * will overwrite it for the last entry
1992 * that's why we always include the padding
1994 SIVAL(pdata,0,pad);
1996 * set padding to zero
1998 if (do_pad) {
1999 memset(p, 0, pad - len);
2000 p = pdata + pad;
2001 } else {
2002 p = pdata + len;
2004 break;
2006 /* CIFS UNIX Extension. */
2008 case SMB_FIND_FILE_UNIX:
2009 case SMB_FIND_FILE_UNIX_INFO2:
2010 p+= 4;
2011 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2013 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2015 if (info_level == SMB_FIND_FILE_UNIX) {
2016 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2017 p = store_file_unix_basic(conn, p,
2018 NULL, &smb_fname->st);
2019 len = srvstr_push(base_data, flags2, p,
2020 fname, PTR_DIFF(end_data, p),
2021 STR_TERMINATE);
2022 } else {
2023 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2024 p = store_file_unix_basic_info2(conn, p,
2025 NULL, &smb_fname->st);
2026 nameptr = p;
2027 p += 4;
2028 len = srvstr_push(base_data, flags2, p, fname,
2029 PTR_DIFF(end_data, p), 0);
2030 SIVAL(nameptr, 0, len);
2033 p += len;
2035 len = PTR_DIFF(p, pdata);
2036 pad = (len + (align-1)) & ~(align-1);
2038 * offset to the next entry, the caller
2039 * will overwrite it for the last entry
2040 * that's why we always include the padding
2042 SIVAL(pdata,0,pad);
2044 * set padding to zero
2046 if (do_pad) {
2047 memset(p, 0, pad - len);
2048 p = pdata + pad;
2049 } else {
2050 p = pdata + len;
2052 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2054 break;
2056 default:
2057 return false;
2060 if (PTR_DIFF(p,pdata) > space_remaining) {
2061 *out_of_space = true;
2062 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2063 "(wanted %u, had %d)\n",
2064 (unsigned int)PTR_DIFF(p,pdata),
2065 space_remaining ));
2066 return false; /* Not finished - just out of space */
2069 /* Setup the last entry pointer, as an offset from base_data */
2070 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2071 /* Advance the data pointer to the next slot */
2072 *ppdata = p;
2074 return true;
2077 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2078 connection_struct *conn,
2079 struct dptr_struct *dirptr,
2080 uint16 flags2,
2081 const char *path_mask,
2082 uint32 dirtype,
2083 int info_level,
2084 int requires_resume_key,
2085 bool dont_descend,
2086 bool ask_sharemode,
2087 uint8_t align,
2088 bool do_pad,
2089 char **ppdata,
2090 char *base_data,
2091 char *end_data,
2092 int space_remaining,
2093 bool *out_of_space,
2094 bool *got_exact_match,
2095 int *_last_entry_off,
2096 struct ea_list *name_list)
2098 const char *p;
2099 const char *mask = NULL;
2100 long prev_dirpos = 0;
2101 uint32_t mode = 0;
2102 char *fname = NULL;
2103 struct smb_filename *smb_fname = NULL;
2104 struct smbd_dirptr_lanman2_state state;
2105 bool ok;
2106 uint64_t last_entry_off = 0;
2108 ZERO_STRUCT(state);
2109 state.conn = conn;
2110 state.info_level = info_level;
2111 state.check_mangled_names = lp_manglednames(conn->params);
2112 state.has_wild = dptr_has_wild(dirptr);
2113 state.got_exact_match = false;
2115 *out_of_space = false;
2116 *got_exact_match = false;
2118 p = strrchr_m(path_mask,'/');
2119 if(p != NULL) {
2120 if(p[1] == '\0') {
2121 mask = "*.*";
2122 } else {
2123 mask = p+1;
2125 } else {
2126 mask = path_mask;
2129 ok = smbd_dirptr_get_entry(ctx,
2130 dirptr,
2131 mask,
2132 dirtype,
2133 dont_descend,
2134 ask_sharemode,
2135 smbd_dirptr_lanman2_match_fn,
2136 smbd_dirptr_lanman2_mode_fn,
2137 &state,
2138 &fname,
2139 &smb_fname,
2140 &mode,
2141 &prev_dirpos);
2142 if (!ok) {
2143 return false;
2146 *got_exact_match = state.got_exact_match;
2148 ok = smbd_marshall_dir_entry(ctx,
2149 conn,
2150 flags2,
2151 info_level,
2152 name_list,
2153 state.check_mangled_names,
2154 requires_resume_key,
2155 mode,
2156 fname,
2157 smb_fname,
2158 space_remaining,
2159 align,
2160 do_pad,
2161 base_data,
2162 ppdata,
2163 end_data,
2164 out_of_space,
2165 &last_entry_off);
2166 TALLOC_FREE(fname);
2167 TALLOC_FREE(smb_fname);
2168 if (*out_of_space) {
2169 dptr_SeekDir(dirptr, prev_dirpos);
2170 return false;
2172 if (!ok) {
2173 return false;
2176 *_last_entry_off = last_entry_off;
2177 return true;
2180 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2181 connection_struct *conn,
2182 struct dptr_struct *dirptr,
2183 uint16 flags2,
2184 const char *path_mask,
2185 uint32 dirtype,
2186 int info_level,
2187 bool requires_resume_key,
2188 bool dont_descend,
2189 bool ask_sharemode,
2190 char **ppdata,
2191 char *base_data,
2192 char *end_data,
2193 int space_remaining,
2194 bool *out_of_space,
2195 bool *got_exact_match,
2196 int *last_entry_off,
2197 struct ea_list *name_list)
2199 uint8_t align = 4;
2200 const bool do_pad = true;
2202 if (info_level >= 1 && info_level <= 3) {
2203 /* No alignment on earlier info levels. */
2204 align = 1;
2207 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2208 path_mask, dirtype, info_level,
2209 requires_resume_key, dont_descend, ask_sharemode,
2210 align, do_pad,
2211 ppdata, base_data, end_data,
2212 space_remaining,
2213 out_of_space, got_exact_match,
2214 last_entry_off, name_list);
2217 /****************************************************************************
2218 Reply to a TRANS2_FINDFIRST.
2219 ****************************************************************************/
2221 static void call_trans2findfirst(connection_struct *conn,
2222 struct smb_request *req,
2223 char **pparams, int total_params,
2224 char **ppdata, int total_data,
2225 unsigned int max_data_bytes)
2227 /* We must be careful here that we don't return more than the
2228 allowed number of data bytes. If this means returning fewer than
2229 maxentries then so be it. We assume that the redirector has
2230 enough room for the fixed number of parameter bytes it has
2231 requested. */
2232 struct smb_filename *smb_dname = NULL;
2233 char *params = *pparams;
2234 char *pdata = *ppdata;
2235 char *data_end;
2236 uint32 dirtype;
2237 int maxentries;
2238 uint16 findfirst_flags;
2239 bool close_after_first;
2240 bool close_if_end;
2241 bool requires_resume_key;
2242 int info_level;
2243 char *directory = NULL;
2244 char *mask = NULL;
2245 char *p;
2246 int last_entry_off=0;
2247 int dptr_num = -1;
2248 int numentries = 0;
2249 int i;
2250 bool finished = False;
2251 bool dont_descend = False;
2252 bool out_of_space = False;
2253 int space_remaining;
2254 bool mask_contains_wcard = False;
2255 struct ea_list *ea_list = NULL;
2256 NTSTATUS ntstatus = NT_STATUS_OK;
2257 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2258 TALLOC_CTX *ctx = talloc_tos();
2259 struct dptr_struct *dirptr = NULL;
2260 struct smbd_server_connection *sconn = smbd_server_conn;
2262 if (total_params < 13) {
2263 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2264 goto out;
2267 dirtype = SVAL(params,0);
2268 maxentries = SVAL(params,2);
2269 findfirst_flags = SVAL(params,4);
2270 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2271 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2272 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2273 info_level = SVAL(params,6);
2275 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2276 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2277 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2278 info_level, max_data_bytes));
2280 if (!maxentries) {
2281 /* W2K3 seems to treat zero as 1. */
2282 maxentries = 1;
2285 switch (info_level) {
2286 case SMB_FIND_INFO_STANDARD:
2287 case SMB_FIND_EA_SIZE:
2288 case SMB_FIND_EA_LIST:
2289 case SMB_FIND_FILE_DIRECTORY_INFO:
2290 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2291 case SMB_FIND_FILE_NAMES_INFO:
2292 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2293 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2294 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2295 break;
2296 case SMB_FIND_FILE_UNIX:
2297 case SMB_FIND_FILE_UNIX_INFO2:
2298 /* Always use filesystem for UNIX mtime query. */
2299 ask_sharemode = false;
2300 if (!lp_unix_extensions()) {
2301 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2302 goto out;
2304 break;
2305 default:
2306 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2307 goto out;
2310 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2311 params+12, total_params - 12,
2312 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2313 if (!NT_STATUS_IS_OK(ntstatus)) {
2314 reply_nterror(req, ntstatus);
2315 goto out;
2318 ntstatus = filename_convert(ctx, conn,
2319 req->flags2 & FLAGS2_DFS_PATHNAMES,
2320 directory,
2321 (UCF_SAVE_LCOMP |
2322 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2323 &mask_contains_wcard,
2324 &smb_dname);
2325 if (!NT_STATUS_IS_OK(ntstatus)) {
2326 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2327 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2328 ERRSRV, ERRbadpath);
2329 goto out;
2331 reply_nterror(req, ntstatus);
2332 goto out;
2335 mask = smb_dname->original_lcomp;
2337 directory = smb_dname->base_name;
2339 p = strrchr_m(directory,'/');
2340 if(p == NULL) {
2341 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2342 if((directory[0] == '.') && (directory[1] == '\0')) {
2343 mask = talloc_strdup(ctx,"*");
2344 if (!mask) {
2345 reply_nterror(req, NT_STATUS_NO_MEMORY);
2346 goto out;
2348 mask_contains_wcard = True;
2350 directory = talloc_strdup(talloc_tos(), "./");
2351 if (!directory) {
2352 reply_nterror(req, NT_STATUS_NO_MEMORY);
2353 goto out;
2355 } else {
2356 *p = 0;
2359 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2361 if (info_level == SMB_FIND_EA_LIST) {
2362 uint32 ea_size;
2364 if (total_data < 4) {
2365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2366 goto out;
2369 ea_size = IVAL(pdata,0);
2370 if (ea_size != total_data) {
2371 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2372 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2373 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2374 goto out;
2377 if (!lp_ea_support(SNUM(conn))) {
2378 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2379 goto out;
2382 /* Pull out the list of names. */
2383 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2384 if (!ea_list) {
2385 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2386 goto out;
2390 *ppdata = (char *)SMB_REALLOC(
2391 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2392 if(*ppdata == NULL ) {
2393 reply_nterror(req, NT_STATUS_NO_MEMORY);
2394 goto out;
2396 pdata = *ppdata;
2397 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2399 /* Realloc the params space */
2400 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2401 if (*pparams == NULL) {
2402 reply_nterror(req, NT_STATUS_NO_MEMORY);
2403 goto out;
2405 params = *pparams;
2407 /* Save the wildcard match and attribs we are using on this directory -
2408 needed as lanman2 assumes these are being saved between calls */
2410 ntstatus = dptr_create(conn,
2411 directory,
2412 False,
2413 True,
2414 req->smbpid,
2415 mask,
2416 mask_contains_wcard,
2417 dirtype,
2418 &dirptr);
2420 if (!NT_STATUS_IS_OK(ntstatus)) {
2421 reply_nterror(req, ntstatus);
2422 goto out;
2425 dptr_num = dptr_dnum(dirptr);
2426 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2428 /* Initialize per TRANS2_FIND_FIRST operation data */
2429 dptr_init_search_op(dirptr);
2431 /* We don't need to check for VOL here as this is returned by
2432 a different TRANS2 call. */
2434 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2435 directory,lp_dontdescend(SNUM(conn))));
2436 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2437 dont_descend = True;
2439 p = pdata;
2440 space_remaining = max_data_bytes;
2441 out_of_space = False;
2443 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2444 bool got_exact_match = False;
2446 /* this is a heuristic to avoid seeking the dirptr except when
2447 absolutely necessary. It allows for a filename of about 40 chars */
2448 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2449 out_of_space = True;
2450 finished = False;
2451 } else {
2452 finished = !get_lanman2_dir_entry(ctx,
2453 conn,
2454 dirptr,
2455 req->flags2,
2456 mask,dirtype,info_level,
2457 requires_resume_key,dont_descend,
2458 ask_sharemode,
2459 &p,pdata,data_end,
2460 space_remaining, &out_of_space,
2461 &got_exact_match,
2462 &last_entry_off, ea_list);
2465 if (finished && out_of_space)
2466 finished = False;
2468 if (!finished && !out_of_space)
2469 numentries++;
2472 * As an optimisation if we know we aren't looking
2473 * for a wildcard name (ie. the name matches the wildcard exactly)
2474 * then we can finish on any (first) match.
2475 * This speeds up large directory searches. JRA.
2478 if(got_exact_match)
2479 finished = True;
2481 /* Ensure space_remaining never goes -ve. */
2482 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2483 space_remaining = 0;
2484 out_of_space = true;
2485 } else {
2486 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2490 /* Check if we can close the dirptr */
2491 if(close_after_first || (finished && close_if_end)) {
2492 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2493 dptr_close(sconn, &dptr_num);
2497 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2498 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2499 * the protocol level is less than NT1. Tested with smbclient. JRA.
2500 * This should fix the OS/2 client bug #2335.
2503 if(numentries == 0) {
2504 dptr_close(sconn, &dptr_num);
2505 if (get_Protocol() < PROTOCOL_NT1) {
2506 reply_force_doserror(req, ERRDOS, ERRnofiles);
2507 goto out;
2508 } else {
2509 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2510 ERRDOS, ERRbadfile);
2511 goto out;
2515 /* At this point pdata points to numentries directory entries. */
2517 /* Set up the return parameter block */
2518 SSVAL(params,0,dptr_num);
2519 SSVAL(params,2,numentries);
2520 SSVAL(params,4,finished);
2521 SSVAL(params,6,0); /* Never an EA error */
2522 SSVAL(params,8,last_entry_off);
2524 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2525 max_data_bytes);
2527 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2528 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2529 if (!directory) {
2530 reply_nterror(req, NT_STATUS_NO_MEMORY);
2534 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2535 smb_fn_name(req->cmd),
2536 mask, directory, dirtype, numentries ) );
2539 * Force a name mangle here to ensure that the
2540 * mask as an 8.3 name is top of the mangled cache.
2541 * The reasons for this are subtle. Don't remove
2542 * this code unless you know what you are doing
2543 * (see PR#13758). JRA.
2546 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2547 char mangled_name[13];
2548 name_to_8_3(mask, mangled_name, True, conn->params);
2550 out:
2551 TALLOC_FREE(smb_dname);
2552 return;
2555 /****************************************************************************
2556 Reply to a TRANS2_FINDNEXT.
2557 ****************************************************************************/
2559 static void call_trans2findnext(connection_struct *conn,
2560 struct smb_request *req,
2561 char **pparams, int total_params,
2562 char **ppdata, int total_data,
2563 unsigned int max_data_bytes)
2565 /* We must be careful here that we don't return more than the
2566 allowed number of data bytes. If this means returning fewer than
2567 maxentries then so be it. We assume that the redirector has
2568 enough room for the fixed number of parameter bytes it has
2569 requested. */
2570 char *params = *pparams;
2571 char *pdata = *ppdata;
2572 char *data_end;
2573 int dptr_num;
2574 int maxentries;
2575 uint16 info_level;
2576 uint32 resume_key;
2577 uint16 findnext_flags;
2578 bool close_after_request;
2579 bool close_if_end;
2580 bool requires_resume_key;
2581 bool continue_bit;
2582 bool mask_contains_wcard = False;
2583 char *resume_name = NULL;
2584 const char *mask = NULL;
2585 const char *directory = NULL;
2586 char *p = NULL;
2587 uint16 dirtype;
2588 int numentries = 0;
2589 int i, last_entry_off=0;
2590 bool finished = False;
2591 bool dont_descend = False;
2592 bool out_of_space = False;
2593 int space_remaining;
2594 struct ea_list *ea_list = NULL;
2595 NTSTATUS ntstatus = NT_STATUS_OK;
2596 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2597 TALLOC_CTX *ctx = talloc_tos();
2598 struct dptr_struct *dirptr;
2599 struct smbd_server_connection *sconn = smbd_server_conn;
2601 if (total_params < 13) {
2602 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2603 return;
2606 dptr_num = SVAL(params,0);
2607 maxentries = SVAL(params,2);
2608 info_level = SVAL(params,4);
2609 resume_key = IVAL(params,6);
2610 findnext_flags = SVAL(params,10);
2611 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2612 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2613 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2614 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2616 if (!continue_bit) {
2617 /* We only need resume_name if continue_bit is zero. */
2618 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2619 params+12,
2620 total_params - 12, STR_TERMINATE, &ntstatus,
2621 &mask_contains_wcard);
2622 if (!NT_STATUS_IS_OK(ntstatus)) {
2623 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2624 complain (it thinks we're asking for the directory above the shared
2625 path or an invalid name). Catch this as the resume name is only compared, never used in
2626 a file access. JRA. */
2627 srvstr_pull_talloc(ctx, params, req->flags2,
2628 &resume_name, params+12,
2629 total_params - 12,
2630 STR_TERMINATE);
2632 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2633 reply_nterror(req, ntstatus);
2634 return;
2639 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2640 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2641 resume_key = %d resume name = %s continue=%d level = %d\n",
2642 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2643 requires_resume_key, resume_key,
2644 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2646 if (!maxentries) {
2647 /* W2K3 seems to treat zero as 1. */
2648 maxentries = 1;
2651 switch (info_level) {
2652 case SMB_FIND_INFO_STANDARD:
2653 case SMB_FIND_EA_SIZE:
2654 case SMB_FIND_EA_LIST:
2655 case SMB_FIND_FILE_DIRECTORY_INFO:
2656 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2657 case SMB_FIND_FILE_NAMES_INFO:
2658 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2659 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2660 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2661 break;
2662 case SMB_FIND_FILE_UNIX:
2663 case SMB_FIND_FILE_UNIX_INFO2:
2664 /* Always use filesystem for UNIX mtime query. */
2665 ask_sharemode = false;
2666 if (!lp_unix_extensions()) {
2667 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2668 return;
2670 break;
2671 default:
2672 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2673 return;
2676 if (info_level == SMB_FIND_EA_LIST) {
2677 uint32 ea_size;
2679 if (total_data < 4) {
2680 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2681 return;
2684 ea_size = IVAL(pdata,0);
2685 if (ea_size != total_data) {
2686 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2687 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2688 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2689 return;
2692 if (!lp_ea_support(SNUM(conn))) {
2693 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2694 return;
2697 /* Pull out the list of names. */
2698 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2699 if (!ea_list) {
2700 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2701 return;
2705 *ppdata = (char *)SMB_REALLOC(
2706 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2707 if(*ppdata == NULL) {
2708 reply_nterror(req, NT_STATUS_NO_MEMORY);
2709 return;
2712 pdata = *ppdata;
2713 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2715 /* Realloc the params space */
2716 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2717 if(*pparams == NULL ) {
2718 reply_nterror(req, NT_STATUS_NO_MEMORY);
2719 return;
2722 params = *pparams;
2724 /* Check that the dptr is valid */
2725 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2726 reply_nterror(req, STATUS_NO_MORE_FILES);
2727 return;
2730 directory = dptr_path(sconn, dptr_num);
2732 /* Get the wildcard mask from the dptr */
2733 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2734 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2735 reply_nterror(req, STATUS_NO_MORE_FILES);
2736 return;
2739 mask = p;
2741 /* Get the attr mask from the dptr */
2742 dirtype = dptr_attr(sconn, dptr_num);
2744 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2745 dptr_num, mask, dirtype,
2746 (long)dirptr,
2747 dptr_TellDir(dirptr)));
2749 /* Initialize per TRANS2_FIND_NEXT operation data */
2750 dptr_init_search_op(dirptr);
2752 /* We don't need to check for VOL here as this is returned by
2753 a different TRANS2 call. */
2755 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2756 directory,lp_dontdescend(SNUM(conn))));
2757 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2758 dont_descend = True;
2760 p = pdata;
2761 space_remaining = max_data_bytes;
2762 out_of_space = False;
2765 * Seek to the correct position. We no longer use the resume key but
2766 * depend on the last file name instead.
2769 if(!continue_bit && resume_name && *resume_name) {
2770 SMB_STRUCT_STAT st;
2772 long current_pos = 0;
2774 * Remember, name_to_8_3 is called by
2775 * get_lanman2_dir_entry(), so the resume name
2776 * could be mangled. Ensure we check the unmangled name.
2779 if (mangle_is_mangled(resume_name, conn->params)) {
2780 char *new_resume_name = NULL;
2781 mangle_lookup_name_from_8_3(ctx,
2782 resume_name,
2783 &new_resume_name,
2784 conn->params);
2785 if (new_resume_name) {
2786 resume_name = new_resume_name;
2791 * Fix for NT redirector problem triggered by resume key indexes
2792 * changing between directory scans. We now return a resume key of 0
2793 * and instead look for the filename to continue from (also given
2794 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2795 * findfirst/findnext (as is usual) then the directory pointer
2796 * should already be at the correct place.
2799 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2800 } /* end if resume_name && !continue_bit */
2802 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2803 bool got_exact_match = False;
2805 /* this is a heuristic to avoid seeking the dirptr except when
2806 absolutely necessary. It allows for a filename of about 40 chars */
2807 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2808 out_of_space = True;
2809 finished = False;
2810 } else {
2811 finished = !get_lanman2_dir_entry(ctx,
2812 conn,
2813 dirptr,
2814 req->flags2,
2815 mask,dirtype,info_level,
2816 requires_resume_key,dont_descend,
2817 ask_sharemode,
2818 &p,pdata,data_end,
2819 space_remaining, &out_of_space,
2820 &got_exact_match,
2821 &last_entry_off, ea_list);
2824 if (finished && out_of_space)
2825 finished = False;
2827 if (!finished && !out_of_space)
2828 numentries++;
2831 * As an optimisation if we know we aren't looking
2832 * for a wildcard name (ie. the name matches the wildcard exactly)
2833 * then we can finish on any (first) match.
2834 * This speeds up large directory searches. JRA.
2837 if(got_exact_match)
2838 finished = True;
2840 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2843 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2844 smb_fn_name(req->cmd),
2845 mask, directory, dirtype, numentries ) );
2847 /* Check if we can close the dirptr */
2848 if(close_after_request || (finished && close_if_end)) {
2849 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2850 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2853 /* Set up the return parameter block */
2854 SSVAL(params,0,numentries);
2855 SSVAL(params,2,finished);
2856 SSVAL(params,4,0); /* Never an EA error */
2857 SSVAL(params,6,last_entry_off);
2859 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2860 max_data_bytes);
2862 return;
2865 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2867 E_md4hash(lp_servicename(SNUM(conn)),objid);
2868 return objid;
2871 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2873 SMB_ASSERT(extended_info != NULL);
2875 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2876 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2877 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2878 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2879 #ifdef SAMBA_VERSION_REVISION
2880 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2881 #endif
2882 extended_info->samba_subversion = 0;
2883 #ifdef SAMBA_VERSION_RC_RELEASE
2884 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2885 #else
2886 #ifdef SAMBA_VERSION_PRE_RELEASE
2887 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2888 #endif
2889 #endif
2890 #ifdef SAMBA_VERSION_VENDOR_PATCH
2891 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2892 #endif
2893 extended_info->samba_gitcommitdate = 0;
2894 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2895 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2896 #endif
2898 memset(extended_info->samba_version_string, 0,
2899 sizeof(extended_info->samba_version_string));
2901 snprintf (extended_info->samba_version_string,
2902 sizeof(extended_info->samba_version_string),
2903 "%s", samba_version_string());
2906 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2907 TALLOC_CTX *mem_ctx,
2908 uint16_t info_level,
2909 uint16_t flags2,
2910 unsigned int max_data_bytes,
2911 char **ppdata,
2912 int *ret_data_len)
2914 char *pdata, *end_data;
2915 int data_len = 0, len;
2916 const char *vname = volume_label(SNUM(conn));
2917 int snum = SNUM(conn);
2918 char *fstype = lp_fstype(SNUM(conn));
2919 uint32 additional_flags = 0;
2920 struct smb_filename smb_fname_dot;
2921 SMB_STRUCT_STAT st;
2923 if (IS_IPC(conn)) {
2924 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2925 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2926 "info level (0x%x) on IPC$.\n",
2927 (unsigned int)info_level));
2928 return NT_STATUS_ACCESS_DENIED;
2932 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2934 ZERO_STRUCT(smb_fname_dot);
2935 smb_fname_dot.base_name = discard_const_p(char, ".");
2937 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2938 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2939 return map_nt_error_from_unix(errno);
2942 st = smb_fname_dot.st;
2944 *ppdata = (char *)SMB_REALLOC(
2945 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2946 if (*ppdata == NULL) {
2947 return NT_STATUS_NO_MEMORY;
2950 pdata = *ppdata;
2951 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2952 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2954 switch (info_level) {
2955 case SMB_INFO_ALLOCATION:
2957 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2958 data_len = 18;
2959 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2960 return map_nt_error_from_unix(errno);
2963 block_size = lp_block_size(snum);
2964 if (bsize < block_size) {
2965 uint64_t factor = block_size/bsize;
2966 bsize = block_size;
2967 dsize /= factor;
2968 dfree /= factor;
2970 if (bsize > block_size) {
2971 uint64_t factor = bsize/block_size;
2972 bsize = block_size;
2973 dsize *= factor;
2974 dfree *= factor;
2976 bytes_per_sector = 512;
2977 sectors_per_unit = bsize/bytes_per_sector;
2979 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2980 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2981 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2983 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2984 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2985 SIVAL(pdata,l1_cUnit,dsize);
2986 SIVAL(pdata,l1_cUnitAvail,dfree);
2987 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2988 break;
2991 case SMB_INFO_VOLUME:
2992 /* Return volume name */
2994 * Add volume serial number - hash of a combination of
2995 * the called hostname and the service name.
2997 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2999 * Win2k3 and previous mess this up by sending a name length
3000 * one byte short. I believe only older clients (OS/2 Win9x) use
3001 * this call so try fixing this by adding a terminating null to
3002 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3004 len = srvstr_push(
3005 pdata, flags2,
3006 pdata+l2_vol_szVolLabel, vname,
3007 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3008 STR_NOALIGN|STR_TERMINATE);
3009 SCVAL(pdata,l2_vol_cch,len);
3010 data_len = l2_vol_szVolLabel + len;
3011 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3012 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3013 len, vname));
3014 break;
3016 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3017 case SMB_FS_ATTRIBUTE_INFORMATION:
3019 additional_flags = 0;
3020 #if defined(HAVE_SYS_QUOTAS)
3021 additional_flags |= FILE_VOLUME_QUOTAS;
3022 #endif
3024 if(lp_nt_acl_support(SNUM(conn))) {
3025 additional_flags |= FILE_PERSISTENT_ACLS;
3028 /* Capabilities are filled in at connection time through STATVFS call */
3029 additional_flags |= conn->fs_capabilities;
3030 additional_flags |= lp_parm_int(conn->params->service,
3031 "share", "fake_fscaps",
3034 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3035 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3036 additional_flags); /* FS ATTRIBUTES */
3038 SIVAL(pdata,4,255); /* Max filename component length */
3039 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3040 and will think we can't do long filenames */
3041 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3042 PTR_DIFF(end_data, pdata+12),
3043 STR_UNICODE);
3044 SIVAL(pdata,8,len);
3045 data_len = 12 + len;
3046 break;
3048 case SMB_QUERY_FS_LABEL_INFO:
3049 case SMB_FS_LABEL_INFORMATION:
3050 len = srvstr_push(pdata, flags2, pdata+4, vname,
3051 PTR_DIFF(end_data, pdata+4), 0);
3052 data_len = 4 + len;
3053 SIVAL(pdata,0,len);
3054 break;
3056 case SMB_QUERY_FS_VOLUME_INFO:
3057 case SMB_FS_VOLUME_INFORMATION:
3060 * Add volume serial number - hash of a combination of
3061 * the called hostname and the service name.
3063 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3064 (str_checksum(get_local_machine_name())<<16));
3066 /* Max label len is 32 characters. */
3067 len = srvstr_push(pdata, flags2, pdata+18, vname,
3068 PTR_DIFF(end_data, pdata+18),
3069 STR_UNICODE);
3070 SIVAL(pdata,12,len);
3071 data_len = 18+len;
3073 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3074 (int)strlen(vname),vname, lp_servicename(snum)));
3075 break;
3077 case SMB_QUERY_FS_SIZE_INFO:
3078 case SMB_FS_SIZE_INFORMATION:
3080 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3081 data_len = 24;
3082 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3083 return map_nt_error_from_unix(errno);
3085 block_size = lp_block_size(snum);
3086 if (bsize < block_size) {
3087 uint64_t factor = block_size/bsize;
3088 bsize = block_size;
3089 dsize /= factor;
3090 dfree /= factor;
3092 if (bsize > block_size) {
3093 uint64_t factor = bsize/block_size;
3094 bsize = block_size;
3095 dsize *= factor;
3096 dfree *= factor;
3098 bytes_per_sector = 512;
3099 sectors_per_unit = bsize/bytes_per_sector;
3100 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3101 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3102 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3103 SBIG_UINT(pdata,0,dsize);
3104 SBIG_UINT(pdata,8,dfree);
3105 SIVAL(pdata,16,sectors_per_unit);
3106 SIVAL(pdata,20,bytes_per_sector);
3107 break;
3110 case SMB_FS_FULL_SIZE_INFORMATION:
3112 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3113 data_len = 32;
3114 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3115 return map_nt_error_from_unix(errno);
3117 block_size = lp_block_size(snum);
3118 if (bsize < block_size) {
3119 uint64_t factor = block_size/bsize;
3120 bsize = block_size;
3121 dsize /= factor;
3122 dfree /= factor;
3124 if (bsize > block_size) {
3125 uint64_t factor = bsize/block_size;
3126 bsize = block_size;
3127 dsize *= factor;
3128 dfree *= factor;
3130 bytes_per_sector = 512;
3131 sectors_per_unit = bsize/bytes_per_sector;
3132 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3133 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3134 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3135 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3136 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3137 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3138 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3139 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3140 break;
3143 case SMB_QUERY_FS_DEVICE_INFO:
3144 case SMB_FS_DEVICE_INFORMATION:
3146 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3148 if (!CAN_WRITE(conn)) {
3149 characteristics |= FILE_READ_ONLY_DEVICE;
3151 data_len = 8;
3152 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3153 SIVAL(pdata,4,characteristics);
3154 break;
3157 #ifdef HAVE_SYS_QUOTAS
3158 case SMB_FS_QUOTA_INFORMATION:
3160 * what we have to send --metze:
3162 * Unknown1: 24 NULL bytes
3163 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3164 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3165 * Quota Flags: 2 byte :
3166 * Unknown3: 6 NULL bytes
3168 * 48 bytes total
3170 * details for Quota Flags:
3172 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3173 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3174 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3175 * 0x0001 Enable Quotas: enable quota for this fs
3179 /* we need to fake up a fsp here,
3180 * because its not send in this call
3182 files_struct fsp;
3183 SMB_NTQUOTA_STRUCT quotas;
3185 ZERO_STRUCT(fsp);
3186 ZERO_STRUCT(quotas);
3188 fsp.conn = conn;
3189 fsp.fnum = -1;
3191 /* access check */
3192 if (conn->server_info->utok.uid != sec_initial_uid()) {
3193 DEBUG(0,("set_user_quota: access_denied "
3194 "service [%s] user [%s]\n",
3195 lp_servicename(SNUM(conn)),
3196 conn->server_info->unix_name));
3197 return NT_STATUS_ACCESS_DENIED;
3200 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3201 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3202 return map_nt_error_from_unix(errno);
3205 data_len = 48;
3207 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3208 lp_servicename(SNUM(conn))));
3210 /* Unknown1 24 NULL bytes*/
3211 SBIG_UINT(pdata,0,(uint64_t)0);
3212 SBIG_UINT(pdata,8,(uint64_t)0);
3213 SBIG_UINT(pdata,16,(uint64_t)0);
3215 /* Default Soft Quota 8 bytes */
3216 SBIG_UINT(pdata,24,quotas.softlim);
3218 /* Default Hard Quota 8 bytes */
3219 SBIG_UINT(pdata,32,quotas.hardlim);
3221 /* Quota flag 2 bytes */
3222 SSVAL(pdata,40,quotas.qflags);
3224 /* Unknown3 6 NULL bytes */
3225 SSVAL(pdata,42,0);
3226 SIVAL(pdata,44,0);
3228 break;
3230 #endif /* HAVE_SYS_QUOTAS */
3231 case SMB_FS_OBJECTID_INFORMATION:
3233 unsigned char objid[16];
3234 struct smb_extended_info extended_info;
3235 memcpy(pdata,create_volume_objectid(conn, objid),16);
3236 samba_extended_info_version (&extended_info);
3237 SIVAL(pdata,16,extended_info.samba_magic);
3238 SIVAL(pdata,20,extended_info.samba_version);
3239 SIVAL(pdata,24,extended_info.samba_subversion);
3240 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3241 memcpy(pdata+36,extended_info.samba_version_string,28);
3242 data_len = 64;
3243 break;
3247 * Query the version and capabilities of the CIFS UNIX extensions
3248 * in use.
3251 case SMB_QUERY_CIFS_UNIX_INFO:
3253 bool large_write = lp_min_receive_file_size() &&
3254 !srv_is_signing_active(smbd_server_conn);
3255 bool large_read = !srv_is_signing_active(smbd_server_conn);
3256 int encrypt_caps = 0;
3258 if (!lp_unix_extensions()) {
3259 return NT_STATUS_INVALID_LEVEL;
3262 switch (conn->encrypt_level) {
3263 case 0:
3264 encrypt_caps = 0;
3265 break;
3266 case 1:
3267 case Auto:
3268 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3269 break;
3270 case Required:
3271 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3272 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3273 large_write = false;
3274 large_read = false;
3275 break;
3278 data_len = 12;
3279 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3280 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3282 /* We have POSIX ACLs, pathname, encryption,
3283 * large read/write, and locking capability. */
3285 SBIG_UINT(pdata,4,((uint64_t)(
3286 CIFS_UNIX_POSIX_ACLS_CAP|
3287 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3288 CIFS_UNIX_FCNTL_LOCKS_CAP|
3289 CIFS_UNIX_EXTATTR_CAP|
3290 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3291 encrypt_caps|
3292 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3293 (large_write ?
3294 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3295 break;
3298 case SMB_QUERY_POSIX_FS_INFO:
3300 int rc;
3301 vfs_statvfs_struct svfs;
3303 if (!lp_unix_extensions()) {
3304 return NT_STATUS_INVALID_LEVEL;
3307 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3309 if (!rc) {
3310 data_len = 56;
3311 SIVAL(pdata,0,svfs.OptimalTransferSize);
3312 SIVAL(pdata,4,svfs.BlockSize);
3313 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3314 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3315 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3316 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3317 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3318 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3319 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3320 #ifdef EOPNOTSUPP
3321 } else if (rc == EOPNOTSUPP) {
3322 return NT_STATUS_INVALID_LEVEL;
3323 #endif /* EOPNOTSUPP */
3324 } else {
3325 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3326 return NT_STATUS_DOS(ERRSRV, ERRerror);
3328 break;
3331 case SMB_QUERY_POSIX_WHOAMI:
3333 uint32_t flags = 0;
3334 uint32_t sid_bytes;
3335 int i;
3337 if (!lp_unix_extensions()) {
3338 return NT_STATUS_INVALID_LEVEL;
3341 if (max_data_bytes < 40) {
3342 return NT_STATUS_BUFFER_TOO_SMALL;
3345 /* We ARE guest if global_sid_Builtin_Guests is
3346 * in our list of SIDs.
3348 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3349 conn->server_info->ptok)) {
3350 flags |= SMB_WHOAMI_GUEST;
3353 /* We are NOT guest if global_sid_Authenticated_Users
3354 * is in our list of SIDs.
3356 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3357 conn->server_info->ptok)) {
3358 flags &= ~SMB_WHOAMI_GUEST;
3361 /* NOTE: 8 bytes for UID/GID, irrespective of native
3362 * platform size. This matches
3363 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3365 data_len = 4 /* flags */
3366 + 4 /* flag mask */
3367 + 8 /* uid */
3368 + 8 /* gid */
3369 + 4 /* ngroups */
3370 + 4 /* num_sids */
3371 + 4 /* SID bytes */
3372 + 4 /* pad/reserved */
3373 + (conn->server_info->utok.ngroups * 8)
3374 /* groups list */
3375 + (conn->server_info->ptok->num_sids *
3376 SID_MAX_SIZE)
3377 /* SID list */;
3379 SIVAL(pdata, 0, flags);
3380 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3381 SBIG_UINT(pdata, 8,
3382 (uint64_t)conn->server_info->utok.uid);
3383 SBIG_UINT(pdata, 16,
3384 (uint64_t)conn->server_info->utok.gid);
3387 if (data_len >= max_data_bytes) {
3388 /* Potential overflow, skip the GIDs and SIDs. */
3390 SIVAL(pdata, 24, 0); /* num_groups */
3391 SIVAL(pdata, 28, 0); /* num_sids */
3392 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3393 SIVAL(pdata, 36, 0); /* reserved */
3395 data_len = 40;
3396 break;
3399 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3400 SIVAL(pdata, 28, conn->server_info->ptok->num_sids);
3402 /* We walk the SID list twice, but this call is fairly
3403 * infrequent, and I don't expect that it's performance
3404 * sensitive -- jpeach
3406 for (i = 0, sid_bytes = 0;
3407 i < conn->server_info->ptok->num_sids; ++i) {
3408 sid_bytes += ndr_size_dom_sid(
3409 &conn->server_info->ptok->user_sids[i],
3413 /* SID list byte count */
3414 SIVAL(pdata, 32, sid_bytes);
3416 /* 4 bytes pad/reserved - must be zero */
3417 SIVAL(pdata, 36, 0);
3418 data_len = 40;
3420 /* GID list */
3421 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3422 SBIG_UINT(pdata, data_len,
3423 (uint64_t)conn->server_info->utok.groups[i]);
3424 data_len += 8;
3427 /* SID list */
3428 for (i = 0;
3429 i < conn->server_info->ptok->num_sids; ++i) {
3430 int sid_len = ndr_size_dom_sid(
3431 &conn->server_info->ptok->user_sids[i],
3434 sid_linearize(pdata + data_len, sid_len,
3435 &conn->server_info->ptok->user_sids[i]);
3436 data_len += sid_len;
3439 break;
3442 case SMB_MAC_QUERY_FS_INFO:
3444 * Thursby MAC extension... ONLY on NTFS filesystems
3445 * once we do streams then we don't need this
3447 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3448 data_len = 88;
3449 SIVAL(pdata,84,0x100); /* Don't support mac... */
3450 break;
3452 /* drop through */
3453 default:
3454 return NT_STATUS_INVALID_LEVEL;
3457 *ret_data_len = data_len;
3458 return NT_STATUS_OK;
3461 /****************************************************************************
3462 Reply to a TRANS2_QFSINFO (query filesystem info).
3463 ****************************************************************************/
3465 static void call_trans2qfsinfo(connection_struct *conn,
3466 struct smb_request *req,
3467 char **pparams, int total_params,
3468 char **ppdata, int total_data,
3469 unsigned int max_data_bytes)
3471 char *params = *pparams;
3472 uint16_t info_level;
3473 int data_len = 0;
3474 NTSTATUS status;
3476 if (total_params < 2) {
3477 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3478 return;
3481 info_level = SVAL(params,0);
3483 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3484 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3485 DEBUG(0,("call_trans2qfsinfo: encryption required "
3486 "and info level 0x%x sent.\n",
3487 (unsigned int)info_level));
3488 exit_server_cleanly("encryption required "
3489 "on connection");
3490 return;
3494 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3496 status = smbd_do_qfsinfo(conn, req,
3497 info_level,
3498 req->flags2,
3499 max_data_bytes,
3500 ppdata, &data_len);
3501 if (!NT_STATUS_IS_OK(status)) {
3502 reply_nterror(req, status);
3503 return;
3506 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3507 max_data_bytes);
3509 DEBUG( 4, ( "%s info_level = %d\n",
3510 smb_fn_name(req->cmd), info_level) );
3512 return;
3515 /****************************************************************************
3516 Reply to a TRANS2_SETFSINFO (set filesystem info).
3517 ****************************************************************************/
3519 static void call_trans2setfsinfo(connection_struct *conn,
3520 struct smb_request *req,
3521 char **pparams, int total_params,
3522 char **ppdata, int total_data,
3523 unsigned int max_data_bytes)
3525 char *pdata = *ppdata;
3526 char *params = *pparams;
3527 uint16 info_level;
3529 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3531 /* */
3532 if (total_params < 4) {
3533 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3534 total_params));
3535 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3536 return;
3539 info_level = SVAL(params,2);
3541 if (IS_IPC(conn)) {
3542 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3543 info_level != SMB_SET_CIFS_UNIX_INFO) {
3544 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3545 "info level (0x%x) on IPC$.\n",
3546 (unsigned int)info_level));
3547 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3548 return;
3552 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3553 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3554 DEBUG(0,("call_trans2setfsinfo: encryption required "
3555 "and info level 0x%x sent.\n",
3556 (unsigned int)info_level));
3557 exit_server_cleanly("encryption required "
3558 "on connection");
3559 return;
3563 switch(info_level) {
3564 case SMB_SET_CIFS_UNIX_INFO:
3566 uint16 client_unix_major;
3567 uint16 client_unix_minor;
3568 uint32 client_unix_cap_low;
3569 uint32 client_unix_cap_high;
3571 if (!lp_unix_extensions()) {
3572 reply_nterror(req,
3573 NT_STATUS_INVALID_LEVEL);
3574 return;
3577 /* There should be 12 bytes of capabilities set. */
3578 if (total_data < 8) {
3579 reply_nterror(
3580 req,
3581 NT_STATUS_INVALID_PARAMETER);
3582 return;
3584 client_unix_major = SVAL(pdata,0);
3585 client_unix_minor = SVAL(pdata,2);
3586 client_unix_cap_low = IVAL(pdata,4);
3587 client_unix_cap_high = IVAL(pdata,8);
3588 /* Just print these values for now. */
3589 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3590 cap_low = 0x%x, cap_high = 0x%x\n",
3591 (unsigned int)client_unix_major,
3592 (unsigned int)client_unix_minor,
3593 (unsigned int)client_unix_cap_low,
3594 (unsigned int)client_unix_cap_high ));
3596 /* Here is where we must switch to posix pathname processing... */
3597 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3598 lp_set_posix_pathnames();
3599 mangle_change_to_posix();
3602 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3603 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3604 /* Client that knows how to do posix locks,
3605 * but not posix open/mkdir operations. Set a
3606 * default type for read/write checks. */
3608 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3611 break;
3614 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3616 NTSTATUS status;
3617 size_t param_len = 0;
3618 size_t data_len = total_data;
3620 if (!lp_unix_extensions()) {
3621 reply_nterror(
3622 req,
3623 NT_STATUS_INVALID_LEVEL);
3624 return;
3627 if (lp_smb_encrypt(SNUM(conn)) == false) {
3628 reply_nterror(
3629 req,
3630 NT_STATUS_NOT_SUPPORTED);
3631 return;
3634 if (smbd_server_conn->smb1.echo_handler.trusted_fde) {
3635 DEBUG( 2,("call_trans2setfsinfo: "
3636 "request transport encryption disabled"
3637 "with 'fork echo handler = yes'\n"));
3638 reply_nterror(
3639 req,
3640 NT_STATUS_NOT_SUPPORTED);
3641 return;
3644 DEBUG( 4,("call_trans2setfsinfo: "
3645 "request transport encryption.\n"));
3647 status = srv_request_encryption_setup(conn,
3648 (unsigned char **)ppdata,
3649 &data_len,
3650 (unsigned char **)pparams,
3651 &param_len);
3653 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3654 !NT_STATUS_IS_OK(status)) {
3655 reply_nterror(req, status);
3656 return;
3659 send_trans2_replies(conn, req,
3660 *pparams,
3661 param_len,
3662 *ppdata,
3663 data_len,
3664 max_data_bytes);
3666 if (NT_STATUS_IS_OK(status)) {
3667 /* Server-side transport
3668 * encryption is now *on*. */
3669 status = srv_encryption_start(conn);
3670 if (!NT_STATUS_IS_OK(status)) {
3671 exit_server_cleanly(
3672 "Failure in setting "
3673 "up encrypted transport");
3676 return;
3679 case SMB_FS_QUOTA_INFORMATION:
3681 files_struct *fsp = NULL;
3682 SMB_NTQUOTA_STRUCT quotas;
3684 ZERO_STRUCT(quotas);
3686 /* access check */
3687 if ((conn->server_info->utok.uid != sec_initial_uid())
3688 ||!CAN_WRITE(conn)) {
3689 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3690 lp_servicename(SNUM(conn)),
3691 conn->server_info->unix_name));
3692 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3693 return;
3696 /* note: normaly there're 48 bytes,
3697 * but we didn't use the last 6 bytes for now
3698 * --metze
3700 fsp = file_fsp(req, SVAL(params,0));
3702 if (!check_fsp_ntquota_handle(conn, req,
3703 fsp)) {
3704 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3705 reply_nterror(
3706 req, NT_STATUS_INVALID_HANDLE);
3707 return;
3710 if (total_data < 42) {
3711 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3712 total_data));
3713 reply_nterror(
3714 req,
3715 NT_STATUS_INVALID_PARAMETER);
3716 return;
3719 /* unknown_1 24 NULL bytes in pdata*/
3721 /* the soft quotas 8 bytes (uint64_t)*/
3722 quotas.softlim = (uint64_t)IVAL(pdata,24);
3723 #ifdef LARGE_SMB_OFF_T
3724 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3725 #else /* LARGE_SMB_OFF_T */
3726 if ((IVAL(pdata,28) != 0)&&
3727 ((quotas.softlim != 0xFFFFFFFF)||
3728 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3729 /* more than 32 bits? */
3730 reply_nterror(
3731 req,
3732 NT_STATUS_INVALID_PARAMETER);
3733 return;
3735 #endif /* LARGE_SMB_OFF_T */
3737 /* the hard quotas 8 bytes (uint64_t)*/
3738 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3739 #ifdef LARGE_SMB_OFF_T
3740 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3741 #else /* LARGE_SMB_OFF_T */
3742 if ((IVAL(pdata,36) != 0)&&
3743 ((quotas.hardlim != 0xFFFFFFFF)||
3744 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3745 /* more than 32 bits? */
3746 reply_nterror(
3747 req,
3748 NT_STATUS_INVALID_PARAMETER);
3749 return;
3751 #endif /* LARGE_SMB_OFF_T */
3753 /* quota_flags 2 bytes **/
3754 quotas.qflags = SVAL(pdata,40);
3756 /* unknown_2 6 NULL bytes follow*/
3758 /* now set the quotas */
3759 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3760 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3761 reply_nterror(req, map_nt_error_from_unix(errno));
3762 return;
3765 break;
3767 default:
3768 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3769 info_level));
3770 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3771 return;
3772 break;
3776 * sending this reply works fine,
3777 * but I'm not sure it's the same
3778 * like windows do...
3779 * --metze
3781 reply_outbuf(req, 10, 0);
3784 #if defined(HAVE_POSIX_ACLS)
3785 /****************************************************************************
3786 Utility function to count the number of entries in a POSIX acl.
3787 ****************************************************************************/
3789 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3791 unsigned int ace_count = 0;
3792 int entry_id = SMB_ACL_FIRST_ENTRY;
3793 SMB_ACL_ENTRY_T entry;
3795 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3796 /* get_next... */
3797 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3798 entry_id = SMB_ACL_NEXT_ENTRY;
3800 ace_count++;
3802 return ace_count;
3805 /****************************************************************************
3806 Utility function to marshall a POSIX acl into wire format.
3807 ****************************************************************************/
3809 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3811 int entry_id = SMB_ACL_FIRST_ENTRY;
3812 SMB_ACL_ENTRY_T entry;
3814 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3815 SMB_ACL_TAG_T tagtype;
3816 SMB_ACL_PERMSET_T permset;
3817 unsigned char perms = 0;
3818 unsigned int own_grp;
3820 /* get_next... */
3821 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3822 entry_id = SMB_ACL_NEXT_ENTRY;
3825 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3826 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3827 return False;
3830 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3831 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3832 return False;
3835 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3836 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3837 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3839 SCVAL(pdata,1,perms);
3841 switch (tagtype) {
3842 case SMB_ACL_USER_OBJ:
3843 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3844 own_grp = (unsigned int)pst->st_ex_uid;
3845 SIVAL(pdata,2,own_grp);
3846 SIVAL(pdata,6,0);
3847 break;
3848 case SMB_ACL_USER:
3850 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3851 if (!puid) {
3852 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3853 return False;
3855 own_grp = (unsigned int)*puid;
3856 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3857 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3858 SIVAL(pdata,2,own_grp);
3859 SIVAL(pdata,6,0);
3860 break;
3862 case SMB_ACL_GROUP_OBJ:
3863 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3864 own_grp = (unsigned int)pst->st_ex_gid;
3865 SIVAL(pdata,2,own_grp);
3866 SIVAL(pdata,6,0);
3867 break;
3868 case SMB_ACL_GROUP:
3870 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3871 if (!pgid) {
3872 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3873 return False;
3875 own_grp = (unsigned int)*pgid;
3876 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3877 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3878 SIVAL(pdata,2,own_grp);
3879 SIVAL(pdata,6,0);
3880 break;
3882 case SMB_ACL_MASK:
3883 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3884 SIVAL(pdata,2,0xFFFFFFFF);
3885 SIVAL(pdata,6,0xFFFFFFFF);
3886 break;
3887 case SMB_ACL_OTHER:
3888 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3889 SIVAL(pdata,2,0xFFFFFFFF);
3890 SIVAL(pdata,6,0xFFFFFFFF);
3891 break;
3892 default:
3893 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3894 return False;
3896 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3899 return True;
3901 #endif
3903 /****************************************************************************
3904 Store the FILE_UNIX_BASIC info.
3905 ****************************************************************************/
3907 static char *store_file_unix_basic(connection_struct *conn,
3908 char *pdata,
3909 files_struct *fsp,
3910 const SMB_STRUCT_STAT *psbuf)
3912 uint64_t file_index = get_FileIndex(conn, psbuf);
3914 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3915 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3917 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3918 pdata += 8;
3920 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3921 pdata += 8;
3923 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3924 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3925 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3926 pdata += 24;
3928 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3929 SIVAL(pdata,4,0);
3930 pdata += 8;
3932 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3933 SIVAL(pdata,4,0);
3934 pdata += 8;
3936 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3937 pdata += 4;
3939 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3940 SIVAL(pdata,4,0);
3941 pdata += 8;
3943 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3944 SIVAL(pdata,4,0);
3945 pdata += 8;
3947 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3948 pdata += 8;
3950 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3951 SIVAL(pdata,4,0);
3952 pdata += 8;
3954 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3955 SIVAL(pdata,4,0);
3956 pdata += 8;
3958 return pdata;
3961 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3962 * the chflags(2) (or equivalent) flags.
3964 * XXX: this really should be behind the VFS interface. To do this, we would
3965 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3966 * Each VFS module could then implement its own mapping as appropriate for the
3967 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3969 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3970 info2_flags_map[] =
3972 #ifdef UF_NODUMP
3973 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3974 #endif
3976 #ifdef UF_IMMUTABLE
3977 { UF_IMMUTABLE, EXT_IMMUTABLE },
3978 #endif
3980 #ifdef UF_APPEND
3981 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3982 #endif
3984 #ifdef UF_HIDDEN
3985 { UF_HIDDEN, EXT_HIDDEN },
3986 #endif
3988 /* Do not remove. We need to guarantee that this array has at least one
3989 * entry to build on HP-UX.
3991 { 0, 0 }
3995 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3996 uint32 *smb_fflags, uint32 *smb_fmask)
3998 int i;
4000 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4001 *smb_fmask |= info2_flags_map[i].smb_fflag;
4002 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4003 *smb_fflags |= info2_flags_map[i].smb_fflag;
4008 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4009 const uint32 smb_fflags,
4010 const uint32 smb_fmask,
4011 int *stat_fflags)
4013 uint32 max_fmask = 0;
4014 int i;
4016 *stat_fflags = psbuf->st_ex_flags;
4018 /* For each flags requested in smb_fmask, check the state of the
4019 * corresponding flag in smb_fflags and set or clear the matching
4020 * stat flag.
4023 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4024 max_fmask |= info2_flags_map[i].smb_fflag;
4025 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4026 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4027 *stat_fflags |= info2_flags_map[i].stat_fflag;
4028 } else {
4029 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4034 /* If smb_fmask is asking to set any bits that are not supported by
4035 * our flag mappings, we should fail.
4037 if ((smb_fmask & max_fmask) != smb_fmask) {
4038 return False;
4041 return True;
4045 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4046 * of file flags and birth (create) time.
4048 static char *store_file_unix_basic_info2(connection_struct *conn,
4049 char *pdata,
4050 files_struct *fsp,
4051 const SMB_STRUCT_STAT *psbuf)
4053 uint32 file_flags = 0;
4054 uint32 flags_mask = 0;
4056 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4058 /* Create (birth) time 64 bit */
4059 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4060 pdata += 8;
4062 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4063 SIVAL(pdata, 0, file_flags); /* flags */
4064 SIVAL(pdata, 4, flags_mask); /* mask */
4065 pdata += 8;
4067 return pdata;
4070 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4071 const struct stream_struct *streams,
4072 char *data,
4073 unsigned int max_data_bytes,
4074 unsigned int *data_size)
4076 unsigned int i;
4077 unsigned int ofs = 0;
4079 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4080 unsigned int next_offset;
4081 size_t namelen;
4082 smb_ucs2_t *namebuf;
4084 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4085 streams[i].name, &namelen) ||
4086 namelen <= 2)
4088 return NT_STATUS_INVALID_PARAMETER;
4092 * name_buf is now null-terminated, we need to marshall as not
4093 * terminated
4096 namelen -= 2;
4098 SIVAL(data, ofs+4, namelen);
4099 SOFF_T(data, ofs+8, streams[i].size);
4100 SOFF_T(data, ofs+16, streams[i].alloc_size);
4101 memcpy(data+ofs+24, namebuf, namelen);
4102 TALLOC_FREE(namebuf);
4104 next_offset = ofs + 24 + namelen;
4106 if (i == num_streams-1) {
4107 SIVAL(data, ofs, 0);
4109 else {
4110 unsigned int align = ndr_align_size(next_offset, 8);
4112 memset(data+next_offset, 0, align);
4113 next_offset += align;
4115 SIVAL(data, ofs, next_offset - ofs);
4116 ofs = next_offset;
4119 ofs = next_offset;
4122 *data_size = ofs;
4124 return NT_STATUS_OK;
4127 /****************************************************************************
4128 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4129 ****************************************************************************/
4131 static void call_trans2qpipeinfo(connection_struct *conn,
4132 struct smb_request *req,
4133 unsigned int tran_call,
4134 char **pparams, int total_params,
4135 char **ppdata, int total_data,
4136 unsigned int max_data_bytes)
4138 char *params = *pparams;
4139 char *pdata = *ppdata;
4140 unsigned int data_size = 0;
4141 unsigned int param_size = 2;
4142 uint16 info_level;
4143 files_struct *fsp;
4145 if (!params) {
4146 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4147 return;
4150 if (total_params < 4) {
4151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4152 return;
4155 fsp = file_fsp(req, SVAL(params,0));
4156 if (!fsp_is_np(fsp)) {
4157 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4158 return;
4161 info_level = SVAL(params,2);
4163 *pparams = (char *)SMB_REALLOC(*pparams,2);
4164 if (*pparams == NULL) {
4165 reply_nterror(req, NT_STATUS_NO_MEMORY);
4166 return;
4168 params = *pparams;
4169 SSVAL(params,0,0);
4170 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4171 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4172 if (*ppdata == NULL ) {
4173 reply_nterror(req, NT_STATUS_NO_MEMORY);
4174 return;
4176 pdata = *ppdata;
4178 switch (info_level) {
4179 case SMB_FILE_STANDARD_INFORMATION:
4180 memset(pdata,0,24);
4181 SOFF_T(pdata,0,4096LL);
4182 SIVAL(pdata,16,1);
4183 SIVAL(pdata,20,1);
4184 data_size = 24;
4185 break;
4187 default:
4188 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4189 return;
4192 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4193 max_data_bytes);
4195 return;
4198 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4199 TALLOC_CTX *mem_ctx,
4200 uint16_t info_level,
4201 files_struct *fsp,
4202 struct smb_filename *smb_fname,
4203 bool delete_pending,
4204 struct timespec write_time_ts,
4205 struct ea_list *ea_list,
4206 int lock_data_count,
4207 char *lock_data,
4208 uint16_t flags2,
4209 unsigned int max_data_bytes,
4210 char **ppdata,
4211 unsigned int *pdata_size)
4213 char *pdata = *ppdata;
4214 char *dstart, *dend;
4215 unsigned int data_size;
4216 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4217 time_t create_time, mtime, atime, c_time;
4218 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4219 char *p;
4220 char *base_name;
4221 char *dos_fname;
4222 int mode;
4223 int nlink;
4224 NTSTATUS status;
4225 uint64_t file_size = 0;
4226 uint64_t pos = 0;
4227 uint64_t allocation_size = 0;
4228 uint64_t file_index = 0;
4229 uint32_t access_mask = 0;
4231 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4232 return NT_STATUS_INVALID_LEVEL;
4235 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4236 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4237 info_level, max_data_bytes));
4239 mode = dos_mode(conn, smb_fname);
4240 nlink = psbuf->st_ex_nlink;
4242 if (nlink && (mode&aDIR)) {
4243 nlink = 1;
4246 if ((nlink > 0) && delete_pending) {
4247 nlink -= 1;
4250 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4251 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4252 if (*ppdata == NULL) {
4253 return NT_STATUS_NO_MEMORY;
4255 pdata = *ppdata;
4256 dstart = pdata;
4257 dend = dstart + data_size - 1;
4259 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4260 update_stat_ex_mtime(psbuf, write_time_ts);
4263 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4264 mtime_ts = psbuf->st_ex_mtime;
4265 atime_ts = psbuf->st_ex_atime;
4266 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4268 if (lp_dos_filetime_resolution(SNUM(conn))) {
4269 dos_filetime_timespec(&create_time_ts);
4270 dos_filetime_timespec(&mtime_ts);
4271 dos_filetime_timespec(&atime_ts);
4272 dos_filetime_timespec(&ctime_ts);
4275 create_time = convert_timespec_to_time_t(create_time_ts);
4276 mtime = convert_timespec_to_time_t(mtime_ts);
4277 atime = convert_timespec_to_time_t(atime_ts);
4278 c_time = convert_timespec_to_time_t(ctime_ts);
4280 p = strrchr_m(smb_fname->base_name,'/');
4281 if (!p)
4282 base_name = smb_fname->base_name;
4283 else
4284 base_name = p+1;
4286 /* NT expects the name to be in an exact form of the *full*
4287 filename. See the trans2 torture test */
4288 if (ISDOT(base_name)) {
4289 dos_fname = talloc_strdup(mem_ctx, "\\");
4290 if (!dos_fname) {
4291 return NT_STATUS_NO_MEMORY;
4293 } else {
4294 dos_fname = talloc_asprintf(mem_ctx,
4295 "\\%s",
4296 smb_fname->base_name);
4297 if (!dos_fname) {
4298 return NT_STATUS_NO_MEMORY;
4300 if (is_ntfs_stream_smb_fname(smb_fname)) {
4301 dos_fname = talloc_asprintf(dos_fname, "%s",
4302 smb_fname->stream_name);
4303 if (!dos_fname) {
4304 return NT_STATUS_NO_MEMORY;
4308 string_replace(dos_fname, '/', '\\');
4311 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4313 if (!fsp) {
4314 /* Do we have this path open ? */
4315 files_struct *fsp1;
4316 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4317 fsp1 = file_find_di_first(fileid);
4318 if (fsp1 && fsp1->initial_allocation_size) {
4319 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4323 if (!(mode & aDIR)) {
4324 file_size = get_file_size_stat(psbuf);
4327 if (fsp) {
4328 pos = fsp->fh->position_information;
4331 if (fsp) {
4332 access_mask = fsp->access_mask;
4333 } else {
4334 /* GENERIC_EXECUTE mapping from Windows */
4335 access_mask = 0x12019F;
4338 /* This should be an index number - looks like
4339 dev/ino to me :-)
4341 I think this causes us to fail the IFSKIT
4342 BasicFileInformationTest. -tpot */
4343 file_index = get_FileIndex(conn, psbuf);
4345 switch (info_level) {
4346 case SMB_INFO_STANDARD:
4347 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4348 data_size = 22;
4349 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4350 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4351 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4352 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4353 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4354 SSVAL(pdata,l1_attrFile,mode);
4355 break;
4357 case SMB_INFO_QUERY_EA_SIZE:
4359 unsigned int ea_size =
4360 estimate_ea_size(conn, fsp,
4361 smb_fname->base_name);
4362 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4363 data_size = 26;
4364 srv_put_dos_date2(pdata,0,create_time);
4365 srv_put_dos_date2(pdata,4,atime);
4366 srv_put_dos_date2(pdata,8,mtime); /* write time */
4367 SIVAL(pdata,12,(uint32)file_size);
4368 SIVAL(pdata,16,(uint32)allocation_size);
4369 SSVAL(pdata,20,mode);
4370 SIVAL(pdata,22,ea_size);
4371 break;
4374 case SMB_INFO_IS_NAME_VALID:
4375 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4376 if (fsp) {
4377 /* os/2 needs this ? really ?*/
4378 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4380 /* This is only reached for qpathinfo */
4381 data_size = 0;
4382 break;
4384 case SMB_INFO_QUERY_EAS_FROM_LIST:
4386 size_t total_ea_len = 0;
4387 struct ea_list *ea_file_list = NULL;
4389 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4391 ea_file_list =
4392 get_ea_list_from_file(mem_ctx, conn, fsp,
4393 smb_fname->base_name,
4394 &total_ea_len);
4395 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4397 if (!ea_list || (total_ea_len > data_size)) {
4398 data_size = 4;
4399 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4400 break;
4403 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4404 break;
4407 case SMB_INFO_QUERY_ALL_EAS:
4409 /* We have data_size bytes to put EA's into. */
4410 size_t total_ea_len = 0;
4412 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4414 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4415 smb_fname->base_name,
4416 &total_ea_len);
4417 if (!ea_list || (total_ea_len > data_size)) {
4418 data_size = 4;
4419 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4420 break;
4423 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4424 break;
4427 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4429 /* This is FileFullEaInformation - 0xF which maps to
4430 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4432 /* We have data_size bytes to put EA's into. */
4433 size_t total_ea_len = 0;
4434 struct ea_list *ea_file_list = NULL;
4436 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4438 /*TODO: add filtering and index handling */
4440 ea_file_list =
4441 get_ea_list_from_file(mem_ctx, conn, fsp,
4442 smb_fname->base_name,
4443 &total_ea_len);
4444 if (!ea_file_list) {
4445 return NT_STATUS_NO_EAS_ON_FILE;
4448 status = fill_ea_chained_buffer(mem_ctx,
4449 pdata,
4450 data_size,
4451 &data_size,
4452 conn, ea_file_list);
4453 if (!NT_STATUS_IS_OK(status)) {
4454 return status;
4456 break;
4459 case SMB_FILE_BASIC_INFORMATION:
4460 case SMB_QUERY_FILE_BASIC_INFO:
4462 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4463 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4464 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4465 } else {
4466 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4467 data_size = 40;
4468 SIVAL(pdata,36,0);
4470 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4471 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4472 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4473 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4474 SIVAL(pdata,32,mode);
4476 DEBUG(5,("SMB_QFBI - "));
4477 DEBUG(5,("create: %s ", ctime(&create_time)));
4478 DEBUG(5,("access: %s ", ctime(&atime)));
4479 DEBUG(5,("write: %s ", ctime(&mtime)));
4480 DEBUG(5,("change: %s ", ctime(&c_time)));
4481 DEBUG(5,("mode: %x\n", mode));
4482 break;
4484 case SMB_FILE_STANDARD_INFORMATION:
4485 case SMB_QUERY_FILE_STANDARD_INFO:
4487 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4488 data_size = 24;
4489 SOFF_T(pdata,0,allocation_size);
4490 SOFF_T(pdata,8,file_size);
4491 SIVAL(pdata,16,nlink);
4492 SCVAL(pdata,20,delete_pending?1:0);
4493 SCVAL(pdata,21,(mode&aDIR)?1:0);
4494 SSVAL(pdata,22,0); /* Padding. */
4495 break;
4497 case SMB_FILE_EA_INFORMATION:
4498 case SMB_QUERY_FILE_EA_INFO:
4500 unsigned int ea_size =
4501 estimate_ea_size(conn, fsp, smb_fname->base_name);
4502 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4503 data_size = 4;
4504 SIVAL(pdata,0,ea_size);
4505 break;
4508 /* Get the 8.3 name - used if NT SMB was negotiated. */
4509 case SMB_QUERY_FILE_ALT_NAME_INFO:
4510 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4512 int len;
4513 char mangled_name[13];
4514 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4515 if (!name_to_8_3(base_name,mangled_name,
4516 True,conn->params)) {
4517 return NT_STATUS_NO_MEMORY;
4519 len = srvstr_push(dstart, flags2,
4520 pdata+4, mangled_name,
4521 PTR_DIFF(dend, pdata+4),
4522 STR_UNICODE);
4523 data_size = 4 + len;
4524 SIVAL(pdata,0,len);
4525 break;
4528 case SMB_QUERY_FILE_NAME_INFO:
4530 int len;
4532 this must be *exactly* right for ACLs on mapped drives to work
4534 len = srvstr_push(dstart, flags2,
4535 pdata+4, dos_fname,
4536 PTR_DIFF(dend, pdata+4),
4537 STR_UNICODE);
4538 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4539 data_size = 4 + len;
4540 SIVAL(pdata,0,len);
4541 break;
4544 case SMB_FILE_ALLOCATION_INFORMATION:
4545 case SMB_QUERY_FILE_ALLOCATION_INFO:
4546 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4547 data_size = 8;
4548 SOFF_T(pdata,0,allocation_size);
4549 break;
4551 case SMB_FILE_END_OF_FILE_INFORMATION:
4552 case SMB_QUERY_FILE_END_OF_FILEINFO:
4553 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4554 data_size = 8;
4555 SOFF_T(pdata,0,file_size);
4556 break;
4558 case SMB_QUERY_FILE_ALL_INFO:
4559 case SMB_FILE_ALL_INFORMATION:
4561 int len;
4562 unsigned int ea_size =
4563 estimate_ea_size(conn, fsp, smb_fname->base_name);
4564 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4565 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4566 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4567 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4568 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4569 SIVAL(pdata,32,mode);
4570 SIVAL(pdata,36,0); /* padding. */
4571 pdata += 40;
4572 SOFF_T(pdata,0,allocation_size);
4573 SOFF_T(pdata,8,file_size);
4574 SIVAL(pdata,16,nlink);
4575 SCVAL(pdata,20,delete_pending);
4576 SCVAL(pdata,21,(mode&aDIR)?1:0);
4577 SSVAL(pdata,22,0);
4578 pdata += 24;
4579 SIVAL(pdata,0,ea_size);
4580 pdata += 4; /* EA info */
4581 len = srvstr_push(dstart, flags2,
4582 pdata+4, dos_fname,
4583 PTR_DIFF(dend, pdata+4),
4584 STR_UNICODE);
4585 SIVAL(pdata,0,len);
4586 pdata += 4 + len;
4587 data_size = PTR_DIFF(pdata,(*ppdata));
4588 break;
4591 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4593 int len;
4594 unsigned int ea_size =
4595 estimate_ea_size(conn, fsp, smb_fname->base_name);
4596 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4597 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4598 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4599 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4600 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4601 SIVAL(pdata, 0x20, mode);
4602 SIVAL(pdata, 0x24, 0); /* padding. */
4603 SBVAL(pdata, 0x28, allocation_size);
4604 SBVAL(pdata, 0x30, file_size);
4605 SIVAL(pdata, 0x38, nlink);
4606 SCVAL(pdata, 0x3C, delete_pending);
4607 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4608 SSVAL(pdata, 0x3E, 0); /* padding */
4609 SBVAL(pdata, 0x40, file_index);
4610 SIVAL(pdata, 0x48, ea_size);
4611 SIVAL(pdata, 0x4C, access_mask);
4612 SBVAL(pdata, 0x50, pos);
4613 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4614 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4616 pdata += 0x60;
4618 len = srvstr_push(dstart, flags2,
4619 pdata+4, dos_fname,
4620 PTR_DIFF(dend, pdata+4),
4621 STR_UNICODE);
4622 SIVAL(pdata,0,len);
4623 pdata += 4 + len;
4624 data_size = PTR_DIFF(pdata,(*ppdata));
4625 break;
4627 case SMB_FILE_INTERNAL_INFORMATION:
4629 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4630 SBVAL(pdata, 0, file_index);
4631 data_size = 8;
4632 break;
4634 case SMB_FILE_ACCESS_INFORMATION:
4635 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4636 SIVAL(pdata, 0, access_mask);
4637 data_size = 4;
4638 break;
4640 case SMB_FILE_NAME_INFORMATION:
4641 /* Pathname with leading '\'. */
4643 size_t byte_len;
4644 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4645 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4646 SIVAL(pdata,0,byte_len);
4647 data_size = 4 + byte_len;
4648 break;
4651 case SMB_FILE_DISPOSITION_INFORMATION:
4652 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4653 data_size = 1;
4654 SCVAL(pdata,0,delete_pending);
4655 break;
4657 case SMB_FILE_POSITION_INFORMATION:
4658 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4659 data_size = 8;
4660 SOFF_T(pdata,0,pos);
4661 break;
4663 case SMB_FILE_MODE_INFORMATION:
4664 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4665 SIVAL(pdata,0,mode);
4666 data_size = 4;
4667 break;
4669 case SMB_FILE_ALIGNMENT_INFORMATION:
4670 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4671 SIVAL(pdata,0,0); /* No alignment needed. */
4672 data_size = 4;
4673 break;
4676 * NT4 server just returns "invalid query" to this - if we try
4677 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4678 * want this. JRA.
4680 /* The first statement above is false - verified using Thursby
4681 * client against NT4 -- gcolley.
4683 case SMB_QUERY_FILE_STREAM_INFO:
4684 case SMB_FILE_STREAM_INFORMATION: {
4685 unsigned int num_streams;
4686 struct stream_struct *streams;
4688 DEBUG(10,("smbd_do_qfilepathinfo: "
4689 "SMB_FILE_STREAM_INFORMATION\n"));
4691 if (is_ntfs_stream_smb_fname(smb_fname)) {
4692 return NT_STATUS_INVALID_PARAMETER;
4695 status = SMB_VFS_STREAMINFO(
4696 conn, fsp, smb_fname->base_name, talloc_tos(),
4697 &num_streams, &streams);
4699 if (!NT_STATUS_IS_OK(status)) {
4700 DEBUG(10, ("could not get stream info: %s\n",
4701 nt_errstr(status)));
4702 return status;
4705 status = marshall_stream_info(num_streams, streams,
4706 pdata, max_data_bytes,
4707 &data_size);
4709 if (!NT_STATUS_IS_OK(status)) {
4710 DEBUG(10, ("marshall_stream_info failed: %s\n",
4711 nt_errstr(status)));
4712 return status;
4715 TALLOC_FREE(streams);
4717 break;
4719 case SMB_QUERY_COMPRESSION_INFO:
4720 case SMB_FILE_COMPRESSION_INFORMATION:
4721 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4722 SOFF_T(pdata,0,file_size);
4723 SIVAL(pdata,8,0); /* ??? */
4724 SIVAL(pdata,12,0); /* ??? */
4725 data_size = 16;
4726 break;
4728 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4729 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4730 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4731 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4732 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4733 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4734 SOFF_T(pdata,32,allocation_size);
4735 SOFF_T(pdata,40,file_size);
4736 SIVAL(pdata,48,mode);
4737 SIVAL(pdata,52,0); /* ??? */
4738 data_size = 56;
4739 break;
4741 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4742 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4743 SIVAL(pdata,0,mode);
4744 SIVAL(pdata,4,0);
4745 data_size = 8;
4746 break;
4749 * CIFS UNIX Extensions.
4752 case SMB_QUERY_FILE_UNIX_BASIC:
4754 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4755 data_size = PTR_DIFF(pdata,(*ppdata));
4758 int i;
4759 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4761 for (i=0; i<100; i++)
4762 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4763 DEBUG(4,("\n"));
4766 break;
4768 case SMB_QUERY_FILE_UNIX_INFO2:
4770 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4771 data_size = PTR_DIFF(pdata,(*ppdata));
4774 int i;
4775 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4777 for (i=0; i<100; i++)
4778 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4779 DEBUG(4,("\n"));
4782 break;
4784 case SMB_QUERY_FILE_UNIX_LINK:
4786 int len;
4787 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4789 if (!buffer) {
4790 return NT_STATUS_NO_MEMORY;
4793 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4794 #ifdef S_ISLNK
4795 if(!S_ISLNK(psbuf->st_ex_mode)) {
4796 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4798 #else
4799 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4800 #endif
4801 len = SMB_VFS_READLINK(conn,
4802 smb_fname->base_name,
4803 buffer, PATH_MAX);
4804 if (len == -1) {
4805 return map_nt_error_from_unix(errno);
4807 buffer[len] = 0;
4808 len = srvstr_push(dstart, flags2,
4809 pdata, buffer,
4810 PTR_DIFF(dend, pdata),
4811 STR_TERMINATE);
4812 pdata += len;
4813 data_size = PTR_DIFF(pdata,(*ppdata));
4815 break;
4818 #if defined(HAVE_POSIX_ACLS)
4819 case SMB_QUERY_POSIX_ACL:
4821 SMB_ACL_T file_acl = NULL;
4822 SMB_ACL_T def_acl = NULL;
4823 uint16 num_file_acls = 0;
4824 uint16 num_def_acls = 0;
4826 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4827 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4828 } else {
4829 file_acl =
4830 SMB_VFS_SYS_ACL_GET_FILE(conn,
4831 smb_fname->base_name,
4832 SMB_ACL_TYPE_ACCESS);
4835 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4836 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4837 "not implemented on "
4838 "filesystem containing %s\n",
4839 smb_fname->base_name));
4840 return NT_STATUS_NOT_IMPLEMENTED;
4843 if (S_ISDIR(psbuf->st_ex_mode)) {
4844 if (fsp && fsp->is_directory) {
4845 def_acl =
4846 SMB_VFS_SYS_ACL_GET_FILE(
4847 conn,
4848 fsp->fsp_name->base_name,
4849 SMB_ACL_TYPE_DEFAULT);
4850 } else {
4851 def_acl =
4852 SMB_VFS_SYS_ACL_GET_FILE(
4853 conn,
4854 smb_fname->base_name,
4855 SMB_ACL_TYPE_DEFAULT);
4857 def_acl = free_empty_sys_acl(conn, def_acl);
4860 num_file_acls = count_acl_entries(conn, file_acl);
4861 num_def_acls = count_acl_entries(conn, def_acl);
4863 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4864 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4865 data_size,
4866 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4867 SMB_POSIX_ACL_HEADER_SIZE) ));
4868 if (file_acl) {
4869 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4871 if (def_acl) {
4872 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4874 return NT_STATUS_BUFFER_TOO_SMALL;
4877 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4878 SSVAL(pdata,2,num_file_acls);
4879 SSVAL(pdata,4,num_def_acls);
4880 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4881 if (file_acl) {
4882 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4884 if (def_acl) {
4885 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4887 return NT_STATUS_INTERNAL_ERROR;
4889 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4890 if (file_acl) {
4891 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4893 if (def_acl) {
4894 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4896 return NT_STATUS_INTERNAL_ERROR;
4899 if (file_acl) {
4900 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4902 if (def_acl) {
4903 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4905 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4906 break;
4908 #endif
4911 case SMB_QUERY_POSIX_LOCK:
4913 uint64_t count;
4914 uint64_t offset;
4915 uint64_t smblctx;
4916 enum brl_type lock_type;
4918 /* We need an open file with a real fd for this. */
4919 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4920 return NT_STATUS_INVALID_LEVEL;
4923 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4924 return NT_STATUS_INVALID_PARAMETER;
4927 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4928 case POSIX_LOCK_TYPE_READ:
4929 lock_type = READ_LOCK;
4930 break;
4931 case POSIX_LOCK_TYPE_WRITE:
4932 lock_type = WRITE_LOCK;
4933 break;
4934 case POSIX_LOCK_TYPE_UNLOCK:
4935 default:
4936 /* There's no point in asking for an unlock... */
4937 return NT_STATUS_INVALID_PARAMETER;
4940 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4941 #if defined(HAVE_LONGLONG)
4942 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4943 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4944 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4945 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4946 #else /* HAVE_LONGLONG */
4947 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4948 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4949 #endif /* HAVE_LONGLONG */
4951 status = query_lock(fsp,
4952 &smblctx,
4953 &count,
4954 &offset,
4955 &lock_type,
4956 POSIX_LOCK);
4958 if (ERROR_WAS_LOCK_DENIED(status)) {
4959 /* Here we need to report who has it locked... */
4960 data_size = POSIX_LOCK_DATA_SIZE;
4962 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4963 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4964 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4965 #if defined(HAVE_LONGLONG)
4966 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4967 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4968 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4969 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4970 #else /* HAVE_LONGLONG */
4971 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4972 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4973 #endif /* HAVE_LONGLONG */
4975 } else if (NT_STATUS_IS_OK(status)) {
4976 /* For success we just return a copy of what we sent
4977 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4978 data_size = POSIX_LOCK_DATA_SIZE;
4979 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4980 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4981 } else {
4982 return status;
4984 break;
4987 default:
4988 return NT_STATUS_INVALID_LEVEL;
4991 *pdata_size = data_size;
4992 return NT_STATUS_OK;
4995 /****************************************************************************
4996 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4997 file name or file id).
4998 ****************************************************************************/
5000 static void call_trans2qfilepathinfo(connection_struct *conn,
5001 struct smb_request *req,
5002 unsigned int tran_call,
5003 char **pparams, int total_params,
5004 char **ppdata, int total_data,
5005 unsigned int max_data_bytes)
5007 char *params = *pparams;
5008 char *pdata = *ppdata;
5009 uint16 info_level;
5010 unsigned int data_size = 0;
5011 unsigned int param_size = 2;
5012 struct smb_filename *smb_fname = NULL;
5013 bool delete_pending = False;
5014 struct timespec write_time_ts;
5015 files_struct *fsp = NULL;
5016 struct file_id fileid;
5017 struct ea_list *ea_list = NULL;
5018 int lock_data_count = 0;
5019 char *lock_data = NULL;
5020 NTSTATUS status = NT_STATUS_OK;
5022 if (!params) {
5023 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5024 return;
5027 ZERO_STRUCT(write_time_ts);
5029 if (tran_call == TRANSACT2_QFILEINFO) {
5030 if (total_params < 4) {
5031 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5032 return;
5035 if (IS_IPC(conn)) {
5036 call_trans2qpipeinfo(conn, req, tran_call,
5037 pparams, total_params,
5038 ppdata, total_data,
5039 max_data_bytes);
5040 return;
5043 fsp = file_fsp(req, SVAL(params,0));
5044 info_level = SVAL(params,2);
5046 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5048 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5049 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5050 return;
5053 /* Initial check for valid fsp ptr. */
5054 if (!check_fsp_open(conn, req, fsp)) {
5055 return;
5058 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5059 &smb_fname);
5060 if (!NT_STATUS_IS_OK(status)) {
5061 reply_nterror(req, status);
5062 return;
5065 if(fsp->fake_file_handle) {
5067 * This is actually for the QUOTA_FAKE_FILE --metze
5070 /* We know this name is ok, it's already passed the checks. */
5072 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5074 * This is actually a QFILEINFO on a directory
5075 * handle (returned from an NT SMB). NT5.0 seems
5076 * to do this call. JRA.
5079 if (INFO_LEVEL_IS_UNIX(info_level)) {
5080 /* Always do lstat for UNIX calls. */
5081 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5082 DEBUG(3,("call_trans2qfilepathinfo: "
5083 "SMB_VFS_LSTAT of %s failed "
5084 "(%s)\n",
5085 smb_fname_str_dbg(smb_fname),
5086 strerror(errno)));
5087 reply_nterror(req,
5088 map_nt_error_from_unix(errno));
5089 return;
5091 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5092 DEBUG(3,("call_trans2qfilepathinfo: "
5093 "SMB_VFS_STAT of %s failed (%s)\n",
5094 smb_fname_str_dbg(smb_fname),
5095 strerror(errno)));
5096 reply_nterror(req,
5097 map_nt_error_from_unix(errno));
5098 return;
5101 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5102 get_file_infos(fileid, &delete_pending, &write_time_ts);
5103 } else {
5105 * Original code - this is an open file.
5107 if (!check_fsp(conn, req, fsp)) {
5108 return;
5111 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5112 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5113 fsp->fnum, strerror(errno)));
5114 reply_nterror(req,
5115 map_nt_error_from_unix(errno));
5116 return;
5118 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5119 get_file_infos(fileid, &delete_pending, &write_time_ts);
5122 } else {
5123 char *fname = NULL;
5125 /* qpathinfo */
5126 if (total_params < 7) {
5127 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5128 return;
5131 info_level = SVAL(params,0);
5133 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5135 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5136 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5137 return;
5140 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5141 total_params - 6,
5142 STR_TERMINATE, &status);
5143 if (!NT_STATUS_IS_OK(status)) {
5144 reply_nterror(req, status);
5145 return;
5148 status = filename_convert(req,
5149 conn,
5150 req->flags2 & FLAGS2_DFS_PATHNAMES,
5151 fname,
5153 NULL,
5154 &smb_fname);
5155 if (!NT_STATUS_IS_OK(status)) {
5156 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5157 reply_botherror(req,
5158 NT_STATUS_PATH_NOT_COVERED,
5159 ERRSRV, ERRbadpath);
5160 return;
5162 reply_nterror(req, status);
5163 return;
5166 /* If this is a stream, check if there is a delete_pending. */
5167 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5168 && is_ntfs_stream_smb_fname(smb_fname)) {
5169 struct smb_filename *smb_fname_base = NULL;
5171 /* Create an smb_filename with stream_name == NULL. */
5172 status =
5173 create_synthetic_smb_fname(talloc_tos(),
5174 smb_fname->base_name,
5175 NULL, NULL,
5176 &smb_fname_base);
5177 if (!NT_STATUS_IS_OK(status)) {
5178 reply_nterror(req, status);
5179 return;
5182 if (INFO_LEVEL_IS_UNIX(info_level)) {
5183 /* Always do lstat for UNIX calls. */
5184 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5185 DEBUG(3,("call_trans2qfilepathinfo: "
5186 "SMB_VFS_LSTAT of %s failed "
5187 "(%s)\n",
5188 smb_fname_str_dbg(smb_fname_base),
5189 strerror(errno)));
5190 TALLOC_FREE(smb_fname_base);
5191 reply_nterror(req,
5192 map_nt_error_from_unix(errno));
5193 return;
5195 } else {
5196 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5197 DEBUG(3,("call_trans2qfilepathinfo: "
5198 "fileinfo of %s failed "
5199 "(%s)\n",
5200 smb_fname_str_dbg(smb_fname_base),
5201 strerror(errno)));
5202 TALLOC_FREE(smb_fname_base);
5203 reply_nterror(req,
5204 map_nt_error_from_unix(errno));
5205 return;
5209 fileid = vfs_file_id_from_sbuf(conn,
5210 &smb_fname_base->st);
5211 TALLOC_FREE(smb_fname_base);
5212 get_file_infos(fileid, &delete_pending, NULL);
5213 if (delete_pending) {
5214 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5215 return;
5219 if (INFO_LEVEL_IS_UNIX(info_level)) {
5220 /* Always do lstat for UNIX calls. */
5221 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5222 DEBUG(3,("call_trans2qfilepathinfo: "
5223 "SMB_VFS_LSTAT of %s failed (%s)\n",
5224 smb_fname_str_dbg(smb_fname),
5225 strerror(errno)));
5226 reply_nterror(req,
5227 map_nt_error_from_unix(errno));
5228 return;
5231 } else {
5232 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5233 DEBUG(3,("call_trans2qfilepathinfo: "
5234 "SMB_VFS_STAT of %s failed (%s)\n",
5235 smb_fname_str_dbg(smb_fname),
5236 strerror(errno)));
5237 reply_nterror(req,
5238 map_nt_error_from_unix(errno));
5239 return;
5243 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5244 get_file_infos(fileid, &delete_pending, &write_time_ts);
5245 if (delete_pending) {
5246 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5247 return;
5251 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5252 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5253 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5255 /* Pull out any data sent here before we realloc. */
5256 switch (info_level) {
5257 case SMB_INFO_QUERY_EAS_FROM_LIST:
5259 /* Pull any EA list from the data portion. */
5260 uint32 ea_size;
5262 if (total_data < 4) {
5263 reply_nterror(
5264 req, NT_STATUS_INVALID_PARAMETER);
5265 return;
5267 ea_size = IVAL(pdata,0);
5269 if (total_data > 0 && ea_size != total_data) {
5270 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5271 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5272 reply_nterror(
5273 req, NT_STATUS_INVALID_PARAMETER);
5274 return;
5277 if (!lp_ea_support(SNUM(conn))) {
5278 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5279 return;
5282 /* Pull out the list of names. */
5283 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5284 if (!ea_list) {
5285 reply_nterror(
5286 req, NT_STATUS_INVALID_PARAMETER);
5287 return;
5289 break;
5292 case SMB_QUERY_POSIX_LOCK:
5294 if (fsp == NULL || fsp->fh->fd == -1) {
5295 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5296 return;
5299 if (total_data != POSIX_LOCK_DATA_SIZE) {
5300 reply_nterror(
5301 req, NT_STATUS_INVALID_PARAMETER);
5302 return;
5305 /* Copy the lock range data. */
5306 lock_data = (char *)TALLOC_MEMDUP(
5307 req, pdata, total_data);
5308 if (!lock_data) {
5309 reply_nterror(req, NT_STATUS_NO_MEMORY);
5310 return;
5312 lock_data_count = total_data;
5314 default:
5315 break;
5318 *pparams = (char *)SMB_REALLOC(*pparams,2);
5319 if (*pparams == NULL) {
5320 reply_nterror(req, NT_STATUS_NO_MEMORY);
5321 return;
5323 params = *pparams;
5324 SSVAL(params,0,0);
5327 * draft-leach-cifs-v1-spec-02.txt
5328 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5329 * says:
5331 * The requested information is placed in the Data portion of the
5332 * transaction response. For the information levels greater than 0x100,
5333 * the transaction response has 1 parameter word which should be
5334 * ignored by the client.
5336 * However Windows only follows this rule for the IS_NAME_VALID call.
5338 switch (info_level) {
5339 case SMB_INFO_IS_NAME_VALID:
5340 param_size = 0;
5341 break;
5344 if ((info_level & 0xFF00) == 0xFF00) {
5346 * We use levels that start with 0xFF00
5347 * internally to represent SMB2 specific levels
5349 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5350 return;
5353 status = smbd_do_qfilepathinfo(conn, req, info_level,
5354 fsp, smb_fname,
5355 delete_pending, write_time_ts,
5356 ea_list,
5357 lock_data_count, lock_data,
5358 req->flags2, max_data_bytes,
5359 ppdata, &data_size);
5360 if (!NT_STATUS_IS_OK(status)) {
5361 reply_nterror(req, status);
5362 return;
5365 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5366 max_data_bytes);
5368 return;
5371 /****************************************************************************
5372 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5373 code.
5374 ****************************************************************************/
5376 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5377 connection_struct *conn,
5378 struct smb_request *req,
5379 bool overwrite_if_exists,
5380 const struct smb_filename *smb_fname_old,
5381 struct smb_filename *smb_fname_new)
5383 NTSTATUS status = NT_STATUS_OK;
5385 /* source must already exist. */
5386 if (!VALID_STAT(smb_fname_old->st)) {
5387 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5390 if (VALID_STAT(smb_fname_new->st)) {
5391 if (overwrite_if_exists) {
5392 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5393 return NT_STATUS_FILE_IS_A_DIRECTORY;
5395 status = unlink_internals(conn,
5396 req,
5397 FILE_ATTRIBUTE_NORMAL,
5398 smb_fname_new,
5399 false);
5400 if (!NT_STATUS_IS_OK(status)) {
5401 return status;
5403 } else {
5404 /* Disallow if newname already exists. */
5405 return NT_STATUS_OBJECT_NAME_COLLISION;
5409 /* No links from a directory. */
5410 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5411 return NT_STATUS_FILE_IS_A_DIRECTORY;
5414 /* Setting a hardlink to/from a stream isn't currently supported. */
5415 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5416 is_ntfs_stream_smb_fname(smb_fname_new)) {
5417 return NT_STATUS_INVALID_PARAMETER;
5420 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5421 smb_fname_old->base_name, smb_fname_new->base_name));
5423 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5424 smb_fname_new->base_name) != 0) {
5425 status = map_nt_error_from_unix(errno);
5426 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5427 nt_errstr(status), smb_fname_old->base_name,
5428 smb_fname_new->base_name));
5430 return status;
5433 /****************************************************************************
5434 Deal with setting the time from any of the setfilepathinfo functions.
5435 ****************************************************************************/
5437 NTSTATUS smb_set_file_time(connection_struct *conn,
5438 files_struct *fsp,
5439 const struct smb_filename *smb_fname,
5440 struct smb_file_time *ft,
5441 bool setting_write_time)
5443 struct smb_filename smb_fname_base;
5444 uint32 action =
5445 FILE_NOTIFY_CHANGE_LAST_ACCESS
5446 |FILE_NOTIFY_CHANGE_LAST_WRITE
5447 |FILE_NOTIFY_CHANGE_CREATION;
5449 if (!VALID_STAT(smb_fname->st)) {
5450 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5453 /* get some defaults (no modifications) if any info is zero or -1. */
5454 if (null_timespec(ft->create_time)) {
5455 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5458 if (null_timespec(ft->atime)) {
5459 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5462 if (null_timespec(ft->mtime)) {
5463 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5466 if (!setting_write_time) {
5467 /* ft->mtime comes from change time, not write time. */
5468 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5471 /* Ensure the resolution is the correct for
5472 * what we can store on this filesystem. */
5474 round_timespec(conn->ts_res, &ft->create_time);
5475 round_timespec(conn->ts_res, &ft->ctime);
5476 round_timespec(conn->ts_res, &ft->atime);
5477 round_timespec(conn->ts_res, &ft->mtime);
5479 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5480 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5481 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5482 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5483 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5484 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5485 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5486 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5488 if (setting_write_time) {
5490 * This was a Windows setfileinfo on an open file.
5491 * NT does this a lot. We also need to
5492 * set the time here, as it can be read by
5493 * FindFirst/FindNext and with the patch for bug #2045
5494 * in smbd/fileio.c it ensures that this timestamp is
5495 * kept sticky even after a write. We save the request
5496 * away and will set it on file close and after a write. JRA.
5499 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5500 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5502 if (fsp != NULL) {
5503 if (fsp->base_fsp) {
5504 set_sticky_write_time_fsp(fsp->base_fsp,
5505 ft->mtime);
5506 } else {
5507 set_sticky_write_time_fsp(fsp, ft->mtime);
5509 } else {
5510 set_sticky_write_time_path(
5511 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5512 ft->mtime);
5516 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5518 /* Always call ntimes on the base, even if a stream was passed in. */
5519 smb_fname_base = *smb_fname;
5520 smb_fname_base.stream_name = NULL;
5522 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5523 return map_nt_error_from_unix(errno);
5526 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5527 smb_fname->base_name);
5528 return NT_STATUS_OK;
5531 /****************************************************************************
5532 Deal with setting the dosmode from any of the setfilepathinfo functions.
5533 ****************************************************************************/
5535 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5536 const struct smb_filename *smb_fname,
5537 uint32 dosmode)
5539 struct smb_filename *smb_fname_base = NULL;
5540 NTSTATUS status;
5542 if (!VALID_STAT(smb_fname->st)) {
5543 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5546 /* Always operate on the base_name, even if a stream was passed in. */
5547 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5548 NULL, &smb_fname->st,
5549 &smb_fname_base);
5550 if (!NT_STATUS_IS_OK(status)) {
5551 return status;
5554 if (dosmode) {
5555 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5556 dosmode |= aDIR;
5557 } else {
5558 dosmode &= ~aDIR;
5562 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5564 /* check the mode isn't different, before changing it */
5565 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5566 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5567 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5568 (unsigned int)dosmode));
5570 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5571 false)) {
5572 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5573 "%s failed (%s)\n",
5574 smb_fname_str_dbg(smb_fname_base),
5575 strerror(errno)));
5576 status = map_nt_error_from_unix(errno);
5577 goto out;
5580 status = NT_STATUS_OK;
5581 out:
5582 TALLOC_FREE(smb_fname_base);
5583 return status;
5586 /****************************************************************************
5587 Deal with setting the size from any of the setfilepathinfo functions.
5588 ****************************************************************************/
5590 static NTSTATUS smb_set_file_size(connection_struct *conn,
5591 struct smb_request *req,
5592 files_struct *fsp,
5593 const struct smb_filename *smb_fname,
5594 const SMB_STRUCT_STAT *psbuf,
5595 SMB_OFF_T size,
5596 bool fail_after_createfile)
5598 NTSTATUS status = NT_STATUS_OK;
5599 struct smb_filename *smb_fname_tmp = NULL;
5600 files_struct *new_fsp = NULL;
5602 if (!VALID_STAT(*psbuf)) {
5603 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5606 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5608 if (size == get_file_size_stat(psbuf)) {
5609 return NT_STATUS_OK;
5612 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5613 smb_fname_str_dbg(smb_fname), (double)size));
5615 if (fsp && fsp->fh->fd != -1) {
5616 /* Handle based call. */
5617 if (vfs_set_filelen(fsp, size) == -1) {
5618 return map_nt_error_from_unix(errno);
5620 trigger_write_time_update_immediate(fsp);
5621 return NT_STATUS_OK;
5624 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5625 if (!NT_STATUS_IS_OK(status)) {
5626 return status;
5629 smb_fname_tmp->st = *psbuf;
5631 status = SMB_VFS_CREATE_FILE(
5632 conn, /* conn */
5633 req, /* req */
5634 0, /* root_dir_fid */
5635 smb_fname_tmp, /* fname */
5636 FILE_WRITE_DATA, /* access_mask */
5637 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5638 FILE_SHARE_DELETE),
5639 FILE_OPEN, /* create_disposition*/
5640 0, /* create_options */
5641 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5642 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5643 0, /* allocation_size */
5644 0, /* private_flags */
5645 NULL, /* sd */
5646 NULL, /* ea_list */
5647 &new_fsp, /* result */
5648 NULL); /* pinfo */
5650 TALLOC_FREE(smb_fname_tmp);
5652 if (!NT_STATUS_IS_OK(status)) {
5653 /* NB. We check for open_was_deferred in the caller. */
5654 return status;
5657 /* See RAW-SFILEINFO-END-OF-FILE */
5658 if (fail_after_createfile) {
5659 close_file(req, new_fsp,NORMAL_CLOSE);
5660 return NT_STATUS_INVALID_LEVEL;
5663 if (vfs_set_filelen(new_fsp, size) == -1) {
5664 status = map_nt_error_from_unix(errno);
5665 close_file(req, new_fsp,NORMAL_CLOSE);
5666 return status;
5669 trigger_write_time_update_immediate(new_fsp);
5670 close_file(req, new_fsp,NORMAL_CLOSE);
5671 return NT_STATUS_OK;
5674 /****************************************************************************
5675 Deal with SMB_INFO_SET_EA.
5676 ****************************************************************************/
5678 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5679 const char *pdata,
5680 int total_data,
5681 files_struct *fsp,
5682 const struct smb_filename *smb_fname)
5684 struct ea_list *ea_list = NULL;
5685 TALLOC_CTX *ctx = NULL;
5686 NTSTATUS status = NT_STATUS_OK;
5688 if (total_data < 10) {
5690 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5691 length. They seem to have no effect. Bug #3212. JRA */
5693 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5694 /* We're done. We only get EA info in this call. */
5695 return NT_STATUS_OK;
5698 return NT_STATUS_INVALID_PARAMETER;
5701 if (IVAL(pdata,0) > total_data) {
5702 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5703 IVAL(pdata,0), (unsigned int)total_data));
5704 return NT_STATUS_INVALID_PARAMETER;
5707 ctx = talloc_tos();
5708 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5709 if (!ea_list) {
5710 return NT_STATUS_INVALID_PARAMETER;
5712 status = set_ea(conn, fsp, smb_fname, ea_list);
5714 return status;
5717 /****************************************************************************
5718 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5719 ****************************************************************************/
5721 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5722 const char *pdata,
5723 int total_data,
5724 files_struct *fsp)
5726 struct ea_list *ea_list = NULL;
5727 NTSTATUS status;
5729 if (!fsp) {
5730 return NT_STATUS_INVALID_HANDLE;
5733 if (!lp_ea_support(SNUM(conn))) {
5734 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5735 "EA's not supported.\n",
5736 (unsigned int)total_data));
5737 return NT_STATUS_EAS_NOT_SUPPORTED;
5740 if (total_data < 10) {
5741 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5742 "too small.\n",
5743 (unsigned int)total_data));
5744 return NT_STATUS_INVALID_PARAMETER;
5747 ea_list = read_nttrans_ea_list(talloc_tos(),
5748 pdata,
5749 total_data);
5751 if (!ea_list) {
5752 return NT_STATUS_INVALID_PARAMETER;
5754 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5756 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5757 smb_fname_str_dbg(fsp->fsp_name),
5758 nt_errstr(status) ));
5760 return status;
5764 /****************************************************************************
5765 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5766 ****************************************************************************/
5768 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5769 const char *pdata,
5770 int total_data,
5771 files_struct *fsp,
5772 struct smb_filename *smb_fname)
5774 NTSTATUS status = NT_STATUS_OK;
5775 bool delete_on_close;
5776 uint32 dosmode = 0;
5778 if (total_data < 1) {
5779 return NT_STATUS_INVALID_PARAMETER;
5782 if (fsp == NULL) {
5783 return NT_STATUS_INVALID_HANDLE;
5786 delete_on_close = (CVAL(pdata,0) ? True : False);
5787 dosmode = dos_mode(conn, smb_fname);
5789 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5790 "delete_on_close = %u\n",
5791 smb_fname_str_dbg(smb_fname),
5792 (unsigned int)dosmode,
5793 (unsigned int)delete_on_close ));
5795 if (delete_on_close) {
5796 status = can_set_delete_on_close(fsp, dosmode);
5797 if (!NT_STATUS_IS_OK(status)) {
5798 return status;
5802 /* The set is across all open files on this dev/inode pair. */
5803 if (!set_delete_on_close(fsp, delete_on_close,
5804 &conn->server_info->utok)) {
5805 return NT_STATUS_ACCESS_DENIED;
5807 return NT_STATUS_OK;
5810 /****************************************************************************
5811 Deal with SMB_FILE_POSITION_INFORMATION.
5812 ****************************************************************************/
5814 static NTSTATUS smb_file_position_information(connection_struct *conn,
5815 const char *pdata,
5816 int total_data,
5817 files_struct *fsp)
5819 uint64_t position_information;
5821 if (total_data < 8) {
5822 return NT_STATUS_INVALID_PARAMETER;
5825 if (fsp == NULL) {
5826 /* Ignore on pathname based set. */
5827 return NT_STATUS_OK;
5830 position_information = (uint64_t)IVAL(pdata,0);
5831 #ifdef LARGE_SMB_OFF_T
5832 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5833 #else /* LARGE_SMB_OFF_T */
5834 if (IVAL(pdata,4) != 0) {
5835 /* more than 32 bits? */
5836 return NT_STATUS_INVALID_PARAMETER;
5838 #endif /* LARGE_SMB_OFF_T */
5840 DEBUG(10,("smb_file_position_information: Set file position "
5841 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5842 (double)position_information));
5843 fsp->fh->position_information = position_information;
5844 return NT_STATUS_OK;
5847 /****************************************************************************
5848 Deal with SMB_FILE_MODE_INFORMATION.
5849 ****************************************************************************/
5851 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5852 const char *pdata,
5853 int total_data)
5855 uint32 mode;
5857 if (total_data < 4) {
5858 return NT_STATUS_INVALID_PARAMETER;
5860 mode = IVAL(pdata,0);
5861 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5862 return NT_STATUS_INVALID_PARAMETER;
5864 return NT_STATUS_OK;
5867 /****************************************************************************
5868 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5869 ****************************************************************************/
5871 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5872 struct smb_request *req,
5873 const char *pdata,
5874 int total_data,
5875 const struct smb_filename *smb_fname)
5877 char *link_target = NULL;
5878 const char *newname = smb_fname->base_name;
5879 TALLOC_CTX *ctx = talloc_tos();
5881 /* Set a symbolic link. */
5882 /* Don't allow this if follow links is false. */
5884 if (total_data == 0) {
5885 return NT_STATUS_INVALID_PARAMETER;
5888 if (!lp_symlinks(SNUM(conn))) {
5889 return NT_STATUS_ACCESS_DENIED;
5892 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5893 total_data, STR_TERMINATE);
5895 if (!link_target) {
5896 return NT_STATUS_INVALID_PARAMETER;
5899 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5900 newname, link_target ));
5902 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5903 return map_nt_error_from_unix(errno);
5906 return NT_STATUS_OK;
5909 /****************************************************************************
5910 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5911 ****************************************************************************/
5913 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5914 struct smb_request *req,
5915 const char *pdata, int total_data,
5916 struct smb_filename *smb_fname_new)
5918 char *oldname = NULL;
5919 struct smb_filename *smb_fname_old = NULL;
5920 TALLOC_CTX *ctx = talloc_tos();
5921 NTSTATUS status = NT_STATUS_OK;
5923 /* Set a hard link. */
5924 if (total_data == 0) {
5925 return NT_STATUS_INVALID_PARAMETER;
5928 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5929 total_data, STR_TERMINATE, &status);
5930 if (!NT_STATUS_IS_OK(status)) {
5931 return status;
5934 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5935 smb_fname_str_dbg(smb_fname_new), oldname));
5937 status = filename_convert(ctx,
5938 conn,
5939 req->flags2 & FLAGS2_DFS_PATHNAMES,
5940 oldname,
5942 NULL,
5943 &smb_fname_old);
5944 if (!NT_STATUS_IS_OK(status)) {
5945 return status;
5948 return hardlink_internals(ctx, conn, req, false,
5949 smb_fname_old, smb_fname_new);
5952 /****************************************************************************
5953 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5954 ****************************************************************************/
5956 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5957 struct smb_request *req,
5958 const char *pdata,
5959 int total_data,
5960 files_struct *fsp,
5961 struct smb_filename *smb_fname_src)
5963 bool overwrite;
5964 uint32_t len;
5965 char *newname = NULL;
5966 struct smb_filename *smb_fname_dst = NULL;
5967 NTSTATUS status = NT_STATUS_OK;
5968 TALLOC_CTX *ctx = talloc_tos();
5970 if (!fsp) {
5971 return NT_STATUS_INVALID_HANDLE;
5974 if (total_data < 20) {
5975 return NT_STATUS_INVALID_PARAMETER;
5978 overwrite = (CVAL(pdata,0) ? True : False);
5979 len = IVAL(pdata,16);
5981 if (len > (total_data - 20) || (len == 0)) {
5982 return NT_STATUS_INVALID_PARAMETER;
5985 srvstr_get_path(ctx, pdata, req->flags2, &newname,
5986 &pdata[20], len, STR_TERMINATE,
5987 &status);
5988 if (!NT_STATUS_IS_OK(status)) {
5989 return status;
5992 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
5993 newname));
5995 status = filename_convert(ctx,
5996 conn,
5997 req->flags2 & FLAGS2_DFS_PATHNAMES,
5998 newname,
6000 NULL,
6001 &smb_fname_dst);
6002 if (!NT_STATUS_IS_OK(status)) {
6003 return status;
6006 if (fsp->base_fsp) {
6007 /* newname must be a stream name. */
6008 if (newname[0] != ':') {
6009 return NT_STATUS_NOT_SUPPORTED;
6012 /* Create an smb_fname to call rename_internals_fsp() with. */
6013 status = create_synthetic_smb_fname(talloc_tos(),
6014 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6015 &smb_fname_dst);
6016 if (!NT_STATUS_IS_OK(status)) {
6017 goto out;
6021 * Set the original last component, since
6022 * rename_internals_fsp() requires it.
6024 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6025 newname);
6026 if (smb_fname_dst->original_lcomp == NULL) {
6027 status = NT_STATUS_NO_MEMORY;
6028 goto out;
6033 DEBUG(10,("smb2_file_rename_information: "
6034 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6035 fsp->fnum, fsp_str_dbg(fsp),
6036 smb_fname_str_dbg(smb_fname_dst)));
6037 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6038 overwrite);
6040 out:
6041 TALLOC_FREE(smb_fname_dst);
6042 return status;
6045 static NTSTATUS smb_file_link_information(connection_struct *conn,
6046 struct smb_request *req,
6047 const char *pdata,
6048 int total_data,
6049 files_struct *fsp,
6050 struct smb_filename *smb_fname_src)
6052 bool overwrite;
6053 uint32_t len;
6054 char *newname = NULL;
6055 struct smb_filename *smb_fname_dst = NULL;
6056 NTSTATUS status = NT_STATUS_OK;
6057 TALLOC_CTX *ctx = talloc_tos();
6059 if (!fsp) {
6060 return NT_STATUS_INVALID_HANDLE;
6063 if (total_data < 20) {
6064 return NT_STATUS_INVALID_PARAMETER;
6067 overwrite = (CVAL(pdata,0) ? true : false);
6068 len = IVAL(pdata,16);
6070 if (len > (total_data - 20) || (len == 0)) {
6071 return NT_STATUS_INVALID_PARAMETER;
6074 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6075 &pdata[20], len, STR_TERMINATE,
6076 &status);
6077 if (!NT_STATUS_IS_OK(status)) {
6078 return status;
6081 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6082 newname));
6084 status = filename_convert(ctx,
6085 conn,
6086 req->flags2 & FLAGS2_DFS_PATHNAMES,
6087 newname,
6089 NULL,
6090 &smb_fname_dst);
6091 if (!NT_STATUS_IS_OK(status)) {
6092 return status;
6095 if (fsp->base_fsp) {
6096 /* No stream names. */
6097 return NT_STATUS_NOT_SUPPORTED;
6100 DEBUG(10,("smb_file_link_information: "
6101 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6102 fsp->fnum, fsp_str_dbg(fsp),
6103 smb_fname_str_dbg(smb_fname_dst)));
6104 status = hardlink_internals(ctx,
6105 conn,
6106 req,
6107 overwrite,
6108 fsp->fsp_name,
6109 smb_fname_dst);
6111 TALLOC_FREE(smb_fname_dst);
6112 return status;
6115 /****************************************************************************
6116 Deal with SMB_FILE_RENAME_INFORMATION.
6117 ****************************************************************************/
6119 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6120 struct smb_request *req,
6121 const char *pdata,
6122 int total_data,
6123 files_struct *fsp,
6124 struct smb_filename *smb_fname_src)
6126 bool overwrite;
6127 uint32 root_fid;
6128 uint32 len;
6129 char *newname = NULL;
6130 struct smb_filename *smb_fname_dst = NULL;
6131 bool dest_has_wcard = False;
6132 NTSTATUS status = NT_STATUS_OK;
6133 char *p;
6134 TALLOC_CTX *ctx = talloc_tos();
6136 if (total_data < 13) {
6137 return NT_STATUS_INVALID_PARAMETER;
6140 overwrite = (CVAL(pdata,0) ? True : False);
6141 root_fid = IVAL(pdata,4);
6142 len = IVAL(pdata,8);
6144 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6145 return NT_STATUS_INVALID_PARAMETER;
6148 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6149 len, 0, &status,
6150 &dest_has_wcard);
6151 if (!NT_STATUS_IS_OK(status)) {
6152 return status;
6155 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6156 newname));
6158 status = resolve_dfspath_wcard(ctx, conn,
6159 req->flags2 & FLAGS2_DFS_PATHNAMES,
6160 newname,
6161 true,
6162 &newname,
6163 &dest_has_wcard);
6164 if (!NT_STATUS_IS_OK(status)) {
6165 return status;
6168 /* Check the new name has no '/' characters. */
6169 if (strchr_m(newname, '/')) {
6170 return NT_STATUS_NOT_SUPPORTED;
6173 if (fsp && fsp->base_fsp) {
6174 /* newname must be a stream name. */
6175 if (newname[0] != ':') {
6176 return NT_STATUS_NOT_SUPPORTED;
6179 /* Create an smb_fname to call rename_internals_fsp() with. */
6180 status = create_synthetic_smb_fname(talloc_tos(),
6181 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6182 &smb_fname_dst);
6183 if (!NT_STATUS_IS_OK(status)) {
6184 goto out;
6188 * Set the original last component, since
6189 * rename_internals_fsp() requires it.
6191 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6192 newname);
6193 if (smb_fname_dst->original_lcomp == NULL) {
6194 status = NT_STATUS_NO_MEMORY;
6195 goto out;
6198 } else {
6200 * Build up an smb_fname_dst based on the filename passed in.
6201 * We basically just strip off the last component, and put on
6202 * the newname instead.
6204 char *base_name = NULL;
6206 /* newname must *not* be a stream name. */
6207 if (newname[0] == ':') {
6208 return NT_STATUS_NOT_SUPPORTED;
6212 * Strip off the last component (filename) of the path passed
6213 * in.
6215 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6216 if (!base_name) {
6217 return NT_STATUS_NO_MEMORY;
6219 p = strrchr_m(base_name, '/');
6220 if (p) {
6221 p[1] = '\0';
6222 } else {
6223 base_name = talloc_strdup(ctx, "./");
6224 if (!base_name) {
6225 return NT_STATUS_NO_MEMORY;
6228 /* Append the new name. */
6229 base_name = talloc_asprintf_append(base_name,
6230 "%s",
6231 newname);
6232 if (!base_name) {
6233 return NT_STATUS_NO_MEMORY;
6236 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6237 (UCF_SAVE_LCOMP |
6238 (dest_has_wcard ?
6239 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6240 0)));
6242 /* If an error we expect this to be
6243 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6245 if (!NT_STATUS_IS_OK(status)) {
6246 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6247 status)) {
6248 goto out;
6250 /* Create an smb_fname to call rename_internals_fsp() */
6251 status = create_synthetic_smb_fname(ctx,
6252 base_name, NULL,
6253 NULL,
6254 &smb_fname_dst);
6255 if (!NT_STATUS_IS_OK(status)) {
6256 goto out;
6261 if (fsp) {
6262 DEBUG(10,("smb_file_rename_information: "
6263 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6264 fsp->fnum, fsp_str_dbg(fsp),
6265 smb_fname_str_dbg(smb_fname_dst)));
6266 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6267 overwrite);
6268 } else {
6269 DEBUG(10,("smb_file_rename_information: "
6270 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6271 smb_fname_str_dbg(smb_fname_src),
6272 smb_fname_str_dbg(smb_fname_dst)));
6273 status = rename_internals(ctx, conn, req, smb_fname_src,
6274 smb_fname_dst, 0, overwrite, false,
6275 dest_has_wcard,
6276 FILE_WRITE_ATTRIBUTES);
6278 out:
6279 TALLOC_FREE(smb_fname_dst);
6280 return status;
6283 /****************************************************************************
6284 Deal with SMB_SET_POSIX_ACL.
6285 ****************************************************************************/
6287 #if defined(HAVE_POSIX_ACLS)
6288 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6289 const char *pdata,
6290 int total_data,
6291 files_struct *fsp,
6292 const struct smb_filename *smb_fname)
6294 uint16 posix_acl_version;
6295 uint16 num_file_acls;
6296 uint16 num_def_acls;
6297 bool valid_file_acls = True;
6298 bool valid_def_acls = True;
6300 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6301 return NT_STATUS_INVALID_PARAMETER;
6303 posix_acl_version = SVAL(pdata,0);
6304 num_file_acls = SVAL(pdata,2);
6305 num_def_acls = SVAL(pdata,4);
6307 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6308 valid_file_acls = False;
6309 num_file_acls = 0;
6312 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6313 valid_def_acls = False;
6314 num_def_acls = 0;
6317 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6318 return NT_STATUS_INVALID_PARAMETER;
6321 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6322 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6323 return NT_STATUS_INVALID_PARAMETER;
6326 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6327 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6328 (unsigned int)num_file_acls,
6329 (unsigned int)num_def_acls));
6331 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6332 smb_fname->base_name, num_file_acls,
6333 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6334 return map_nt_error_from_unix(errno);
6337 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6338 smb_fname->base_name, &smb_fname->st, num_def_acls,
6339 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6340 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6341 return map_nt_error_from_unix(errno);
6343 return NT_STATUS_OK;
6345 #endif
6347 /****************************************************************************
6348 Deal with SMB_SET_POSIX_LOCK.
6349 ****************************************************************************/
6351 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6352 struct smb_request *req,
6353 const char *pdata,
6354 int total_data,
6355 files_struct *fsp)
6357 uint64_t count;
6358 uint64_t offset;
6359 uint64_t smblctx;
6360 bool blocking_lock = False;
6361 enum brl_type lock_type;
6363 NTSTATUS status = NT_STATUS_OK;
6365 if (fsp == NULL || fsp->fh->fd == -1) {
6366 return NT_STATUS_INVALID_HANDLE;
6369 if (total_data != POSIX_LOCK_DATA_SIZE) {
6370 return NT_STATUS_INVALID_PARAMETER;
6373 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6374 case POSIX_LOCK_TYPE_READ:
6375 lock_type = READ_LOCK;
6376 break;
6377 case POSIX_LOCK_TYPE_WRITE:
6378 /* Return the right POSIX-mappable error code for files opened read-only. */
6379 if (!fsp->can_write) {
6380 return NT_STATUS_INVALID_HANDLE;
6382 lock_type = WRITE_LOCK;
6383 break;
6384 case POSIX_LOCK_TYPE_UNLOCK:
6385 lock_type = UNLOCK_LOCK;
6386 break;
6387 default:
6388 return NT_STATUS_INVALID_PARAMETER;
6391 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6392 blocking_lock = False;
6393 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6394 blocking_lock = True;
6395 } else {
6396 return NT_STATUS_INVALID_PARAMETER;
6399 if (!lp_blocking_locks(SNUM(conn))) {
6400 blocking_lock = False;
6403 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6404 #if defined(HAVE_LONGLONG)
6405 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6406 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6407 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6408 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6409 #else /* HAVE_LONGLONG */
6410 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6411 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6412 #endif /* HAVE_LONGLONG */
6414 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6415 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6416 fsp_str_dbg(fsp),
6417 (unsigned int)lock_type,
6418 (unsigned long long)smblctx,
6419 (double)count,
6420 (double)offset ));
6422 if (lock_type == UNLOCK_LOCK) {
6423 status = do_unlock(smbd_messaging_context(),
6424 fsp,
6425 smblctx,
6426 count,
6427 offset,
6428 POSIX_LOCK);
6429 } else {
6430 uint64_t block_smblctx;
6432 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6433 fsp,
6434 smblctx,
6435 count,
6436 offset,
6437 lock_type,
6438 POSIX_LOCK,
6439 blocking_lock,
6440 &status,
6441 &block_smblctx,
6442 NULL);
6444 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6446 * A blocking lock was requested. Package up
6447 * this smb into a queued request and push it
6448 * onto the blocking lock queue.
6450 if(push_blocking_lock_request(br_lck,
6451 req,
6452 fsp,
6453 -1, /* infinite timeout. */
6455 smblctx,
6456 lock_type,
6457 POSIX_LOCK,
6458 offset,
6459 count,
6460 block_smblctx)) {
6461 TALLOC_FREE(br_lck);
6462 return status;
6465 TALLOC_FREE(br_lck);
6468 return status;
6471 /****************************************************************************
6472 Deal with SMB_SET_FILE_BASIC_INFO.
6473 ****************************************************************************/
6475 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6476 const char *pdata,
6477 int total_data,
6478 files_struct *fsp,
6479 const struct smb_filename *smb_fname)
6481 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6482 struct smb_file_time ft;
6483 uint32 dosmode = 0;
6484 NTSTATUS status = NT_STATUS_OK;
6486 ZERO_STRUCT(ft);
6488 if (total_data < 36) {
6489 return NT_STATUS_INVALID_PARAMETER;
6492 /* Set the attributes */
6493 dosmode = IVAL(pdata,32);
6494 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6495 if (!NT_STATUS_IS_OK(status)) {
6496 return status;
6499 /* create time */
6500 ft.create_time = interpret_long_date(pdata);
6502 /* access time */
6503 ft.atime = interpret_long_date(pdata+8);
6505 /* write time. */
6506 ft.mtime = interpret_long_date(pdata+16);
6508 /* change time. */
6509 ft.ctime = interpret_long_date(pdata+24);
6511 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6512 smb_fname_str_dbg(smb_fname)));
6514 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6515 true);
6518 /****************************************************************************
6519 Deal with SMB_INFO_STANDARD.
6520 ****************************************************************************/
6522 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6523 const char *pdata,
6524 int total_data,
6525 files_struct *fsp,
6526 const struct smb_filename *smb_fname)
6528 struct smb_file_time ft;
6530 ZERO_STRUCT(ft);
6532 if (total_data < 12) {
6533 return NT_STATUS_INVALID_PARAMETER;
6536 /* create time */
6537 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6538 /* access time */
6539 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6540 /* write time */
6541 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6543 DEBUG(10,("smb_set_info_standard: file %s\n",
6544 smb_fname_str_dbg(smb_fname)));
6546 return smb_set_file_time(conn,
6547 fsp,
6548 smb_fname,
6549 &ft,
6550 true);
6553 /****************************************************************************
6554 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6555 ****************************************************************************/
6557 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6558 struct smb_request *req,
6559 const char *pdata,
6560 int total_data,
6561 files_struct *fsp,
6562 struct smb_filename *smb_fname)
6564 uint64_t allocation_size = 0;
6565 NTSTATUS status = NT_STATUS_OK;
6566 files_struct *new_fsp = NULL;
6568 if (!VALID_STAT(smb_fname->st)) {
6569 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6572 if (total_data < 8) {
6573 return NT_STATUS_INVALID_PARAMETER;
6576 allocation_size = (uint64_t)IVAL(pdata,0);
6577 #ifdef LARGE_SMB_OFF_T
6578 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6579 #else /* LARGE_SMB_OFF_T */
6580 if (IVAL(pdata,4) != 0) {
6581 /* more than 32 bits? */
6582 return NT_STATUS_INVALID_PARAMETER;
6584 #endif /* LARGE_SMB_OFF_T */
6586 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6587 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6588 (double)allocation_size));
6590 if (allocation_size) {
6591 allocation_size = smb_roundup(conn, allocation_size);
6594 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6595 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6596 (double)allocation_size));
6598 if (fsp && fsp->fh->fd != -1) {
6599 /* Open file handle. */
6600 /* Only change if needed. */
6601 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6602 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6603 return map_nt_error_from_unix(errno);
6606 /* But always update the time. */
6608 * This is equivalent to a write. Ensure it's seen immediately
6609 * if there are no pending writes.
6611 trigger_write_time_update_immediate(fsp);
6612 return NT_STATUS_OK;
6615 /* Pathname or stat or directory file. */
6616 status = SMB_VFS_CREATE_FILE(
6617 conn, /* conn */
6618 req, /* req */
6619 0, /* root_dir_fid */
6620 smb_fname, /* fname */
6621 FILE_WRITE_DATA, /* access_mask */
6622 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6623 FILE_SHARE_DELETE),
6624 FILE_OPEN, /* create_disposition*/
6625 0, /* create_options */
6626 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6627 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6628 0, /* allocation_size */
6629 0, /* private_flags */
6630 NULL, /* sd */
6631 NULL, /* ea_list */
6632 &new_fsp, /* result */
6633 NULL); /* pinfo */
6635 if (!NT_STATUS_IS_OK(status)) {
6636 /* NB. We check for open_was_deferred in the caller. */
6637 return status;
6640 /* Only change if needed. */
6641 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6642 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6643 status = map_nt_error_from_unix(errno);
6644 close_file(req, new_fsp, NORMAL_CLOSE);
6645 return status;
6649 /* Changing the allocation size should set the last mod time. */
6651 * This is equivalent to a write. Ensure it's seen immediately
6652 * if there are no pending writes.
6654 trigger_write_time_update_immediate(new_fsp);
6656 close_file(req, new_fsp, NORMAL_CLOSE);
6657 return NT_STATUS_OK;
6660 /****************************************************************************
6661 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6662 ****************************************************************************/
6664 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6665 struct smb_request *req,
6666 const char *pdata,
6667 int total_data,
6668 files_struct *fsp,
6669 const struct smb_filename *smb_fname,
6670 bool fail_after_createfile)
6672 SMB_OFF_T size;
6674 if (total_data < 8) {
6675 return NT_STATUS_INVALID_PARAMETER;
6678 size = IVAL(pdata,0);
6679 #ifdef LARGE_SMB_OFF_T
6680 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6681 #else /* LARGE_SMB_OFF_T */
6682 if (IVAL(pdata,4) != 0) {
6683 /* more than 32 bits? */
6684 return NT_STATUS_INVALID_PARAMETER;
6686 #endif /* LARGE_SMB_OFF_T */
6687 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6688 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6689 (double)size));
6691 return smb_set_file_size(conn, req,
6692 fsp,
6693 smb_fname,
6694 &smb_fname->st,
6695 size,
6696 fail_after_createfile);
6699 /****************************************************************************
6700 Allow a UNIX info mknod.
6701 ****************************************************************************/
6703 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6704 const char *pdata,
6705 int total_data,
6706 const struct smb_filename *smb_fname)
6708 uint32 file_type = IVAL(pdata,56);
6709 #if defined(HAVE_MAKEDEV)
6710 uint32 dev_major = IVAL(pdata,60);
6711 uint32 dev_minor = IVAL(pdata,68);
6712 #endif
6713 SMB_DEV_T dev = (SMB_DEV_T)0;
6714 uint32 raw_unixmode = IVAL(pdata,84);
6715 NTSTATUS status;
6716 mode_t unixmode;
6718 if (total_data < 100) {
6719 return NT_STATUS_INVALID_PARAMETER;
6722 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6723 PERM_NEW_FILE, &unixmode);
6724 if (!NT_STATUS_IS_OK(status)) {
6725 return status;
6728 #if defined(HAVE_MAKEDEV)
6729 dev = makedev(dev_major, dev_minor);
6730 #endif
6732 switch (file_type) {
6733 #if defined(S_IFIFO)
6734 case UNIX_TYPE_FIFO:
6735 unixmode |= S_IFIFO;
6736 break;
6737 #endif
6738 #if defined(S_IFSOCK)
6739 case UNIX_TYPE_SOCKET:
6740 unixmode |= S_IFSOCK;
6741 break;
6742 #endif
6743 #if defined(S_IFCHR)
6744 case UNIX_TYPE_CHARDEV:
6745 unixmode |= S_IFCHR;
6746 break;
6747 #endif
6748 #if defined(S_IFBLK)
6749 case UNIX_TYPE_BLKDEV:
6750 unixmode |= S_IFBLK;
6751 break;
6752 #endif
6753 default:
6754 return NT_STATUS_INVALID_PARAMETER;
6757 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6758 "%.0f mode 0%o for file %s\n", (double)dev,
6759 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6761 /* Ok - do the mknod. */
6762 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6763 return map_nt_error_from_unix(errno);
6766 /* If any of the other "set" calls fail we
6767 * don't want to end up with a half-constructed mknod.
6770 if (lp_inherit_perms(SNUM(conn))) {
6771 char *parent;
6772 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6773 &parent, NULL)) {
6774 return NT_STATUS_NO_MEMORY;
6776 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6777 unixmode);
6778 TALLOC_FREE(parent);
6781 return NT_STATUS_OK;
6784 /****************************************************************************
6785 Deal with SMB_SET_FILE_UNIX_BASIC.
6786 ****************************************************************************/
6788 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6789 struct smb_request *req,
6790 const char *pdata,
6791 int total_data,
6792 files_struct *fsp,
6793 const struct smb_filename *smb_fname)
6795 struct smb_file_time ft;
6796 uint32 raw_unixmode;
6797 mode_t unixmode;
6798 SMB_OFF_T size = 0;
6799 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6800 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6801 NTSTATUS status = NT_STATUS_OK;
6802 bool delete_on_fail = False;
6803 enum perm_type ptype;
6804 files_struct *all_fsps = NULL;
6805 bool modify_mtime = true;
6806 struct file_id id;
6807 SMB_STRUCT_STAT sbuf;
6809 ZERO_STRUCT(ft);
6811 if (total_data < 100) {
6812 return NT_STATUS_INVALID_PARAMETER;
6815 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6816 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6817 size=IVAL(pdata,0); /* first 8 Bytes are size */
6818 #ifdef LARGE_SMB_OFF_T
6819 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6820 #else /* LARGE_SMB_OFF_T */
6821 if (IVAL(pdata,4) != 0) {
6822 /* more than 32 bits? */
6823 return NT_STATUS_INVALID_PARAMETER;
6825 #endif /* LARGE_SMB_OFF_T */
6828 ft.atime = interpret_long_date(pdata+24); /* access_time */
6829 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6830 set_owner = (uid_t)IVAL(pdata,40);
6831 set_grp = (gid_t)IVAL(pdata,48);
6832 raw_unixmode = IVAL(pdata,84);
6834 if (VALID_STAT(smb_fname->st)) {
6835 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6836 ptype = PERM_EXISTING_DIR;
6837 } else {
6838 ptype = PERM_EXISTING_FILE;
6840 } else {
6841 ptype = PERM_NEW_FILE;
6844 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6845 ptype, &unixmode);
6846 if (!NT_STATUS_IS_OK(status)) {
6847 return status;
6850 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6851 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6852 smb_fname_str_dbg(smb_fname), (double)size,
6853 (unsigned int)set_owner, (unsigned int)set_grp,
6854 (int)raw_unixmode));
6856 sbuf = smb_fname->st;
6858 if (!VALID_STAT(sbuf)) {
6859 struct smb_filename *smb_fname_tmp = NULL;
6861 * The only valid use of this is to create character and block
6862 * devices, and named pipes. This is deprecated (IMHO) and
6863 * a new info level should be used for mknod. JRA.
6866 status = smb_unix_mknod(conn,
6867 pdata,
6868 total_data,
6869 smb_fname);
6870 if (!NT_STATUS_IS_OK(status)) {
6871 return status;
6874 status = copy_smb_filename(talloc_tos(), smb_fname,
6875 &smb_fname_tmp);
6876 if (!NT_STATUS_IS_OK(status)) {
6877 return status;
6880 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6881 status = map_nt_error_from_unix(errno);
6882 TALLOC_FREE(smb_fname_tmp);
6883 SMB_VFS_UNLINK(conn, smb_fname);
6884 return status;
6887 sbuf = smb_fname_tmp->st;
6888 TALLOC_FREE(smb_fname_tmp);
6890 /* Ensure we don't try and change anything else. */
6891 raw_unixmode = SMB_MODE_NO_CHANGE;
6892 size = get_file_size_stat(&sbuf);
6893 ft.atime = sbuf.st_ex_atime;
6894 ft.mtime = sbuf.st_ex_mtime;
6896 * We continue here as we might want to change the
6897 * owner uid/gid.
6899 delete_on_fail = True;
6902 #if 1
6903 /* Horrible backwards compatibility hack as an old server bug
6904 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6905 * */
6907 if (!size) {
6908 size = get_file_size_stat(&sbuf);
6910 #endif
6913 * Deal with the UNIX specific mode set.
6916 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6917 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6918 "setting mode 0%o for file %s\n",
6919 (unsigned int)unixmode,
6920 smb_fname_str_dbg(smb_fname)));
6921 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6922 return map_nt_error_from_unix(errno);
6927 * Deal with the UNIX specific uid set.
6930 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6931 (sbuf.st_ex_uid != set_owner)) {
6932 int ret;
6934 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6935 "changing owner %u for path %s\n",
6936 (unsigned int)set_owner,
6937 smb_fname_str_dbg(smb_fname)));
6939 if (S_ISLNK(sbuf.st_ex_mode)) {
6940 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6941 set_owner, (gid_t)-1);
6942 } else {
6943 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6944 set_owner, (gid_t)-1);
6947 if (ret != 0) {
6948 status = map_nt_error_from_unix(errno);
6949 if (delete_on_fail) {
6950 SMB_VFS_UNLINK(conn, smb_fname);
6952 return status;
6957 * Deal with the UNIX specific gid set.
6960 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6961 (sbuf.st_ex_gid != set_grp)) {
6962 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6963 "changing group %u for file %s\n",
6964 (unsigned int)set_owner,
6965 smb_fname_str_dbg(smb_fname)));
6966 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6967 set_grp) != 0) {
6968 status = map_nt_error_from_unix(errno);
6969 if (delete_on_fail) {
6970 SMB_VFS_UNLINK(conn, smb_fname);
6972 return status;
6976 /* Deal with any size changes. */
6978 status = smb_set_file_size(conn, req,
6979 fsp,
6980 smb_fname,
6981 &sbuf,
6982 size,
6983 false);
6984 if (!NT_STATUS_IS_OK(status)) {
6985 return status;
6988 /* Deal with any time changes. */
6989 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6990 /* No change, don't cancel anything. */
6991 return status;
6994 id = vfs_file_id_from_sbuf(conn, &sbuf);
6995 for(all_fsps = file_find_di_first(id); all_fsps;
6996 all_fsps = file_find_di_next(all_fsps)) {
6998 * We're setting the time explicitly for UNIX.
6999 * Cancel any pending changes over all handles.
7001 all_fsps->update_write_time_on_close = false;
7002 TALLOC_FREE(all_fsps->update_write_time_event);
7006 * Override the "setting_write_time"
7007 * parameter here as it almost does what
7008 * we need. Just remember if we modified
7009 * mtime and send the notify ourselves.
7011 if (null_timespec(ft.mtime)) {
7012 modify_mtime = false;
7015 status = smb_set_file_time(conn,
7016 fsp,
7017 smb_fname,
7018 &ft,
7019 false);
7020 if (modify_mtime) {
7021 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7022 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7024 return status;
7027 /****************************************************************************
7028 Deal with SMB_SET_FILE_UNIX_INFO2.
7029 ****************************************************************************/
7031 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7032 struct smb_request *req,
7033 const char *pdata,
7034 int total_data,
7035 files_struct *fsp,
7036 const struct smb_filename *smb_fname)
7038 NTSTATUS status;
7039 uint32 smb_fflags;
7040 uint32 smb_fmask;
7042 if (total_data < 116) {
7043 return NT_STATUS_INVALID_PARAMETER;
7046 /* Start by setting all the fields that are common between UNIX_BASIC
7047 * and UNIX_INFO2.
7049 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7050 fsp, smb_fname);
7051 if (!NT_STATUS_IS_OK(status)) {
7052 return status;
7055 smb_fflags = IVAL(pdata, 108);
7056 smb_fmask = IVAL(pdata, 112);
7058 /* NB: We should only attempt to alter the file flags if the client
7059 * sends a non-zero mask.
7061 if (smb_fmask != 0) {
7062 int stat_fflags = 0;
7064 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7065 smb_fmask, &stat_fflags)) {
7066 /* Client asked to alter a flag we don't understand. */
7067 return NT_STATUS_INVALID_PARAMETER;
7070 if (fsp && fsp->fh->fd != -1) {
7071 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7072 return NT_STATUS_NOT_SUPPORTED;
7073 } else {
7074 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7075 stat_fflags) != 0) {
7076 return map_nt_error_from_unix(errno);
7081 /* XXX: need to add support for changing the create_time here. You
7082 * can do this for paths on Darwin with setattrlist(2). The right way
7083 * to hook this up is probably by extending the VFS utimes interface.
7086 return NT_STATUS_OK;
7089 /****************************************************************************
7090 Create a directory with POSIX semantics.
7091 ****************************************************************************/
7093 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7094 struct smb_request *req,
7095 char **ppdata,
7096 int total_data,
7097 struct smb_filename *smb_fname,
7098 int *pdata_return_size)
7100 NTSTATUS status = NT_STATUS_OK;
7101 uint32 raw_unixmode = 0;
7102 uint32 mod_unixmode = 0;
7103 mode_t unixmode = (mode_t)0;
7104 files_struct *fsp = NULL;
7105 uint16 info_level_return = 0;
7106 int info;
7107 char *pdata = *ppdata;
7109 if (total_data < 18) {
7110 return NT_STATUS_INVALID_PARAMETER;
7113 raw_unixmode = IVAL(pdata,8);
7114 /* Next 4 bytes are not yet defined. */
7116 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7117 PERM_NEW_DIR, &unixmode);
7118 if (!NT_STATUS_IS_OK(status)) {
7119 return status;
7122 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7124 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7125 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7127 status = SMB_VFS_CREATE_FILE(
7128 conn, /* conn */
7129 req, /* req */
7130 0, /* root_dir_fid */
7131 smb_fname, /* fname */
7132 FILE_READ_ATTRIBUTES, /* access_mask */
7133 FILE_SHARE_NONE, /* share_access */
7134 FILE_CREATE, /* create_disposition*/
7135 FILE_DIRECTORY_FILE, /* create_options */
7136 mod_unixmode, /* file_attributes */
7137 0, /* oplock_request */
7138 0, /* allocation_size */
7139 0, /* private_flags */
7140 NULL, /* sd */
7141 NULL, /* ea_list */
7142 &fsp, /* result */
7143 &info); /* pinfo */
7145 if (NT_STATUS_IS_OK(status)) {
7146 close_file(req, fsp, NORMAL_CLOSE);
7149 info_level_return = SVAL(pdata,16);
7151 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7152 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7153 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7154 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7155 } else {
7156 *pdata_return_size = 12;
7159 /* Realloc the data size */
7160 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7161 if (*ppdata == NULL) {
7162 *pdata_return_size = 0;
7163 return NT_STATUS_NO_MEMORY;
7165 pdata = *ppdata;
7167 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7168 SSVAL(pdata,2,0); /* No fnum. */
7169 SIVAL(pdata,4,info); /* Was directory created. */
7171 switch (info_level_return) {
7172 case SMB_QUERY_FILE_UNIX_BASIC:
7173 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7174 SSVAL(pdata,10,0); /* Padding. */
7175 store_file_unix_basic(conn, pdata + 12, fsp,
7176 &smb_fname->st);
7177 break;
7178 case SMB_QUERY_FILE_UNIX_INFO2:
7179 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7180 SSVAL(pdata,10,0); /* Padding. */
7181 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7182 &smb_fname->st);
7183 break;
7184 default:
7185 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7186 SSVAL(pdata,10,0); /* Padding. */
7187 break;
7190 return status;
7193 /****************************************************************************
7194 Open/Create a file with POSIX semantics.
7195 ****************************************************************************/
7197 static NTSTATUS smb_posix_open(connection_struct *conn,
7198 struct smb_request *req,
7199 char **ppdata,
7200 int total_data,
7201 struct smb_filename *smb_fname,
7202 int *pdata_return_size)
7204 bool extended_oplock_granted = False;
7205 char *pdata = *ppdata;
7206 uint32 flags = 0;
7207 uint32 wire_open_mode = 0;
7208 uint32 raw_unixmode = 0;
7209 uint32 mod_unixmode = 0;
7210 uint32 create_disp = 0;
7211 uint32 access_mask = 0;
7212 uint32 create_options = 0;
7213 NTSTATUS status = NT_STATUS_OK;
7214 mode_t unixmode = (mode_t)0;
7215 files_struct *fsp = NULL;
7216 int oplock_request = 0;
7217 int info = 0;
7218 uint16 info_level_return = 0;
7220 if (total_data < 18) {
7221 return NT_STATUS_INVALID_PARAMETER;
7224 flags = IVAL(pdata,0);
7225 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7226 if (oplock_request) {
7227 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7230 wire_open_mode = IVAL(pdata,4);
7232 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7233 return smb_posix_mkdir(conn, req,
7234 ppdata,
7235 total_data,
7236 smb_fname,
7237 pdata_return_size);
7240 switch (wire_open_mode & SMB_ACCMODE) {
7241 case SMB_O_RDONLY:
7242 access_mask = FILE_READ_DATA;
7243 break;
7244 case SMB_O_WRONLY:
7245 access_mask = FILE_WRITE_DATA;
7246 break;
7247 case SMB_O_RDWR:
7248 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7249 break;
7250 default:
7251 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7252 (unsigned int)wire_open_mode ));
7253 return NT_STATUS_INVALID_PARAMETER;
7256 wire_open_mode &= ~SMB_ACCMODE;
7258 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7259 create_disp = FILE_CREATE;
7260 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7261 create_disp = FILE_OVERWRITE_IF;
7262 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7263 create_disp = FILE_OPEN_IF;
7264 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7265 create_disp = FILE_OPEN;
7266 } else {
7267 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7268 (unsigned int)wire_open_mode ));
7269 return NT_STATUS_INVALID_PARAMETER;
7272 raw_unixmode = IVAL(pdata,8);
7273 /* Next 4 bytes are not yet defined. */
7275 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7276 (VALID_STAT(smb_fname->st) ?
7277 PERM_EXISTING_FILE : PERM_NEW_FILE),
7278 &unixmode);
7280 if (!NT_STATUS_IS_OK(status)) {
7281 return status;
7284 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7286 if (wire_open_mode & SMB_O_SYNC) {
7287 create_options |= FILE_WRITE_THROUGH;
7289 if (wire_open_mode & SMB_O_APPEND) {
7290 access_mask |= FILE_APPEND_DATA;
7292 if (wire_open_mode & SMB_O_DIRECT) {
7293 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7296 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7297 smb_fname_str_dbg(smb_fname),
7298 (unsigned int)wire_open_mode,
7299 (unsigned int)unixmode ));
7301 status = SMB_VFS_CREATE_FILE(
7302 conn, /* conn */
7303 req, /* req */
7304 0, /* root_dir_fid */
7305 smb_fname, /* fname */
7306 access_mask, /* access_mask */
7307 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7308 FILE_SHARE_DELETE),
7309 create_disp, /* create_disposition*/
7310 FILE_NON_DIRECTORY_FILE, /* create_options */
7311 mod_unixmode, /* file_attributes */
7312 oplock_request, /* oplock_request */
7313 0, /* allocation_size */
7314 0, /* private_flags */
7315 NULL, /* sd */
7316 NULL, /* ea_list */
7317 &fsp, /* result */
7318 &info); /* pinfo */
7320 if (!NT_STATUS_IS_OK(status)) {
7321 return status;
7324 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7325 extended_oplock_granted = True;
7328 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7329 extended_oplock_granted = True;
7332 info_level_return = SVAL(pdata,16);
7334 /* Allocate the correct return size. */
7336 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7337 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7338 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7339 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7340 } else {
7341 *pdata_return_size = 12;
7344 /* Realloc the data size */
7345 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7346 if (*ppdata == NULL) {
7347 close_file(req, fsp, ERROR_CLOSE);
7348 *pdata_return_size = 0;
7349 return NT_STATUS_NO_MEMORY;
7351 pdata = *ppdata;
7353 if (extended_oplock_granted) {
7354 if (flags & REQUEST_BATCH_OPLOCK) {
7355 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7356 } else {
7357 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7359 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7360 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7361 } else {
7362 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7365 SSVAL(pdata,2,fsp->fnum);
7366 SIVAL(pdata,4,info); /* Was file created etc. */
7368 switch (info_level_return) {
7369 case SMB_QUERY_FILE_UNIX_BASIC:
7370 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7371 SSVAL(pdata,10,0); /* padding. */
7372 store_file_unix_basic(conn, pdata + 12, fsp,
7373 &smb_fname->st);
7374 break;
7375 case SMB_QUERY_FILE_UNIX_INFO2:
7376 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7377 SSVAL(pdata,10,0); /* padding. */
7378 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7379 &smb_fname->st);
7380 break;
7381 default:
7382 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7383 SSVAL(pdata,10,0); /* padding. */
7384 break;
7386 return NT_STATUS_OK;
7389 /****************************************************************************
7390 Delete a file with POSIX semantics.
7391 ****************************************************************************/
7393 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7394 struct smb_request *req,
7395 const char *pdata,
7396 int total_data,
7397 struct smb_filename *smb_fname)
7399 NTSTATUS status = NT_STATUS_OK;
7400 files_struct *fsp = NULL;
7401 uint16 flags = 0;
7402 char del = 1;
7403 int info = 0;
7404 int create_options = 0;
7405 int i;
7406 struct share_mode_lock *lck = NULL;
7408 if (total_data < 2) {
7409 return NT_STATUS_INVALID_PARAMETER;
7412 flags = SVAL(pdata,0);
7414 if (!VALID_STAT(smb_fname->st)) {
7415 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7418 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7419 !VALID_STAT_OF_DIR(smb_fname->st)) {
7420 return NT_STATUS_NOT_A_DIRECTORY;
7423 DEBUG(10,("smb_posix_unlink: %s %s\n",
7424 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7425 smb_fname_str_dbg(smb_fname)));
7427 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7428 create_options |= FILE_DIRECTORY_FILE;
7431 status = SMB_VFS_CREATE_FILE(
7432 conn, /* conn */
7433 req, /* req */
7434 0, /* root_dir_fid */
7435 smb_fname, /* fname */
7436 DELETE_ACCESS, /* access_mask */
7437 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7438 FILE_SHARE_DELETE),
7439 FILE_OPEN, /* create_disposition*/
7440 create_options, /* create_options */
7441 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7442 0, /* oplock_request */
7443 0, /* allocation_size */
7444 0, /* private_flags */
7445 NULL, /* sd */
7446 NULL, /* ea_list */
7447 &fsp, /* result */
7448 &info); /* pinfo */
7450 if (!NT_STATUS_IS_OK(status)) {
7451 return status;
7455 * Don't lie to client. If we can't really delete due to
7456 * non-POSIX opens return SHARING_VIOLATION.
7459 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7460 NULL);
7461 if (lck == NULL) {
7462 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7463 "lock for file %s\n", fsp_str_dbg(fsp)));
7464 close_file(req, fsp, NORMAL_CLOSE);
7465 return NT_STATUS_INVALID_PARAMETER;
7469 * See if others still have the file open. If this is the case, then
7470 * don't delete. If all opens are POSIX delete we can set the delete
7471 * on close disposition.
7473 for (i=0; i<lck->num_share_modes; i++) {
7474 struct share_mode_entry *e = &lck->share_modes[i];
7475 if (is_valid_share_mode_entry(e)) {
7476 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7477 continue;
7479 /* Fail with sharing violation. */
7480 close_file(req, fsp, NORMAL_CLOSE);
7481 TALLOC_FREE(lck);
7482 return NT_STATUS_SHARING_VIOLATION;
7487 * Set the delete on close.
7489 status = smb_set_file_disposition_info(conn,
7490 &del,
7492 fsp,
7493 smb_fname);
7495 if (!NT_STATUS_IS_OK(status)) {
7496 close_file(req, fsp, NORMAL_CLOSE);
7497 TALLOC_FREE(lck);
7498 return status;
7500 TALLOC_FREE(lck);
7501 return close_file(req, fsp, NORMAL_CLOSE);
7504 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7505 struct smb_request *req,
7506 TALLOC_CTX *mem_ctx,
7507 uint16_t info_level,
7508 files_struct *fsp,
7509 struct smb_filename *smb_fname,
7510 char **ppdata, int total_data,
7511 int *ret_data_size)
7513 char *pdata = *ppdata;
7514 NTSTATUS status = NT_STATUS_OK;
7515 int data_return_size = 0;
7517 *ret_data_size = 0;
7519 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7520 return NT_STATUS_INVALID_LEVEL;
7523 if (!CAN_WRITE(conn)) {
7524 /* Allow POSIX opens. The open path will deny
7525 * any non-readonly opens. */
7526 if (info_level != SMB_POSIX_PATH_OPEN) {
7527 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7531 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7532 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7533 fsp ? fsp->fnum : -1, info_level, total_data));
7535 switch (info_level) {
7537 case SMB_INFO_STANDARD:
7539 status = smb_set_info_standard(conn,
7540 pdata,
7541 total_data,
7542 fsp,
7543 smb_fname);
7544 break;
7547 case SMB_INFO_SET_EA:
7549 status = smb_info_set_ea(conn,
7550 pdata,
7551 total_data,
7552 fsp,
7553 smb_fname);
7554 break;
7557 case SMB_SET_FILE_BASIC_INFO:
7558 case SMB_FILE_BASIC_INFORMATION:
7560 status = smb_set_file_basic_info(conn,
7561 pdata,
7562 total_data,
7563 fsp,
7564 smb_fname);
7565 break;
7568 case SMB_FILE_ALLOCATION_INFORMATION:
7569 case SMB_SET_FILE_ALLOCATION_INFO:
7571 status = smb_set_file_allocation_info(conn, req,
7572 pdata,
7573 total_data,
7574 fsp,
7575 smb_fname);
7576 break;
7579 case SMB_FILE_END_OF_FILE_INFORMATION:
7580 case SMB_SET_FILE_END_OF_FILE_INFO:
7583 * XP/Win7 both fail after the createfile with
7584 * SMB_SET_FILE_END_OF_FILE_INFO but not
7585 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7586 * The level is known here, so pass it down
7587 * appropriately.
7589 bool should_fail =
7590 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7592 status = smb_set_file_end_of_file_info(conn, req,
7593 pdata,
7594 total_data,
7595 fsp,
7596 smb_fname,
7597 should_fail);
7598 break;
7601 case SMB_FILE_DISPOSITION_INFORMATION:
7602 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7604 #if 0
7605 /* JRA - We used to just ignore this on a path ?
7606 * Shouldn't this be invalid level on a pathname
7607 * based call ?
7609 if (tran_call != TRANSACT2_SETFILEINFO) {
7610 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7612 #endif
7613 status = smb_set_file_disposition_info(conn,
7614 pdata,
7615 total_data,
7616 fsp,
7617 smb_fname);
7618 break;
7621 case SMB_FILE_POSITION_INFORMATION:
7623 status = smb_file_position_information(conn,
7624 pdata,
7625 total_data,
7626 fsp);
7627 break;
7630 case SMB_FILE_FULL_EA_INFORMATION:
7632 status = smb_set_file_full_ea_info(conn,
7633 pdata,
7634 total_data,
7635 fsp);
7636 break;
7639 /* From tridge Samba4 :
7640 * MODE_INFORMATION in setfileinfo (I have no
7641 * idea what "mode information" on a file is - it takes a value of 0,
7642 * 2, 4 or 6. What could it be?).
7645 case SMB_FILE_MODE_INFORMATION:
7647 status = smb_file_mode_information(conn,
7648 pdata,
7649 total_data);
7650 break;
7654 * CIFS UNIX extensions.
7657 case SMB_SET_FILE_UNIX_BASIC:
7659 status = smb_set_file_unix_basic(conn, req,
7660 pdata,
7661 total_data,
7662 fsp,
7663 smb_fname);
7664 break;
7667 case SMB_SET_FILE_UNIX_INFO2:
7669 status = smb_set_file_unix_info2(conn, req,
7670 pdata,
7671 total_data,
7672 fsp,
7673 smb_fname);
7674 break;
7677 case SMB_SET_FILE_UNIX_LINK:
7679 if (fsp) {
7680 /* We must have a pathname for this. */
7681 return NT_STATUS_INVALID_LEVEL;
7683 status = smb_set_file_unix_link(conn, req, pdata,
7684 total_data, smb_fname);
7685 break;
7688 case SMB_SET_FILE_UNIX_HLINK:
7690 if (fsp) {
7691 /* We must have a pathname for this. */
7692 return NT_STATUS_INVALID_LEVEL;
7694 status = smb_set_file_unix_hlink(conn, req,
7695 pdata, total_data,
7696 smb_fname);
7697 break;
7700 case SMB_FILE_RENAME_INFORMATION:
7702 status = smb_file_rename_information(conn, req,
7703 pdata, total_data,
7704 fsp, smb_fname);
7705 break;
7708 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7710 /* SMB2 rename information. */
7711 status = smb2_file_rename_information(conn, req,
7712 pdata, total_data,
7713 fsp, smb_fname);
7714 break;
7717 case SMB_FILE_LINK_INFORMATION:
7719 status = smb_file_link_information(conn, req,
7720 pdata, total_data,
7721 fsp, smb_fname);
7722 break;
7725 #if defined(HAVE_POSIX_ACLS)
7726 case SMB_SET_POSIX_ACL:
7728 status = smb_set_posix_acl(conn,
7729 pdata,
7730 total_data,
7731 fsp,
7732 smb_fname);
7733 break;
7735 #endif
7737 case SMB_SET_POSIX_LOCK:
7739 if (!fsp) {
7740 return NT_STATUS_INVALID_LEVEL;
7742 status = smb_set_posix_lock(conn, req,
7743 pdata, total_data, fsp);
7744 break;
7747 case SMB_POSIX_PATH_OPEN:
7749 if (fsp) {
7750 /* We must have a pathname for this. */
7751 return NT_STATUS_INVALID_LEVEL;
7754 status = smb_posix_open(conn, req,
7755 ppdata,
7756 total_data,
7757 smb_fname,
7758 &data_return_size);
7759 break;
7762 case SMB_POSIX_PATH_UNLINK:
7764 if (fsp) {
7765 /* We must have a pathname for this. */
7766 return NT_STATUS_INVALID_LEVEL;
7769 status = smb_posix_unlink(conn, req,
7770 pdata,
7771 total_data,
7772 smb_fname);
7773 break;
7776 default:
7777 return NT_STATUS_INVALID_LEVEL;
7780 if (!NT_STATUS_IS_OK(status)) {
7781 return status;
7784 *ret_data_size = data_return_size;
7785 return NT_STATUS_OK;
7788 /****************************************************************************
7789 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7790 ****************************************************************************/
7792 static void call_trans2setfilepathinfo(connection_struct *conn,
7793 struct smb_request *req,
7794 unsigned int tran_call,
7795 char **pparams, int total_params,
7796 char **ppdata, int total_data,
7797 unsigned int max_data_bytes)
7799 char *params = *pparams;
7800 char *pdata = *ppdata;
7801 uint16 info_level;
7802 struct smb_filename *smb_fname = NULL;
7803 files_struct *fsp = NULL;
7804 NTSTATUS status = NT_STATUS_OK;
7805 int data_return_size = 0;
7807 if (!params) {
7808 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7809 return;
7812 if (tran_call == TRANSACT2_SETFILEINFO) {
7813 if (total_params < 4) {
7814 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7815 return;
7818 fsp = file_fsp(req, SVAL(params,0));
7819 /* Basic check for non-null fsp. */
7820 if (!check_fsp_open(conn, req, fsp)) {
7821 return;
7823 info_level = SVAL(params,2);
7825 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7826 &smb_fname);
7827 if (!NT_STATUS_IS_OK(status)) {
7828 reply_nterror(req, status);
7829 return;
7832 if(fsp->is_directory || fsp->fh->fd == -1) {
7834 * This is actually a SETFILEINFO on a directory
7835 * handle (returned from an NT SMB). NT5.0 seems
7836 * to do this call. JRA.
7838 if (INFO_LEVEL_IS_UNIX(info_level)) {
7839 /* Always do lstat for UNIX calls. */
7840 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7841 DEBUG(3,("call_trans2setfilepathinfo: "
7842 "SMB_VFS_LSTAT of %s failed "
7843 "(%s)\n",
7844 smb_fname_str_dbg(smb_fname),
7845 strerror(errno)));
7846 reply_nterror(req, map_nt_error_from_unix(errno));
7847 return;
7849 } else {
7850 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7851 DEBUG(3,("call_trans2setfilepathinfo: "
7852 "fileinfo of %s failed (%s)\n",
7853 smb_fname_str_dbg(smb_fname),
7854 strerror(errno)));
7855 reply_nterror(req, map_nt_error_from_unix(errno));
7856 return;
7859 } else if (fsp->print_file) {
7861 * Doing a DELETE_ON_CLOSE should cancel a print job.
7863 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7864 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7866 DEBUG(3,("call_trans2setfilepathinfo: "
7867 "Cancelling print job (%s)\n",
7868 fsp_str_dbg(fsp)));
7870 SSVAL(params,0,0);
7871 send_trans2_replies(conn, req, params, 2,
7872 *ppdata, 0,
7873 max_data_bytes);
7874 return;
7875 } else {
7876 reply_nterror(req,
7877 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7878 return;
7880 } else {
7882 * Original code - this is an open file.
7884 if (!check_fsp(conn, req, fsp)) {
7885 return;
7888 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7889 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7890 "of fnum %d failed (%s)\n", fsp->fnum,
7891 strerror(errno)));
7892 reply_nterror(req, map_nt_error_from_unix(errno));
7893 return;
7896 } else {
7897 char *fname = NULL;
7899 /* set path info */
7900 if (total_params < 7) {
7901 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7902 return;
7905 info_level = SVAL(params,0);
7906 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7907 total_params - 6, STR_TERMINATE,
7908 &status);
7909 if (!NT_STATUS_IS_OK(status)) {
7910 reply_nterror(req, status);
7911 return;
7914 status = filename_convert(req, conn,
7915 req->flags2 & FLAGS2_DFS_PATHNAMES,
7916 fname,
7918 NULL,
7919 &smb_fname);
7920 if (!NT_STATUS_IS_OK(status)) {
7921 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7922 reply_botherror(req,
7923 NT_STATUS_PATH_NOT_COVERED,
7924 ERRSRV, ERRbadpath);
7925 return;
7927 reply_nterror(req, status);
7928 return;
7931 if (INFO_LEVEL_IS_UNIX(info_level)) {
7933 * For CIFS UNIX extensions the target name may not exist.
7936 /* Always do lstat for UNIX calls. */
7937 SMB_VFS_LSTAT(conn, smb_fname);
7939 } else if (!VALID_STAT(smb_fname->st) &&
7940 SMB_VFS_STAT(conn, smb_fname)) {
7941 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7942 "%s failed (%s)\n",
7943 smb_fname_str_dbg(smb_fname),
7944 strerror(errno)));
7945 reply_nterror(req, map_nt_error_from_unix(errno));
7946 return;
7950 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7951 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7952 fsp ? fsp->fnum : -1, info_level,total_data));
7954 /* Realloc the parameter size */
7955 *pparams = (char *)SMB_REALLOC(*pparams,2);
7956 if (*pparams == NULL) {
7957 reply_nterror(req, NT_STATUS_NO_MEMORY);
7958 return;
7960 params = *pparams;
7962 SSVAL(params,0,0);
7964 status = smbd_do_setfilepathinfo(conn, req, req,
7965 info_level,
7966 fsp,
7967 smb_fname,
7968 ppdata, total_data,
7969 &data_return_size);
7970 if (!NT_STATUS_IS_OK(status)) {
7971 if (open_was_deferred(req->mid)) {
7972 /* We have re-scheduled this call. */
7973 return;
7975 if (blocking_lock_was_deferred_smb1(req->mid)) {
7976 /* We have re-scheduled this call. */
7977 return;
7979 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7980 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7981 ERRSRV, ERRbadpath);
7982 return;
7984 if (info_level == SMB_POSIX_PATH_OPEN) {
7985 reply_openerror(req, status);
7986 return;
7989 reply_nterror(req, status);
7990 return;
7993 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7994 max_data_bytes);
7996 return;
7999 /****************************************************************************
8000 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8001 ****************************************************************************/
8003 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8004 char **pparams, int total_params,
8005 char **ppdata, int total_data,
8006 unsigned int max_data_bytes)
8008 struct smb_filename *smb_dname = NULL;
8009 char *params = *pparams;
8010 char *pdata = *ppdata;
8011 char *directory = NULL;
8012 NTSTATUS status = NT_STATUS_OK;
8013 struct ea_list *ea_list = NULL;
8014 TALLOC_CTX *ctx = talloc_tos();
8016 if (!CAN_WRITE(conn)) {
8017 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8018 return;
8021 if (total_params < 5) {
8022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8023 return;
8026 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8027 total_params - 4, STR_TERMINATE,
8028 &status);
8029 if (!NT_STATUS_IS_OK(status)) {
8030 reply_nterror(req, status);
8031 return;
8034 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8036 status = filename_convert(ctx,
8037 conn,
8038 req->flags2 & FLAGS2_DFS_PATHNAMES,
8039 directory,
8041 NULL,
8042 &smb_dname);
8044 if (!NT_STATUS_IS_OK(status)) {
8045 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8046 reply_botherror(req,
8047 NT_STATUS_PATH_NOT_COVERED,
8048 ERRSRV, ERRbadpath);
8049 return;
8051 reply_nterror(req, status);
8052 return;
8056 * OS/2 workplace shell seems to send SET_EA requests of "null"
8057 * length (4 bytes containing IVAL 4).
8058 * They seem to have no effect. Bug #3212. JRA.
8061 if (total_data && (total_data != 4)) {
8062 /* Any data in this call is an EA list. */
8063 if (total_data < 10) {
8064 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8065 goto out;
8068 if (IVAL(pdata,0) > total_data) {
8069 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8070 IVAL(pdata,0), (unsigned int)total_data));
8071 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8072 goto out;
8075 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8076 total_data - 4);
8077 if (!ea_list) {
8078 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8079 goto out;
8082 if (!lp_ea_support(SNUM(conn))) {
8083 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8084 goto out;
8087 /* If total_data == 4 Windows doesn't care what values
8088 * are placed in that field, it just ignores them.
8089 * The System i QNTC IBM SMB client puts bad values here,
8090 * so ignore them. */
8092 status = create_directory(conn, req, smb_dname);
8094 if (!NT_STATUS_IS_OK(status)) {
8095 reply_nterror(req, status);
8096 goto out;
8099 /* Try and set any given EA. */
8100 if (ea_list) {
8101 status = set_ea(conn, NULL, smb_dname, ea_list);
8102 if (!NT_STATUS_IS_OK(status)) {
8103 reply_nterror(req, status);
8104 goto out;
8108 /* Realloc the parameter and data sizes */
8109 *pparams = (char *)SMB_REALLOC(*pparams,2);
8110 if(*pparams == NULL) {
8111 reply_nterror(req, NT_STATUS_NO_MEMORY);
8112 goto out;
8114 params = *pparams;
8116 SSVAL(params,0,0);
8118 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8120 out:
8121 TALLOC_FREE(smb_dname);
8122 return;
8125 /****************************************************************************
8126 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8127 We don't actually do this - we just send a null response.
8128 ****************************************************************************/
8130 static void call_trans2findnotifyfirst(connection_struct *conn,
8131 struct smb_request *req,
8132 char **pparams, int total_params,
8133 char **ppdata, int total_data,
8134 unsigned int max_data_bytes)
8136 char *params = *pparams;
8137 uint16 info_level;
8139 if (total_params < 6) {
8140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8141 return;
8144 info_level = SVAL(params,4);
8145 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8147 switch (info_level) {
8148 case 1:
8149 case 2:
8150 break;
8151 default:
8152 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8153 return;
8156 /* Realloc the parameter and data sizes */
8157 *pparams = (char *)SMB_REALLOC(*pparams,6);
8158 if (*pparams == NULL) {
8159 reply_nterror(req, NT_STATUS_NO_MEMORY);
8160 return;
8162 params = *pparams;
8164 SSVAL(params,0,fnf_handle);
8165 SSVAL(params,2,0); /* No changes */
8166 SSVAL(params,4,0); /* No EA errors */
8168 fnf_handle++;
8170 if(fnf_handle == 0)
8171 fnf_handle = 257;
8173 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8175 return;
8178 /****************************************************************************
8179 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8180 changes). Currently this does nothing.
8181 ****************************************************************************/
8183 static void call_trans2findnotifynext(connection_struct *conn,
8184 struct smb_request *req,
8185 char **pparams, int total_params,
8186 char **ppdata, int total_data,
8187 unsigned int max_data_bytes)
8189 char *params = *pparams;
8191 DEBUG(3,("call_trans2findnotifynext\n"));
8193 /* Realloc the parameter and data sizes */
8194 *pparams = (char *)SMB_REALLOC(*pparams,4);
8195 if (*pparams == NULL) {
8196 reply_nterror(req, NT_STATUS_NO_MEMORY);
8197 return;
8199 params = *pparams;
8201 SSVAL(params,0,0); /* No changes */
8202 SSVAL(params,2,0); /* No EA errors */
8204 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8206 return;
8209 /****************************************************************************
8210 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8211 ****************************************************************************/
8213 static void call_trans2getdfsreferral(connection_struct *conn,
8214 struct smb_request *req,
8215 char **pparams, int total_params,
8216 char **ppdata, int total_data,
8217 unsigned int max_data_bytes)
8219 char *params = *pparams;
8220 char *pathname = NULL;
8221 int reply_size = 0;
8222 int max_referral_level;
8223 NTSTATUS status = NT_STATUS_OK;
8224 TALLOC_CTX *ctx = talloc_tos();
8226 DEBUG(10,("call_trans2getdfsreferral\n"));
8228 if (total_params < 3) {
8229 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8230 return;
8233 max_referral_level = SVAL(params,0);
8235 if(!lp_host_msdfs()) {
8236 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8237 return;
8240 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8241 total_params - 2, STR_TERMINATE);
8242 if (!pathname) {
8243 reply_nterror(req, NT_STATUS_NOT_FOUND);
8244 return;
8246 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8247 ppdata,&status)) < 0) {
8248 reply_nterror(req, status);
8249 return;
8252 SSVAL(req->inbuf, smb_flg2,
8253 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8254 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8256 return;
8259 #define LMCAT_SPL 0x53
8260 #define LMFUNC_GETJOBID 0x60
8262 /****************************************************************************
8263 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8264 ****************************************************************************/
8266 static void call_trans2ioctl(connection_struct *conn,
8267 struct smb_request *req,
8268 char **pparams, int total_params,
8269 char **ppdata, int total_data,
8270 unsigned int max_data_bytes)
8272 char *pdata = *ppdata;
8273 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8275 /* check for an invalid fid before proceeding */
8277 if (!fsp) {
8278 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8279 return;
8282 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8283 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8284 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8285 if (*ppdata == NULL) {
8286 reply_nterror(req, NT_STATUS_NO_MEMORY);
8287 return;
8289 pdata = *ppdata;
8291 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8292 CAN ACCEPT THIS IN UNICODE. JRA. */
8294 /* Job number */
8295 if (fsp->print_file) {
8296 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8297 } else {
8298 SSVAL(pdata, 0, 0);
8300 srvstr_push(pdata, req->flags2, pdata + 2,
8301 global_myname(), 15,
8302 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8303 srvstr_push(pdata, req->flags2, pdata+18,
8304 lp_servicename(SNUM(conn)), 13,
8305 STR_ASCII|STR_TERMINATE); /* Service name */
8306 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8307 max_data_bytes);
8308 return;
8311 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8312 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8315 /****************************************************************************
8316 Reply to a SMBfindclose (stop trans2 directory search).
8317 ****************************************************************************/
8319 void reply_findclose(struct smb_request *req)
8321 int dptr_num;
8322 struct smbd_server_connection *sconn = smbd_server_conn;
8324 START_PROFILE(SMBfindclose);
8326 if (req->wct < 1) {
8327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8328 END_PROFILE(SMBfindclose);
8329 return;
8332 dptr_num = SVALS(req->vwv+0, 0);
8334 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8336 dptr_close(sconn, &dptr_num);
8338 reply_outbuf(req, 0, 0);
8340 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8342 END_PROFILE(SMBfindclose);
8343 return;
8346 /****************************************************************************
8347 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8348 ****************************************************************************/
8350 void reply_findnclose(struct smb_request *req)
8352 int dptr_num;
8354 START_PROFILE(SMBfindnclose);
8356 if (req->wct < 1) {
8357 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8358 END_PROFILE(SMBfindnclose);
8359 return;
8362 dptr_num = SVAL(req->vwv+0, 0);
8364 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8366 /* We never give out valid handles for a
8367 findnotifyfirst - so any dptr_num is ok here.
8368 Just ignore it. */
8370 reply_outbuf(req, 0, 0);
8372 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8374 END_PROFILE(SMBfindnclose);
8375 return;
8378 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8379 struct trans_state *state)
8381 if (get_Protocol() >= PROTOCOL_NT1) {
8382 req->flags2 |= 0x40; /* IS_LONG_NAME */
8383 SSVAL(req->inbuf,smb_flg2,req->flags2);
8386 if (conn->encrypt_level == Required && !req->encrypted) {
8387 if (state->call != TRANSACT2_QFSINFO &&
8388 state->call != TRANSACT2_SETFSINFO) {
8389 DEBUG(0,("handle_trans2: encryption required "
8390 "with call 0x%x\n",
8391 (unsigned int)state->call));
8392 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8393 return;
8397 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8399 /* Now we must call the relevant TRANS2 function */
8400 switch(state->call) {
8401 case TRANSACT2_OPEN:
8403 START_PROFILE(Trans2_open);
8404 call_trans2open(conn, req,
8405 &state->param, state->total_param,
8406 &state->data, state->total_data,
8407 state->max_data_return);
8408 END_PROFILE(Trans2_open);
8409 break;
8412 case TRANSACT2_FINDFIRST:
8414 START_PROFILE(Trans2_findfirst);
8415 call_trans2findfirst(conn, req,
8416 &state->param, state->total_param,
8417 &state->data, state->total_data,
8418 state->max_data_return);
8419 END_PROFILE(Trans2_findfirst);
8420 break;
8423 case TRANSACT2_FINDNEXT:
8425 START_PROFILE(Trans2_findnext);
8426 call_trans2findnext(conn, req,
8427 &state->param, state->total_param,
8428 &state->data, state->total_data,
8429 state->max_data_return);
8430 END_PROFILE(Trans2_findnext);
8431 break;
8434 case TRANSACT2_QFSINFO:
8436 START_PROFILE(Trans2_qfsinfo);
8437 call_trans2qfsinfo(conn, req,
8438 &state->param, state->total_param,
8439 &state->data, state->total_data,
8440 state->max_data_return);
8441 END_PROFILE(Trans2_qfsinfo);
8442 break;
8445 case TRANSACT2_SETFSINFO:
8447 START_PROFILE(Trans2_setfsinfo);
8448 call_trans2setfsinfo(conn, req,
8449 &state->param, state->total_param,
8450 &state->data, state->total_data,
8451 state->max_data_return);
8452 END_PROFILE(Trans2_setfsinfo);
8453 break;
8456 case TRANSACT2_QPATHINFO:
8457 case TRANSACT2_QFILEINFO:
8459 START_PROFILE(Trans2_qpathinfo);
8460 call_trans2qfilepathinfo(conn, req, state->call,
8461 &state->param, state->total_param,
8462 &state->data, state->total_data,
8463 state->max_data_return);
8464 END_PROFILE(Trans2_qpathinfo);
8465 break;
8468 case TRANSACT2_SETPATHINFO:
8469 case TRANSACT2_SETFILEINFO:
8471 START_PROFILE(Trans2_setpathinfo);
8472 call_trans2setfilepathinfo(conn, req, state->call,
8473 &state->param, state->total_param,
8474 &state->data, state->total_data,
8475 state->max_data_return);
8476 END_PROFILE(Trans2_setpathinfo);
8477 break;
8480 case TRANSACT2_FINDNOTIFYFIRST:
8482 START_PROFILE(Trans2_findnotifyfirst);
8483 call_trans2findnotifyfirst(conn, req,
8484 &state->param, state->total_param,
8485 &state->data, state->total_data,
8486 state->max_data_return);
8487 END_PROFILE(Trans2_findnotifyfirst);
8488 break;
8491 case TRANSACT2_FINDNOTIFYNEXT:
8493 START_PROFILE(Trans2_findnotifynext);
8494 call_trans2findnotifynext(conn, req,
8495 &state->param, state->total_param,
8496 &state->data, state->total_data,
8497 state->max_data_return);
8498 END_PROFILE(Trans2_findnotifynext);
8499 break;
8502 case TRANSACT2_MKDIR:
8504 START_PROFILE(Trans2_mkdir);
8505 call_trans2mkdir(conn, req,
8506 &state->param, state->total_param,
8507 &state->data, state->total_data,
8508 state->max_data_return);
8509 END_PROFILE(Trans2_mkdir);
8510 break;
8513 case TRANSACT2_GET_DFS_REFERRAL:
8515 START_PROFILE(Trans2_get_dfs_referral);
8516 call_trans2getdfsreferral(conn, req,
8517 &state->param, state->total_param,
8518 &state->data, state->total_data,
8519 state->max_data_return);
8520 END_PROFILE(Trans2_get_dfs_referral);
8521 break;
8524 case TRANSACT2_IOCTL:
8526 START_PROFILE(Trans2_ioctl);
8527 call_trans2ioctl(conn, req,
8528 &state->param, state->total_param,
8529 &state->data, state->total_data,
8530 state->max_data_return);
8531 END_PROFILE(Trans2_ioctl);
8532 break;
8535 default:
8536 /* Error in request */
8537 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8538 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8542 /****************************************************************************
8543 Reply to a SMBtrans2.
8544 ****************************************************************************/
8546 void reply_trans2(struct smb_request *req)
8548 connection_struct *conn = req->conn;
8549 unsigned int dsoff;
8550 unsigned int dscnt;
8551 unsigned int psoff;
8552 unsigned int pscnt;
8553 unsigned int tran_call;
8554 struct trans_state *state;
8555 NTSTATUS result;
8557 START_PROFILE(SMBtrans2);
8559 if (req->wct < 14) {
8560 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8561 END_PROFILE(SMBtrans2);
8562 return;
8565 dsoff = SVAL(req->vwv+12, 0);
8566 dscnt = SVAL(req->vwv+11, 0);
8567 psoff = SVAL(req->vwv+10, 0);
8568 pscnt = SVAL(req->vwv+9, 0);
8569 tran_call = SVAL(req->vwv+14, 0);
8571 result = allow_new_trans(conn->pending_trans, req->mid);
8572 if (!NT_STATUS_IS_OK(result)) {
8573 DEBUG(2, ("Got invalid trans2 request: %s\n",
8574 nt_errstr(result)));
8575 reply_nterror(req, result);
8576 END_PROFILE(SMBtrans2);
8577 return;
8580 if (IS_IPC(conn)) {
8581 switch (tran_call) {
8582 /* List the allowed trans2 calls on IPC$ */
8583 case TRANSACT2_OPEN:
8584 case TRANSACT2_GET_DFS_REFERRAL:
8585 case TRANSACT2_QFILEINFO:
8586 case TRANSACT2_QFSINFO:
8587 case TRANSACT2_SETFSINFO:
8588 break;
8589 default:
8590 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8591 END_PROFILE(SMBtrans2);
8592 return;
8596 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8597 DEBUG(0, ("talloc failed\n"));
8598 reply_nterror(req, NT_STATUS_NO_MEMORY);
8599 END_PROFILE(SMBtrans2);
8600 return;
8603 state->cmd = SMBtrans2;
8605 state->mid = req->mid;
8606 state->vuid = req->vuid;
8607 state->setup_count = SVAL(req->vwv+13, 0);
8608 state->setup = NULL;
8609 state->total_param = SVAL(req->vwv+0, 0);
8610 state->param = NULL;
8611 state->total_data = SVAL(req->vwv+1, 0);
8612 state->data = NULL;
8613 state->max_param_return = SVAL(req->vwv+2, 0);
8614 state->max_data_return = SVAL(req->vwv+3, 0);
8615 state->max_setup_return = SVAL(req->vwv+4, 0);
8616 state->close_on_completion = BITSETW(req->vwv+5, 0);
8617 state->one_way = BITSETW(req->vwv+5, 1);
8619 state->call = tran_call;
8621 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8622 is so as a sanity check */
8623 if (state->setup_count != 1) {
8625 * Need to have rc=0 for ioctl to get job id for OS/2.
8626 * Network printing will fail if function is not successful.
8627 * Similar function in reply.c will be used if protocol
8628 * is LANMAN1.0 instead of LM1.2X002.
8629 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8630 * outbuf doesn't have to be set(only job id is used).
8632 if ( (state->setup_count == 4)
8633 && (tran_call == TRANSACT2_IOCTL)
8634 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8635 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8636 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8637 } else {
8638 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8639 DEBUG(2,("Transaction is %d\n",tran_call));
8640 TALLOC_FREE(state);
8641 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8642 END_PROFILE(SMBtrans2);
8643 return;
8647 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8648 goto bad_param;
8650 if (state->total_data) {
8652 if (trans_oob(state->total_data, 0, dscnt)
8653 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8654 goto bad_param;
8657 /* Can't use talloc here, the core routines do realloc on the
8658 * params and data. */
8659 state->data = (char *)SMB_MALLOC(state->total_data);
8660 if (state->data == NULL) {
8661 DEBUG(0,("reply_trans2: data malloc fail for %u "
8662 "bytes !\n", (unsigned int)state->total_data));
8663 TALLOC_FREE(state);
8664 reply_nterror(req, NT_STATUS_NO_MEMORY);
8665 END_PROFILE(SMBtrans2);
8666 return;
8669 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8672 if (state->total_param) {
8674 if (trans_oob(state->total_param, 0, pscnt)
8675 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8676 goto bad_param;
8679 /* Can't use talloc here, the core routines do realloc on the
8680 * params and data. */
8681 state->param = (char *)SMB_MALLOC(state->total_param);
8682 if (state->param == NULL) {
8683 DEBUG(0,("reply_trans: param malloc fail for %u "
8684 "bytes !\n", (unsigned int)state->total_param));
8685 SAFE_FREE(state->data);
8686 TALLOC_FREE(state);
8687 reply_nterror(req, NT_STATUS_NO_MEMORY);
8688 END_PROFILE(SMBtrans2);
8689 return;
8692 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8695 state->received_data = dscnt;
8696 state->received_param = pscnt;
8698 if ((state->received_param == state->total_param) &&
8699 (state->received_data == state->total_data)) {
8701 handle_trans2(conn, req, state);
8703 SAFE_FREE(state->data);
8704 SAFE_FREE(state->param);
8705 TALLOC_FREE(state);
8706 END_PROFILE(SMBtrans2);
8707 return;
8710 DLIST_ADD(conn->pending_trans, state);
8712 /* We need to send an interim response then receive the rest
8713 of the parameter/data bytes */
8714 reply_outbuf(req, 0, 0);
8715 show_msg((char *)req->outbuf);
8716 END_PROFILE(SMBtrans2);
8717 return;
8719 bad_param:
8721 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8722 SAFE_FREE(state->data);
8723 SAFE_FREE(state->param);
8724 TALLOC_FREE(state);
8725 END_PROFILE(SMBtrans2);
8726 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8730 /****************************************************************************
8731 Reply to a SMBtranss2
8732 ****************************************************************************/
8734 void reply_transs2(struct smb_request *req)
8736 connection_struct *conn = req->conn;
8737 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8738 struct trans_state *state;
8740 START_PROFILE(SMBtranss2);
8742 show_msg((char *)req->inbuf);
8744 if (req->wct < 8) {
8745 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8746 END_PROFILE(SMBtranss2);
8747 return;
8750 for (state = conn->pending_trans; state != NULL;
8751 state = state->next) {
8752 if (state->mid == req->mid) {
8753 break;
8757 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8758 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8759 END_PROFILE(SMBtranss2);
8760 return;
8763 /* Revise state->total_param and state->total_data in case they have
8764 changed downwards */
8766 if (SVAL(req->vwv+0, 0) < state->total_param)
8767 state->total_param = SVAL(req->vwv+0, 0);
8768 if (SVAL(req->vwv+1, 0) < state->total_data)
8769 state->total_data = SVAL(req->vwv+1, 0);
8771 pcnt = SVAL(req->vwv+2, 0);
8772 poff = SVAL(req->vwv+3, 0);
8773 pdisp = SVAL(req->vwv+4, 0);
8775 dcnt = SVAL(req->vwv+5, 0);
8776 doff = SVAL(req->vwv+6, 0);
8777 ddisp = SVAL(req->vwv+7, 0);
8779 state->received_param += pcnt;
8780 state->received_data += dcnt;
8782 if ((state->received_data > state->total_data) ||
8783 (state->received_param > state->total_param))
8784 goto bad_param;
8786 if (pcnt) {
8787 if (trans_oob(state->total_param, pdisp, pcnt)
8788 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8789 goto bad_param;
8791 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8794 if (dcnt) {
8795 if (trans_oob(state->total_data, ddisp, dcnt)
8796 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8797 goto bad_param;
8799 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8802 if ((state->received_param < state->total_param) ||
8803 (state->received_data < state->total_data)) {
8804 END_PROFILE(SMBtranss2);
8805 return;
8808 handle_trans2(conn, req, state);
8810 DLIST_REMOVE(conn->pending_trans, state);
8811 SAFE_FREE(state->data);
8812 SAFE_FREE(state->param);
8813 TALLOC_FREE(state);
8815 END_PROFILE(SMBtranss2);
8816 return;
8818 bad_param:
8820 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8821 DLIST_REMOVE(conn->pending_trans, state);
8822 SAFE_FREE(state->data);
8823 SAFE_FREE(state->param);
8824 TALLOC_FREE(state);
8825 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8826 END_PROFILE(SMBtranss2);
8827 return;