Fix bug #8144 - touch /mnt/newfile fails to set timestamp with CIFS client.
[Samba.git] / source3 / smbd / trans2.c
blob42b915bea8da9acc87ead0d6ce878c3de113ec26
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "system/filesys.h"
28 #include "version.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "libcli/security/security.h"
35 #include "trans2.h"
36 #include "auth.h"
37 #include "smbprofile.h"
38 #include "rpc_server/srv_pipe_hnd.h"
39 #include "libsmb/libsmb.h"
41 #define DIR_ENTRY_SAFETY_MARGIN 4096
43 static char *store_file_unix_basic(connection_struct *conn,
44 char *pdata,
45 files_struct *fsp,
46 const SMB_STRUCT_STAT *psbuf);
48 static char *store_file_unix_basic_info2(connection_struct *conn,
49 char *pdata,
50 files_struct *fsp,
51 const SMB_STRUCT_STAT *psbuf);
53 /********************************************************************
54 Roundup a value to the nearest allocation roundup size boundary.
55 Only do this for Windows clients.
56 ********************************************************************/
58 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
60 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
62 /* Only roundup for Windows clients. */
63 enum remote_arch_types ra_type = get_remote_arch();
64 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
65 val = SMB_ROUNDUP(val,rval);
67 return val;
70 /********************************************************************
71 Create a 64 bit FileIndex. If the file is on the same device as
72 the root of the share, just return the 64-bit inode. If it isn't,
73 mangle as we used to do.
74 ********************************************************************/
76 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
78 uint64_t file_index;
79 if (conn->base_share_dev == psbuf->st_ex_dev) {
80 return (uint64_t)psbuf->st_ex_ino;
82 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
83 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
84 return file_index;
87 /****************************************************************************
88 Utility functions for dealing with extended attributes.
89 ****************************************************************************/
91 /****************************************************************************
92 Refuse to allow clients to overwrite our private xattrs.
93 ****************************************************************************/
95 static bool samba_private_attr_name(const char *unix_ea_name)
97 static const char * const prohibited_ea_names[] = {
98 SAMBA_POSIX_INHERITANCE_EA_NAME,
99 SAMBA_XATTR_DOS_ATTRIB,
100 SAMBA_XATTR_MARKER,
101 XATTR_NTACL_NAME,
102 NULL
105 int i;
107 for (i = 0; prohibited_ea_names[i]; i++) {
108 if (strequal( prohibited_ea_names[i], unix_ea_name))
109 return true;
111 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
112 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
113 return true;
115 return false;
118 /****************************************************************************
119 Get one EA value. Fill in a struct ea_struct.
120 ****************************************************************************/
122 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
123 files_struct *fsp, const char *fname,
124 const char *ea_name, struct ea_struct *pea)
126 /* Get the value of this xattr. Max size is 64k. */
127 size_t attr_size = 256;
128 char *val = NULL;
129 ssize_t sizeret;
131 again:
133 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
134 if (!val) {
135 return NT_STATUS_NO_MEMORY;
138 if (fsp && fsp->fh->fd != -1) {
139 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
140 } else {
141 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
144 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
145 attr_size = 65536;
146 goto again;
149 if (sizeret == -1) {
150 return map_nt_error_from_unix(errno);
153 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
154 dump_data(10, (uint8 *)val, sizeret);
156 pea->flags = 0;
157 if (strnequal(ea_name, "user.", 5)) {
158 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
159 } else {
160 pea->name = talloc_strdup(mem_ctx, ea_name);
162 if (pea->name == NULL) {
163 TALLOC_FREE(val);
164 return NT_STATUS_NO_MEMORY;
166 pea->value.data = (unsigned char *)val;
167 pea->value.length = (size_t)sizeret;
168 return NT_STATUS_OK;
171 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
172 files_struct *fsp, const char *fname,
173 char ***pnames, size_t *pnum_names)
175 /* Get a list of all xattrs. Max namesize is 64k. */
176 size_t ea_namelist_size = 1024;
177 char *ea_namelist = NULL;
179 char *p;
180 char **names, **tmp;
181 size_t num_names;
182 ssize_t sizeret = -1;
184 if (!lp_ea_support(SNUM(conn))) {
185 if (pnames) {
186 *pnames = NULL;
188 *pnum_names = 0;
189 return NT_STATUS_OK;
193 * TALLOC the result early to get the talloc hierarchy right.
196 names = TALLOC_ARRAY(mem_ctx, char *, 1);
197 if (names == NULL) {
198 DEBUG(0, ("talloc failed\n"));
199 return NT_STATUS_NO_MEMORY;
202 while (ea_namelist_size <= 65536) {
204 ea_namelist = TALLOC_REALLOC_ARRAY(
205 names, ea_namelist, char, ea_namelist_size);
206 if (ea_namelist == NULL) {
207 DEBUG(0, ("talloc failed\n"));
208 TALLOC_FREE(names);
209 return NT_STATUS_NO_MEMORY;
212 if (fsp && fsp->fh->fd != -1) {
213 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
214 ea_namelist_size);
215 } else {
216 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
217 ea_namelist_size);
220 if ((sizeret == -1) && (errno == ERANGE)) {
221 ea_namelist_size *= 2;
223 else {
224 break;
228 if (sizeret == -1) {
229 TALLOC_FREE(names);
230 return map_nt_error_from_unix(errno);
233 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
234 (unsigned int)sizeret));
236 if (sizeret == 0) {
237 TALLOC_FREE(names);
238 if (pnames) {
239 *pnames = NULL;
241 *pnum_names = 0;
242 return NT_STATUS_OK;
246 * Ensure the result is 0-terminated
249 if (ea_namelist[sizeret-1] != '\0') {
250 TALLOC_FREE(names);
251 return NT_STATUS_INTERNAL_ERROR;
255 * count the names
257 num_names = 0;
259 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
260 num_names += 1;
263 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
264 if (tmp == NULL) {
265 DEBUG(0, ("talloc failed\n"));
266 TALLOC_FREE(names);
267 return NT_STATUS_NO_MEMORY;
270 names = tmp;
271 num_names = 0;
273 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
274 names[num_names++] = p;
277 if (pnames) {
278 *pnames = names;
279 } else {
280 TALLOC_FREE(names);
282 *pnum_names = num_names;
283 return NT_STATUS_OK;
286 /****************************************************************************
287 Return a linked list of the total EA's. Plus the total size
288 ****************************************************************************/
290 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
291 const char *fname, size_t *pea_total_len)
293 /* Get a list of all xattrs. Max namesize is 64k. */
294 size_t i, num_names;
295 char **names;
296 struct ea_list *ea_list_head = NULL;
297 NTSTATUS status;
299 *pea_total_len = 0;
301 if (!lp_ea_support(SNUM(conn))) {
302 return NULL;
305 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
306 &names, &num_names);
308 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
309 return NULL;
312 for (i=0; i<num_names; i++) {
313 struct ea_list *listp;
314 fstring dos_ea_name;
316 if (strnequal(names[i], "system.", 7)
317 || samba_private_attr_name(names[i]))
318 continue;
320 listp = TALLOC_P(mem_ctx, struct ea_list);
321 if (listp == NULL) {
322 return NULL;
325 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
326 fname, names[i],
327 &listp->ea))) {
328 return NULL;
331 push_ascii_fstring(dos_ea_name, listp->ea.name);
333 *pea_total_len +=
334 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
336 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
337 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
338 (unsigned int)listp->ea.value.length));
340 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
344 /* Add on 4 for total length. */
345 if (*pea_total_len) {
346 *pea_total_len += 4;
349 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
350 (unsigned int)*pea_total_len));
352 return ea_list_head;
355 /****************************************************************************
356 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
357 that was filled.
358 ****************************************************************************/
360 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
361 connection_struct *conn, struct ea_list *ea_list)
363 unsigned int ret_data_size = 4;
364 char *p = pdata;
366 SMB_ASSERT(total_data_size >= 4);
368 if (!lp_ea_support(SNUM(conn))) {
369 SIVAL(pdata,4,0);
370 return 4;
373 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
374 size_t dos_namelen;
375 fstring dos_ea_name;
376 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
377 dos_namelen = strlen(dos_ea_name);
378 if (dos_namelen > 255 || dos_namelen == 0) {
379 break;
381 if (ea_list->ea.value.length > 65535) {
382 break;
384 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
385 break;
388 /* We know we have room. */
389 SCVAL(p,0,ea_list->ea.flags);
390 SCVAL(p,1,dos_namelen);
391 SSVAL(p,2,ea_list->ea.value.length);
392 fstrcpy(p+4, dos_ea_name);
393 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
395 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
396 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
399 ret_data_size = PTR_DIFF(p, pdata);
400 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
401 SIVAL(pdata,0,ret_data_size);
402 return ret_data_size;
405 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
406 char *pdata,
407 unsigned int total_data_size,
408 unsigned int *ret_data_size,
409 connection_struct *conn,
410 struct ea_list *ea_list)
412 uint8_t *p = (uint8_t *)pdata;
413 uint8_t *last_start = NULL;
415 *ret_data_size = 0;
417 if (!lp_ea_support(SNUM(conn))) {
418 return NT_STATUS_NO_EAS_ON_FILE;
421 for (; ea_list; ea_list = ea_list->next) {
422 size_t dos_namelen;
423 fstring dos_ea_name;
424 size_t this_size;
426 if (last_start) {
427 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
429 last_start = p;
431 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
432 dos_namelen = strlen(dos_ea_name);
433 if (dos_namelen > 255 || dos_namelen == 0) {
434 return NT_STATUS_INTERNAL_ERROR;
436 if (ea_list->ea.value.length > 65535) {
437 return NT_STATUS_INTERNAL_ERROR;
440 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
442 if (ea_list->next) {
443 size_t pad = 4 - (this_size % 4);
444 this_size += pad;
447 if (this_size > total_data_size) {
448 return NT_STATUS_INFO_LENGTH_MISMATCH;
451 /* We know we have room. */
452 SIVAL(p, 0x00, 0); /* next offset */
453 SCVAL(p, 0x04, ea_list->ea.flags);
454 SCVAL(p, 0x05, dos_namelen);
455 SSVAL(p, 0x06, ea_list->ea.value.length);
456 fstrcpy((char *)(p+0x08), dos_ea_name);
457 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
459 total_data_size -= this_size;
460 p += this_size;
463 *ret_data_size = PTR_DIFF(p, pdata);
464 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
465 return NT_STATUS_OK;
468 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
470 size_t total_ea_len = 0;
471 TALLOC_CTX *mem_ctx = NULL;
473 if (!lp_ea_support(SNUM(conn))) {
474 return 0;
476 mem_ctx = talloc_tos();
477 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
478 return total_ea_len;
481 /****************************************************************************
482 Ensure the EA name is case insensitive by matching any existing EA name.
483 ****************************************************************************/
485 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
487 size_t total_ea_len;
488 TALLOC_CTX *mem_ctx = talloc_tos();
489 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
491 for (; ea_list; ea_list = ea_list->next) {
492 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
493 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
494 &unix_ea_name[5], ea_list->ea.name));
495 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
496 break;
501 /****************************************************************************
502 Set or delete an extended attribute.
503 ****************************************************************************/
505 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
506 const struct smb_filename *smb_fname, struct ea_list *ea_list)
508 char *fname = NULL;
510 if (!lp_ea_support(SNUM(conn))) {
511 return NT_STATUS_EAS_NOT_SUPPORTED;
514 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
515 return NT_STATUS_ACCESS_DENIED;
518 /* For now setting EAs on streams isn't supported. */
519 fname = smb_fname->base_name;
521 for (;ea_list; ea_list = ea_list->next) {
522 int ret;
523 fstring unix_ea_name;
525 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
526 fstrcat(unix_ea_name, ea_list->ea.name);
528 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
530 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
532 if (samba_private_attr_name(unix_ea_name)) {
533 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
534 return NT_STATUS_ACCESS_DENIED;
537 if (ea_list->ea.value.length == 0) {
538 /* Remove the attribute. */
539 if (fsp && (fsp->fh->fd != -1)) {
540 DEBUG(10,("set_ea: deleting ea name %s on "
541 "file %s by file descriptor.\n",
542 unix_ea_name, fsp_str_dbg(fsp)));
543 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
544 } else {
545 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
546 unix_ea_name, fname));
547 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
549 #ifdef ENOATTR
550 /* Removing a non existent attribute always succeeds. */
551 if (ret == -1 && errno == ENOATTR) {
552 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
553 unix_ea_name));
554 ret = 0;
556 #endif
557 } else {
558 if (fsp && (fsp->fh->fd != -1)) {
559 DEBUG(10,("set_ea: setting ea name %s on file "
560 "%s by file descriptor.\n",
561 unix_ea_name, fsp_str_dbg(fsp)));
562 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
563 ea_list->ea.value.data, ea_list->ea.value.length, 0);
564 } else {
565 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
566 unix_ea_name, fname));
567 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
568 ea_list->ea.value.data, ea_list->ea.value.length, 0);
572 if (ret == -1) {
573 #ifdef ENOTSUP
574 if (errno == ENOTSUP) {
575 return NT_STATUS_EAS_NOT_SUPPORTED;
577 #endif
578 return map_nt_error_from_unix(errno);
582 return NT_STATUS_OK;
584 /****************************************************************************
585 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
586 ****************************************************************************/
588 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
590 struct ea_list *ea_list_head = NULL;
591 size_t converted_size, offset = 0;
593 while (offset + 2 < data_size) {
594 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
595 unsigned int namelen = CVAL(pdata,offset);
597 offset++; /* Go past the namelen byte. */
599 /* integer wrap paranioa. */
600 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
601 (offset > data_size) || (namelen > data_size) ||
602 (offset + namelen >= data_size)) {
603 break;
605 /* Ensure the name is null terminated. */
606 if (pdata[offset + namelen] != '\0') {
607 return NULL;
609 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
610 &converted_size)) {
611 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
612 "failed: %s", strerror(errno)));
614 if (!eal->ea.name) {
615 return NULL;
618 offset += (namelen + 1); /* Go past the name + terminating zero. */
619 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
620 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
623 return ea_list_head;
626 /****************************************************************************
627 Read one EA list entry from the buffer.
628 ****************************************************************************/
630 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
632 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
633 uint16 val_len;
634 unsigned int namelen;
635 size_t converted_size;
637 if (!eal) {
638 return NULL;
641 if (data_size < 6) {
642 return NULL;
645 eal->ea.flags = CVAL(pdata,0);
646 namelen = CVAL(pdata,1);
647 val_len = SVAL(pdata,2);
649 if (4 + namelen + 1 + val_len > data_size) {
650 return NULL;
653 /* Ensure the name is null terminated. */
654 if (pdata[namelen + 4] != '\0') {
655 return NULL;
657 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
658 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
659 strerror(errno)));
661 if (!eal->ea.name) {
662 return NULL;
665 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
666 if (!eal->ea.value.data) {
667 return NULL;
670 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
672 /* Ensure we're null terminated just in case we print the value. */
673 eal->ea.value.data[val_len] = '\0';
674 /* But don't count the null. */
675 eal->ea.value.length--;
677 if (pbytes_used) {
678 *pbytes_used = 4 + namelen + 1 + val_len;
681 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
682 dump_data(10, eal->ea.value.data, eal->ea.value.length);
684 return eal;
687 /****************************************************************************
688 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
689 ****************************************************************************/
691 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
693 struct ea_list *ea_list_head = NULL;
694 size_t offset = 0;
695 size_t bytes_used = 0;
697 while (offset < data_size) {
698 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
700 if (!eal) {
701 return NULL;
704 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
705 offset += bytes_used;
708 return ea_list_head;
711 /****************************************************************************
712 Count the total EA size needed.
713 ****************************************************************************/
715 static size_t ea_list_size(struct ea_list *ealist)
717 fstring dos_ea_name;
718 struct ea_list *listp;
719 size_t ret = 0;
721 for (listp = ealist; listp; listp = listp->next) {
722 push_ascii_fstring(dos_ea_name, listp->ea.name);
723 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
725 /* Add on 4 for total length. */
726 if (ret) {
727 ret += 4;
730 return ret;
733 /****************************************************************************
734 Return a union of EA's from a file list and a list of names.
735 The TALLOC context for the two lists *MUST* be identical as we steal
736 memory from one list to add to another. JRA.
737 ****************************************************************************/
739 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
741 struct ea_list *nlistp, *flistp;
743 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
744 for (flistp = file_list; flistp; flistp = flistp->next) {
745 if (strequal(nlistp->ea.name, flistp->ea.name)) {
746 break;
750 if (flistp) {
751 /* Copy the data from this entry. */
752 nlistp->ea.flags = flistp->ea.flags;
753 nlistp->ea.value = flistp->ea.value;
754 } else {
755 /* Null entry. */
756 nlistp->ea.flags = 0;
757 ZERO_STRUCT(nlistp->ea.value);
761 *total_ea_len = ea_list_size(name_list);
762 return name_list;
765 /****************************************************************************
766 Send the required number of replies back.
767 We assume all fields other than the data fields are
768 set correctly for the type of call.
769 HACK ! Always assumes smb_setup field is zero.
770 ****************************************************************************/
772 void send_trans2_replies(connection_struct *conn,
773 struct smb_request *req,
774 const char *params,
775 int paramsize,
776 const char *pdata,
777 int datasize,
778 int max_data_bytes)
780 /* As we are using a protocol > LANMAN1 then the max_send
781 variable must have been set in the sessetupX call.
782 This takes precedence over the max_xmit field in the
783 global struct. These different max_xmit variables should
784 be merged as this is now too confusing */
786 int data_to_send = datasize;
787 int params_to_send = paramsize;
788 int useable_space;
789 const char *pp = params;
790 const char *pd = pdata;
791 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
792 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
793 int data_alignment_offset = 0;
794 bool overflow = False;
795 struct smbd_server_connection *sconn = req->sconn;
796 int max_send = sconn->smb1.sessions.max_send;
798 /* Modify the data_to_send and datasize and set the error if
799 we're trying to send more than max_data_bytes. We still send
800 the part of the packet(s) that fit. Strange, but needed
801 for OS/2. */
803 if (max_data_bytes > 0 && datasize > max_data_bytes) {
804 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
805 max_data_bytes, datasize ));
806 datasize = data_to_send = max_data_bytes;
807 overflow = True;
810 /* If there genuinely are no parameters or data to send just send the empty packet */
812 if(params_to_send == 0 && data_to_send == 0) {
813 reply_outbuf(req, 10, 0);
814 show_msg((char *)req->outbuf);
815 if (!srv_send_smb(sconn,
816 (char *)req->outbuf,
817 true, req->seqnum+1,
818 IS_CONN_ENCRYPTED(conn),
819 &req->pcd)) {
820 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
822 TALLOC_FREE(req->outbuf);
823 return;
826 /* When sending params and data ensure that both are nicely aligned */
827 /* Only do this alignment when there is also data to send - else
828 can cause NT redirector problems. */
830 if (((params_to_send % 4) != 0) && (data_to_send != 0))
831 data_alignment_offset = 4 - (params_to_send % 4);
833 /* Space is bufsize minus Netbios over TCP header minus SMB header */
834 /* The alignment_offset is to align the param bytes on an even byte
835 boundary. NT 4.0 Beta needs this to work correctly. */
837 useable_space = max_send - (smb_size
838 + 2 * 10 /* wct */
839 + alignment_offset
840 + data_alignment_offset);
842 if (useable_space < 0) {
843 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
844 "= %d!!!", useable_space));
845 exit_server_cleanly("send_trans2_replies: Not enough space");
848 while (params_to_send || data_to_send) {
849 /* Calculate whether we will totally or partially fill this packet */
851 total_sent_thistime = params_to_send + data_to_send;
853 /* We can never send more than useable_space */
855 * Note that 'useable_space' does not include the alignment offsets,
856 * but we must include the alignment offsets in the calculation of
857 * the length of the data we send over the wire, as the alignment offsets
858 * are sent here. Fix from Marc_Jacobsen@hp.com.
861 total_sent_thistime = MIN(total_sent_thistime, useable_space);
863 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
864 + data_alignment_offset);
867 * We might have SMBtrans2s in req which was transferred to
868 * the outbuf, fix that.
870 SCVAL(req->outbuf, smb_com, SMBtrans2);
872 /* Set total params and data to be sent */
873 SSVAL(req->outbuf,smb_tprcnt,paramsize);
874 SSVAL(req->outbuf,smb_tdrcnt,datasize);
876 /* Calculate how many parameters and data we can fit into
877 * this packet. Parameters get precedence
880 params_sent_thistime = MIN(params_to_send,useable_space);
881 data_sent_thistime = useable_space - params_sent_thistime;
882 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
884 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
886 /* smb_proff is the offset from the start of the SMB header to the
887 parameter bytes, however the first 4 bytes of outbuf are
888 the Netbios over TCP header. Thus use smb_base() to subtract
889 them from the calculation */
891 SSVAL(req->outbuf,smb_proff,
892 ((smb_buf(req->outbuf)+alignment_offset)
893 - smb_base(req->outbuf)));
895 if(params_sent_thistime == 0)
896 SSVAL(req->outbuf,smb_prdisp,0);
897 else
898 /* Absolute displacement of param bytes sent in this packet */
899 SSVAL(req->outbuf,smb_prdisp,pp - params);
901 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
902 if(data_sent_thistime == 0) {
903 SSVAL(req->outbuf,smb_droff,0);
904 SSVAL(req->outbuf,smb_drdisp, 0);
905 } else {
906 /* The offset of the data bytes is the offset of the
907 parameter bytes plus the number of parameters being sent this time */
908 SSVAL(req->outbuf, smb_droff,
909 ((smb_buf(req->outbuf)+alignment_offset)
910 - smb_base(req->outbuf))
911 + params_sent_thistime + data_alignment_offset);
912 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
915 /* Initialize the padding for alignment */
917 if (alignment_offset != 0) {
918 memset(smb_buf(req->outbuf), 0, alignment_offset);
921 /* Copy the param bytes into the packet */
923 if(params_sent_thistime) {
924 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
925 params_sent_thistime);
928 /* Copy in the data bytes */
929 if(data_sent_thistime) {
930 if (data_alignment_offset != 0) {
931 memset((smb_buf(req->outbuf)+alignment_offset+
932 params_sent_thistime), 0,
933 data_alignment_offset);
935 memcpy(smb_buf(req->outbuf)+alignment_offset
936 +params_sent_thistime+data_alignment_offset,
937 pd,data_sent_thistime);
940 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
941 params_sent_thistime, data_sent_thistime, useable_space));
942 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
943 params_to_send, data_to_send, paramsize, datasize));
945 if (overflow) {
946 error_packet_set((char *)req->outbuf,
947 ERRDOS,ERRbufferoverflow,
948 STATUS_BUFFER_OVERFLOW,
949 __LINE__,__FILE__);
952 /* Send the packet */
953 show_msg((char *)req->outbuf);
954 if (!srv_send_smb(sconn,
955 (char *)req->outbuf,
956 true, req->seqnum+1,
957 IS_CONN_ENCRYPTED(conn),
958 &req->pcd))
959 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
961 TALLOC_FREE(req->outbuf);
963 pp += params_sent_thistime;
964 pd += data_sent_thistime;
966 params_to_send -= params_sent_thistime;
967 data_to_send -= data_sent_thistime;
969 /* Sanity check */
970 if(params_to_send < 0 || data_to_send < 0) {
971 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
972 params_to_send, data_to_send));
973 return;
977 return;
980 /****************************************************************************
981 Reply to a TRANSACT2_OPEN.
982 ****************************************************************************/
984 static void call_trans2open(connection_struct *conn,
985 struct smb_request *req,
986 char **pparams, int total_params,
987 char **ppdata, int total_data,
988 unsigned int max_data_bytes)
990 struct smb_filename *smb_fname = NULL;
991 char *params = *pparams;
992 char *pdata = *ppdata;
993 int deny_mode;
994 int32 open_attr;
995 bool oplock_request;
996 #if 0
997 bool return_additional_info;
998 int16 open_sattr;
999 time_t open_time;
1000 #endif
1001 int open_ofun;
1002 uint32 open_size;
1003 char *pname;
1004 char *fname = NULL;
1005 SMB_OFF_T size=0;
1006 int fattr=0,mtime=0;
1007 SMB_INO_T inode = 0;
1008 int smb_action = 0;
1009 files_struct *fsp;
1010 struct ea_list *ea_list = NULL;
1011 uint16 flags = 0;
1012 NTSTATUS status;
1013 uint32 access_mask;
1014 uint32 share_mode;
1015 uint32 create_disposition;
1016 uint32 create_options = 0;
1017 uint32_t private_flags = 0;
1018 TALLOC_CTX *ctx = talloc_tos();
1021 * Ensure we have enough parameters to perform the operation.
1024 if (total_params < 29) {
1025 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1026 goto out;
1029 flags = SVAL(params, 0);
1030 deny_mode = SVAL(params, 2);
1031 open_attr = SVAL(params,6);
1032 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1033 if (oplock_request) {
1034 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1037 #if 0
1038 return_additional_info = BITSETW(params,0);
1039 open_sattr = SVAL(params, 4);
1040 open_time = make_unix_date3(params+8);
1041 #endif
1042 open_ofun = SVAL(params,12);
1043 open_size = IVAL(params,14);
1044 pname = &params[28];
1046 if (IS_IPC(conn)) {
1047 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1048 goto out;
1051 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1052 total_params - 28, STR_TERMINATE,
1053 &status);
1054 if (!NT_STATUS_IS_OK(status)) {
1055 reply_nterror(req, status);
1056 goto out;
1059 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1060 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1061 (unsigned int)open_ofun, open_size));
1063 status = filename_convert(ctx,
1064 conn,
1065 req->flags2 & FLAGS2_DFS_PATHNAMES,
1066 fname,
1068 NULL,
1069 &smb_fname);
1070 if (!NT_STATUS_IS_OK(status)) {
1071 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1072 reply_botherror(req,
1073 NT_STATUS_PATH_NOT_COVERED,
1074 ERRSRV, ERRbadpath);
1075 goto out;
1077 reply_nterror(req, status);
1078 goto out;
1081 if (open_ofun == 0) {
1082 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1083 goto out;
1086 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1087 &access_mask, &share_mode,
1088 &create_disposition,
1089 &create_options,
1090 &private_flags)) {
1091 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1092 goto out;
1095 /* Any data in this call is an EA list. */
1096 if (total_data && (total_data != 4)) {
1097 if (total_data < 10) {
1098 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1099 goto out;
1102 if (IVAL(pdata,0) > total_data) {
1103 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1104 IVAL(pdata,0), (unsigned int)total_data));
1105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1106 goto out;
1109 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1110 total_data - 4);
1111 if (!ea_list) {
1112 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1113 goto out;
1116 if (!lp_ea_support(SNUM(conn))) {
1117 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1118 goto out;
1122 status = SMB_VFS_CREATE_FILE(
1123 conn, /* conn */
1124 req, /* req */
1125 0, /* root_dir_fid */
1126 smb_fname, /* fname */
1127 access_mask, /* access_mask */
1128 share_mode, /* share_access */
1129 create_disposition, /* create_disposition*/
1130 create_options, /* create_options */
1131 open_attr, /* file_attributes */
1132 oplock_request, /* oplock_request */
1133 open_size, /* allocation_size */
1134 private_flags,
1135 NULL, /* sd */
1136 ea_list, /* ea_list */
1137 &fsp, /* result */
1138 &smb_action); /* psbuf */
1140 if (!NT_STATUS_IS_OK(status)) {
1141 if (open_was_deferred(req->mid)) {
1142 /* We have re-scheduled this call. */
1143 goto out;
1145 reply_openerror(req, status);
1146 goto out;
1149 size = get_file_size_stat(&smb_fname->st);
1150 fattr = dos_mode(conn, smb_fname);
1151 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1152 inode = smb_fname->st.st_ex_ino;
1153 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1154 close_file(req, fsp, ERROR_CLOSE);
1155 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1156 goto out;
1159 /* Realloc the size of parameters and data we will return */
1160 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1161 if(*pparams == NULL ) {
1162 reply_nterror(req, NT_STATUS_NO_MEMORY);
1163 goto out;
1165 params = *pparams;
1167 SSVAL(params,0,fsp->fnum);
1168 SSVAL(params,2,fattr);
1169 srv_put_dos_date2(params,4, mtime);
1170 SIVAL(params,8, (uint32)size);
1171 SSVAL(params,12,deny_mode);
1172 SSVAL(params,14,0); /* open_type - file or directory. */
1173 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1175 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1176 smb_action |= EXTENDED_OPLOCK_GRANTED;
1179 SSVAL(params,18,smb_action);
1182 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1184 SIVAL(params,20,inode);
1185 SSVAL(params,24,0); /* Padding. */
1186 if (flags & 8) {
1187 uint32 ea_size = estimate_ea_size(conn, fsp,
1188 fsp->fsp_name->base_name);
1189 SIVAL(params, 26, ea_size);
1190 } else {
1191 SIVAL(params, 26, 0);
1194 /* Send the required number of replies */
1195 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1196 out:
1197 TALLOC_FREE(smb_fname);
1200 /*********************************************************
1201 Routine to check if a given string matches exactly.
1202 as a special case a mask of "." does NOT match. That
1203 is required for correct wildcard semantics
1204 Case can be significant or not.
1205 **********************************************************/
1207 static bool exact_match(bool has_wild,
1208 bool case_sensitive,
1209 const char *str,
1210 const char *mask)
1212 if (mask[0] == '.' && mask[1] == 0) {
1213 return false;
1216 if (has_wild) {
1217 return false;
1220 if (case_sensitive) {
1221 return strcmp(str,mask)==0;
1222 } else {
1223 return StrCaseCmp(str,mask) == 0;
1227 /****************************************************************************
1228 Return the filetype for UNIX extensions.
1229 ****************************************************************************/
1231 static uint32 unix_filetype(mode_t mode)
1233 if(S_ISREG(mode))
1234 return UNIX_TYPE_FILE;
1235 else if(S_ISDIR(mode))
1236 return UNIX_TYPE_DIR;
1237 #ifdef S_ISLNK
1238 else if(S_ISLNK(mode))
1239 return UNIX_TYPE_SYMLINK;
1240 #endif
1241 #ifdef S_ISCHR
1242 else if(S_ISCHR(mode))
1243 return UNIX_TYPE_CHARDEV;
1244 #endif
1245 #ifdef S_ISBLK
1246 else if(S_ISBLK(mode))
1247 return UNIX_TYPE_BLKDEV;
1248 #endif
1249 #ifdef S_ISFIFO
1250 else if(S_ISFIFO(mode))
1251 return UNIX_TYPE_FIFO;
1252 #endif
1253 #ifdef S_ISSOCK
1254 else if(S_ISSOCK(mode))
1255 return UNIX_TYPE_SOCKET;
1256 #endif
1258 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1259 return UNIX_TYPE_UNKNOWN;
1262 /****************************************************************************
1263 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1264 ****************************************************************************/
1266 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1268 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1269 const SMB_STRUCT_STAT *psbuf,
1270 uint32 perms,
1271 enum perm_type ptype,
1272 mode_t *ret_perms)
1274 mode_t ret = 0;
1276 if (perms == SMB_MODE_NO_CHANGE) {
1277 if (!VALID_STAT(*psbuf)) {
1278 return NT_STATUS_INVALID_PARAMETER;
1279 } else {
1280 *ret_perms = psbuf->st_ex_mode;
1281 return NT_STATUS_OK;
1285 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1286 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1287 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1288 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1289 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1290 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1291 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1292 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1293 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1294 #ifdef S_ISVTX
1295 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1296 #endif
1297 #ifdef S_ISGID
1298 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1299 #endif
1300 #ifdef S_ISUID
1301 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1302 #endif
1304 switch (ptype) {
1305 case PERM_NEW_FILE:
1306 /* Apply mode mask */
1307 ret &= lp_create_mask(SNUM(conn));
1308 /* Add in force bits */
1309 ret |= lp_force_create_mode(SNUM(conn));
1310 break;
1311 case PERM_NEW_DIR:
1312 ret &= lp_dir_mask(SNUM(conn));
1313 /* Add in force bits */
1314 ret |= lp_force_dir_mode(SNUM(conn));
1315 break;
1316 case PERM_EXISTING_FILE:
1317 /* Apply mode mask */
1318 ret &= lp_security_mask(SNUM(conn));
1319 /* Add in force bits */
1320 ret |= lp_force_security_mode(SNUM(conn));
1321 break;
1322 case PERM_EXISTING_DIR:
1323 /* Apply mode mask */
1324 ret &= lp_dir_security_mask(SNUM(conn));
1325 /* Add in force bits */
1326 ret |= lp_force_dir_security_mode(SNUM(conn));
1327 break;
1330 *ret_perms = ret;
1331 return NT_STATUS_OK;
1334 /****************************************************************************
1335 Needed to show the msdfs symlinks as directories. Modifies psbuf
1336 to be a directory if it's a msdfs link.
1337 ****************************************************************************/
1339 static bool check_msdfs_link(connection_struct *conn,
1340 const char *pathname,
1341 SMB_STRUCT_STAT *psbuf)
1343 int saved_errno = errno;
1344 if(lp_host_msdfs() &&
1345 lp_msdfs_root(SNUM(conn)) &&
1346 is_msdfs_link(conn, pathname, psbuf)) {
1348 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1349 "as a directory\n",
1350 pathname));
1351 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1352 errno = saved_errno;
1353 return true;
1355 errno = saved_errno;
1356 return false;
1360 /****************************************************************************
1361 Get a level dependent lanman2 dir entry.
1362 ****************************************************************************/
1364 struct smbd_dirptr_lanman2_state {
1365 connection_struct *conn;
1366 uint32_t info_level;
1367 bool check_mangled_names;
1368 bool has_wild;
1369 bool got_exact_match;
1372 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1373 void *private_data,
1374 const char *dname,
1375 const char *mask,
1376 char **_fname)
1378 struct smbd_dirptr_lanman2_state *state =
1379 (struct smbd_dirptr_lanman2_state *)private_data;
1380 bool ok;
1381 char mangled_name[13]; /* mangled 8.3 name. */
1382 bool got_match;
1383 const char *fname;
1385 /* Mangle fname if it's an illegal name. */
1386 if (mangle_must_mangle(dname, state->conn->params)) {
1387 ok = name_to_8_3(dname, mangled_name,
1388 true, state->conn->params);
1389 if (!ok) {
1390 return false;
1392 fname = mangled_name;
1393 } else {
1394 fname = dname;
1397 got_match = exact_match(state->has_wild,
1398 state->conn->case_sensitive,
1399 fname, mask);
1400 state->got_exact_match = got_match;
1401 if (!got_match) {
1402 got_match = mask_match(fname, mask,
1403 state->conn->case_sensitive);
1406 if(!got_match && state->check_mangled_names &&
1407 !mangle_is_8_3(fname, false, state->conn->params)) {
1409 * It turns out that NT matches wildcards against
1410 * both long *and* short names. This may explain some
1411 * of the wildcard wierdness from old DOS clients
1412 * that some people have been seeing.... JRA.
1414 /* Force the mangling into 8.3. */
1415 ok = name_to_8_3(fname, mangled_name,
1416 false, state->conn->params);
1417 if (!ok) {
1418 return false;
1421 got_match = exact_match(state->has_wild,
1422 state->conn->case_sensitive,
1423 mangled_name, mask);
1424 state->got_exact_match = got_match;
1425 if (!got_match) {
1426 got_match = mask_match(mangled_name, mask,
1427 state->conn->case_sensitive);
1431 if (!got_match) {
1432 return false;
1435 *_fname = talloc_strdup(ctx, fname);
1436 if (*_fname == NULL) {
1437 return false;
1440 return true;
1443 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1444 void *private_data,
1445 struct smb_filename *smb_fname,
1446 uint32_t *_mode)
1448 struct smbd_dirptr_lanman2_state *state =
1449 (struct smbd_dirptr_lanman2_state *)private_data;
1450 bool ms_dfs_link = false;
1451 uint32_t mode = 0;
1453 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1454 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1455 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1456 "Couldn't lstat [%s] (%s)\n",
1457 smb_fname_str_dbg(smb_fname),
1458 strerror(errno)));
1459 return false;
1461 } else if (!VALID_STAT(smb_fname->st) &&
1462 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1463 /* Needed to show the msdfs symlinks as
1464 * directories */
1466 ms_dfs_link = check_msdfs_link(state->conn,
1467 smb_fname->base_name,
1468 &smb_fname->st);
1469 if (!ms_dfs_link) {
1470 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1471 "Couldn't stat [%s] (%s)\n",
1472 smb_fname_str_dbg(smb_fname),
1473 strerror(errno)));
1474 return false;
1478 if (ms_dfs_link) {
1479 mode = dos_mode_msdfs(state->conn, smb_fname);
1480 } else {
1481 mode = dos_mode(state->conn, smb_fname);
1484 *_mode = mode;
1485 return true;
1488 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1489 connection_struct *conn,
1490 uint16_t flags2,
1491 uint32_t info_level,
1492 struct ea_list *name_list,
1493 bool check_mangled_names,
1494 bool requires_resume_key,
1495 uint32_t mode,
1496 const char *fname,
1497 const struct smb_filename *smb_fname,
1498 int space_remaining,
1499 uint8_t align,
1500 bool do_pad,
1501 char *base_data,
1502 char **ppdata,
1503 char *end_data,
1504 bool *out_of_space,
1505 uint64_t *last_entry_off)
1507 char *p, *q, *pdata = *ppdata;
1508 uint32_t reskey=0;
1509 uint64_t file_size = 0;
1510 uint64_t allocation_size = 0;
1511 uint64_t file_index = 0;
1512 uint32_t len;
1513 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1514 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1515 time_t c_date = (time_t)0;
1516 char *nameptr;
1517 char *last_entry_ptr;
1518 bool was_8_3;
1519 int off;
1520 int pad = 0;
1522 *out_of_space = false;
1524 ZERO_STRUCT(mdate_ts);
1525 ZERO_STRUCT(adate_ts);
1526 ZERO_STRUCT(create_date_ts);
1527 ZERO_STRUCT(cdate_ts);
1529 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1530 file_size = get_file_size_stat(&smb_fname->st);
1532 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1534 file_index = get_FileIndex(conn, &smb_fname->st);
1536 mdate_ts = smb_fname->st.st_ex_mtime;
1537 adate_ts = smb_fname->st.st_ex_atime;
1538 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1539 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1541 if (lp_dos_filetime_resolution(SNUM(conn))) {
1542 dos_filetime_timespec(&create_date_ts);
1543 dos_filetime_timespec(&mdate_ts);
1544 dos_filetime_timespec(&adate_ts);
1545 dos_filetime_timespec(&cdate_ts);
1548 create_date = convert_timespec_to_time_t(create_date_ts);
1549 mdate = convert_timespec_to_time_t(mdate_ts);
1550 adate = convert_timespec_to_time_t(adate_ts);
1551 c_date = convert_timespec_to_time_t(cdate_ts);
1553 /* align the record */
1554 SMB_ASSERT(align >= 1);
1556 off = (int)PTR_DIFF(pdata, base_data);
1557 pad = (off + (align-1)) & ~(align-1);
1558 pad -= off;
1560 if (pad && pad > space_remaining) {
1561 *out_of_space = true;
1562 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1563 "for padding (wanted %u, had %d)\n",
1564 (unsigned int)pad,
1565 space_remaining ));
1566 return false; /* Not finished - just out of space */
1569 off += pad;
1570 /* initialize padding to 0 */
1571 if (pad) {
1572 memset(pdata, 0, pad);
1574 space_remaining -= pad;
1576 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1577 space_remaining ));
1579 pdata += pad;
1580 p = pdata;
1581 last_entry_ptr = p;
1583 pad = 0;
1584 off = 0;
1586 switch (info_level) {
1587 case SMB_FIND_INFO_STANDARD:
1588 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1589 if(requires_resume_key) {
1590 SIVAL(p,0,reskey);
1591 p += 4;
1593 srv_put_dos_date2(p,0,create_date);
1594 srv_put_dos_date2(p,4,adate);
1595 srv_put_dos_date2(p,8,mdate);
1596 SIVAL(p,12,(uint32)file_size);
1597 SIVAL(p,16,(uint32)allocation_size);
1598 SSVAL(p,20,mode);
1599 p += 23;
1600 nameptr = p;
1601 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1602 p += ucs2_align(base_data, p, 0);
1604 len = srvstr_push(base_data, flags2, p,
1605 fname, PTR_DIFF(end_data, p),
1606 STR_TERMINATE);
1607 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1608 if (len > 2) {
1609 SCVAL(nameptr, -1, len - 2);
1610 } else {
1611 SCVAL(nameptr, -1, 0);
1613 } else {
1614 if (len > 1) {
1615 SCVAL(nameptr, -1, len - 1);
1616 } else {
1617 SCVAL(nameptr, -1, 0);
1620 p += len;
1621 break;
1623 case SMB_FIND_EA_SIZE:
1624 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1625 if (requires_resume_key) {
1626 SIVAL(p,0,reskey);
1627 p += 4;
1629 srv_put_dos_date2(p,0,create_date);
1630 srv_put_dos_date2(p,4,adate);
1631 srv_put_dos_date2(p,8,mdate);
1632 SIVAL(p,12,(uint32)file_size);
1633 SIVAL(p,16,(uint32)allocation_size);
1634 SSVAL(p,20,mode);
1636 unsigned int ea_size = estimate_ea_size(conn, NULL,
1637 smb_fname->base_name);
1638 SIVAL(p,22,ea_size); /* Extended attributes */
1640 p += 27;
1641 nameptr = p - 1;
1642 len = srvstr_push(base_data, flags2,
1643 p, fname, PTR_DIFF(end_data, p),
1644 STR_TERMINATE | STR_NOALIGN);
1645 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1646 if (len > 2) {
1647 len -= 2;
1648 } else {
1649 len = 0;
1651 } else {
1652 if (len > 1) {
1653 len -= 1;
1654 } else {
1655 len = 0;
1658 SCVAL(nameptr,0,len);
1659 p += len;
1660 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1661 break;
1663 case SMB_FIND_EA_LIST:
1665 struct ea_list *file_list = NULL;
1666 size_t ea_len = 0;
1668 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1669 if (!name_list) {
1670 return false;
1672 if (requires_resume_key) {
1673 SIVAL(p,0,reskey);
1674 p += 4;
1676 srv_put_dos_date2(p,0,create_date);
1677 srv_put_dos_date2(p,4,adate);
1678 srv_put_dos_date2(p,8,mdate);
1679 SIVAL(p,12,(uint32)file_size);
1680 SIVAL(p,16,(uint32)allocation_size);
1681 SSVAL(p,20,mode);
1682 p += 22; /* p now points to the EA area. */
1684 file_list = get_ea_list_from_file(ctx, conn, NULL,
1685 smb_fname->base_name,
1686 &ea_len);
1687 name_list = ea_list_union(name_list, file_list, &ea_len);
1689 /* We need to determine if this entry will fit in the space available. */
1690 /* Max string size is 255 bytes. */
1691 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1692 *out_of_space = true;
1693 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1694 "(wanted %u, had %d)\n",
1695 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1696 space_remaining ));
1697 return False; /* Not finished - just out of space */
1700 /* Push the ea_data followed by the name. */
1701 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1702 nameptr = p;
1703 len = srvstr_push(base_data, flags2,
1704 p + 1, fname, PTR_DIFF(end_data, p+1),
1705 STR_TERMINATE | STR_NOALIGN);
1706 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1707 if (len > 2) {
1708 len -= 2;
1709 } else {
1710 len = 0;
1712 } else {
1713 if (len > 1) {
1714 len -= 1;
1715 } else {
1716 len = 0;
1719 SCVAL(nameptr,0,len);
1720 p += len + 1;
1721 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1722 break;
1725 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1726 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1727 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1728 p += 4;
1729 SIVAL(p,0,reskey); p += 4;
1730 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1731 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1732 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1733 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1734 SOFF_T(p,0,file_size); p += 8;
1735 SOFF_T(p,0,allocation_size); p += 8;
1736 SIVAL(p,0,mode); p += 4;
1737 q = p; p += 4; /* q is placeholder for name length. */
1739 unsigned int ea_size = estimate_ea_size(conn, NULL,
1740 smb_fname->base_name);
1741 SIVAL(p,0,ea_size); /* Extended attributes */
1742 p += 4;
1744 /* Clear the short name buffer. This is
1745 * IMPORTANT as not doing so will trigger
1746 * a Win2k client bug. JRA.
1748 if (!was_8_3 && check_mangled_names) {
1749 char mangled_name[13]; /* mangled 8.3 name. */
1750 if (!name_to_8_3(fname,mangled_name,True,
1751 conn->params)) {
1752 /* Error - mangle failed ! */
1753 memset(mangled_name,'\0',12);
1755 mangled_name[12] = 0;
1756 len = srvstr_push(base_data, flags2,
1757 p+2, mangled_name, 24,
1758 STR_UPPER|STR_UNICODE);
1759 if (len < 24) {
1760 memset(p + 2 + len,'\0',24 - len);
1762 SSVAL(p, 0, len);
1763 } else {
1764 memset(p,'\0',26);
1766 p += 2 + 24;
1767 len = srvstr_push(base_data, flags2, p,
1768 fname, PTR_DIFF(end_data, p),
1769 STR_TERMINATE_ASCII);
1770 SIVAL(q,0,len);
1771 p += len;
1773 len = PTR_DIFF(p, pdata);
1774 pad = (len + (align-1)) & ~(align-1);
1776 * offset to the next entry, the caller
1777 * will overwrite it for the last entry
1778 * that's why we always include the padding
1780 SIVAL(pdata,0,pad);
1782 * set padding to zero
1784 if (do_pad) {
1785 memset(p, 0, pad - len);
1786 p = pdata + pad;
1787 } else {
1788 p = pdata + len;
1790 break;
1792 case SMB_FIND_FILE_DIRECTORY_INFO:
1793 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1794 p += 4;
1795 SIVAL(p,0,reskey); p += 4;
1796 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1797 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1798 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1799 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1800 SOFF_T(p,0,file_size); p += 8;
1801 SOFF_T(p,0,allocation_size); p += 8;
1802 SIVAL(p,0,mode); p += 4;
1803 len = srvstr_push(base_data, flags2,
1804 p + 4, fname, PTR_DIFF(end_data, p+4),
1805 STR_TERMINATE_ASCII);
1806 SIVAL(p,0,len);
1807 p += 4 + len;
1809 len = PTR_DIFF(p, pdata);
1810 pad = (len + (align-1)) & ~(align-1);
1812 * offset to the next entry, the caller
1813 * will overwrite it for the last entry
1814 * that's why we always include the padding
1816 SIVAL(pdata,0,pad);
1818 * set padding to zero
1820 if (do_pad) {
1821 memset(p, 0, pad - len);
1822 p = pdata + pad;
1823 } else {
1824 p = pdata + len;
1826 break;
1828 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1829 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1830 p += 4;
1831 SIVAL(p,0,reskey); p += 4;
1832 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1833 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1834 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1835 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1836 SOFF_T(p,0,file_size); p += 8;
1837 SOFF_T(p,0,allocation_size); p += 8;
1838 SIVAL(p,0,mode); p += 4;
1839 q = p; p += 4; /* q is placeholder for name length. */
1841 unsigned int ea_size = estimate_ea_size(conn, NULL,
1842 smb_fname->base_name);
1843 SIVAL(p,0,ea_size); /* Extended attributes */
1844 p +=4;
1846 len = srvstr_push(base_data, flags2, p,
1847 fname, PTR_DIFF(end_data, p),
1848 STR_TERMINATE_ASCII);
1849 SIVAL(q, 0, len);
1850 p += len;
1852 len = PTR_DIFF(p, pdata);
1853 pad = (len + (align-1)) & ~(align-1);
1855 * offset to the next entry, the caller
1856 * will overwrite it for the last entry
1857 * that's why we always include the padding
1859 SIVAL(pdata,0,pad);
1861 * set padding to zero
1863 if (do_pad) {
1864 memset(p, 0, pad - len);
1865 p = pdata + pad;
1866 } else {
1867 p = pdata + len;
1869 break;
1871 case SMB_FIND_FILE_NAMES_INFO:
1872 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1873 p += 4;
1874 SIVAL(p,0,reskey); p += 4;
1875 p += 4;
1876 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1877 acl on a dir (tridge) */
1878 len = srvstr_push(base_data, flags2, p,
1879 fname, PTR_DIFF(end_data, p),
1880 STR_TERMINATE_ASCII);
1881 SIVAL(p, -4, len);
1882 p += len;
1884 len = PTR_DIFF(p, pdata);
1885 pad = (len + (align-1)) & ~(align-1);
1887 * offset to the next entry, the caller
1888 * will overwrite it for the last entry
1889 * that's why we always include the padding
1891 SIVAL(pdata,0,pad);
1893 * set padding to zero
1895 if (do_pad) {
1896 memset(p, 0, pad - len);
1897 p = pdata + pad;
1898 } else {
1899 p = pdata + len;
1901 break;
1903 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1904 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1905 p += 4;
1906 SIVAL(p,0,reskey); p += 4;
1907 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1908 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1909 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1910 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1911 SOFF_T(p,0,file_size); p += 8;
1912 SOFF_T(p,0,allocation_size); p += 8;
1913 SIVAL(p,0,mode); p += 4;
1914 q = p; p += 4; /* q is placeholder for name length. */
1916 unsigned int ea_size = estimate_ea_size(conn, NULL,
1917 smb_fname->base_name);
1918 SIVAL(p,0,ea_size); /* Extended attributes */
1919 p +=4;
1921 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1922 SBVAL(p,0,file_index); p += 8;
1923 len = srvstr_push(base_data, flags2, p,
1924 fname, PTR_DIFF(end_data, p),
1925 STR_TERMINATE_ASCII);
1926 SIVAL(q, 0, len);
1927 p += len;
1929 len = PTR_DIFF(p, pdata);
1930 pad = (len + (align-1)) & ~(align-1);
1932 * offset to the next entry, the caller
1933 * will overwrite it for the last entry
1934 * that's why we always include the padding
1936 SIVAL(pdata,0,pad);
1938 * set padding to zero
1940 if (do_pad) {
1941 memset(p, 0, pad - len);
1942 p = pdata + pad;
1943 } else {
1944 p = pdata + len;
1946 break;
1948 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1949 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1950 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1951 p += 4;
1952 SIVAL(p,0,reskey); p += 4;
1953 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1954 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1955 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1956 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1957 SOFF_T(p,0,file_size); p += 8;
1958 SOFF_T(p,0,allocation_size); p += 8;
1959 SIVAL(p,0,mode); p += 4;
1960 q = p; p += 4; /* q is placeholder for name length */
1962 unsigned int ea_size = estimate_ea_size(conn, NULL,
1963 smb_fname->base_name);
1964 SIVAL(p,0,ea_size); /* Extended attributes */
1965 p +=4;
1967 /* Clear the short name buffer. This is
1968 * IMPORTANT as not doing so will trigger
1969 * a Win2k client bug. JRA.
1971 if (!was_8_3 && check_mangled_names) {
1972 char mangled_name[13]; /* mangled 8.3 name. */
1973 if (!name_to_8_3(fname,mangled_name,True,
1974 conn->params)) {
1975 /* Error - mangle failed ! */
1976 memset(mangled_name,'\0',12);
1978 mangled_name[12] = 0;
1979 len = srvstr_push(base_data, flags2,
1980 p+2, mangled_name, 24,
1981 STR_UPPER|STR_UNICODE);
1982 SSVAL(p, 0, len);
1983 if (len < 24) {
1984 memset(p + 2 + len,'\0',24 - len);
1986 SSVAL(p, 0, len);
1987 } else {
1988 memset(p,'\0',26);
1990 p += 26;
1991 SSVAL(p,0,0); p += 2; /* Reserved ? */
1992 SBVAL(p,0,file_index); p += 8;
1993 len = srvstr_push(base_data, flags2, p,
1994 fname, PTR_DIFF(end_data, p),
1995 STR_TERMINATE_ASCII);
1996 SIVAL(q,0,len);
1997 p += len;
1999 len = PTR_DIFF(p, pdata);
2000 pad = (len + (align-1)) & ~(align-1);
2002 * offset to the next entry, the caller
2003 * will overwrite it for the last entry
2004 * that's why we always include the padding
2006 SIVAL(pdata,0,pad);
2008 * set padding to zero
2010 if (do_pad) {
2011 memset(p, 0, pad - len);
2012 p = pdata + pad;
2013 } else {
2014 p = pdata + len;
2016 break;
2018 /* CIFS UNIX Extension. */
2020 case SMB_FIND_FILE_UNIX:
2021 case SMB_FIND_FILE_UNIX_INFO2:
2022 p+= 4;
2023 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2025 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2027 if (info_level == SMB_FIND_FILE_UNIX) {
2028 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2029 p = store_file_unix_basic(conn, p,
2030 NULL, &smb_fname->st);
2031 len = srvstr_push(base_data, flags2, p,
2032 fname, PTR_DIFF(end_data, p),
2033 STR_TERMINATE);
2034 } else {
2035 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2036 p = store_file_unix_basic_info2(conn, p,
2037 NULL, &smb_fname->st);
2038 nameptr = p;
2039 p += 4;
2040 len = srvstr_push(base_data, flags2, p, fname,
2041 PTR_DIFF(end_data, p), 0);
2042 SIVAL(nameptr, 0, len);
2045 p += len;
2047 len = PTR_DIFF(p, pdata);
2048 pad = (len + (align-1)) & ~(align-1);
2050 * offset to the next entry, the caller
2051 * will overwrite it for the last entry
2052 * that's why we always include the padding
2054 SIVAL(pdata,0,pad);
2056 * set padding to zero
2058 if (do_pad) {
2059 memset(p, 0, pad - len);
2060 p = pdata + pad;
2061 } else {
2062 p = pdata + len;
2064 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2066 break;
2068 default:
2069 return false;
2072 if (PTR_DIFF(p,pdata) > space_remaining) {
2073 *out_of_space = true;
2074 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2075 "(wanted %u, had %d)\n",
2076 (unsigned int)PTR_DIFF(p,pdata),
2077 space_remaining ));
2078 return false; /* Not finished - just out of space */
2081 /* Setup the last entry pointer, as an offset from base_data */
2082 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2083 /* Advance the data pointer to the next slot */
2084 *ppdata = p;
2086 return true;
2089 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2090 connection_struct *conn,
2091 struct dptr_struct *dirptr,
2092 uint16 flags2,
2093 const char *path_mask,
2094 uint32 dirtype,
2095 int info_level,
2096 int requires_resume_key,
2097 bool dont_descend,
2098 bool ask_sharemode,
2099 uint8_t align,
2100 bool do_pad,
2101 char **ppdata,
2102 char *base_data,
2103 char *end_data,
2104 int space_remaining,
2105 bool *out_of_space,
2106 bool *got_exact_match,
2107 int *_last_entry_off,
2108 struct ea_list *name_list)
2110 const char *p;
2111 const char *mask = NULL;
2112 long prev_dirpos = 0;
2113 uint32_t mode = 0;
2114 char *fname = NULL;
2115 struct smb_filename *smb_fname = NULL;
2116 struct smbd_dirptr_lanman2_state state;
2117 bool ok;
2118 uint64_t last_entry_off = 0;
2120 ZERO_STRUCT(state);
2121 state.conn = conn;
2122 state.info_level = info_level;
2123 state.check_mangled_names = lp_manglednames(conn->params);
2124 state.has_wild = dptr_has_wild(dirptr);
2125 state.got_exact_match = false;
2127 *out_of_space = false;
2128 *got_exact_match = false;
2130 p = strrchr_m(path_mask,'/');
2131 if(p != NULL) {
2132 if(p[1] == '\0') {
2133 mask = "*.*";
2134 } else {
2135 mask = p+1;
2137 } else {
2138 mask = path_mask;
2141 ok = smbd_dirptr_get_entry(ctx,
2142 dirptr,
2143 mask,
2144 dirtype,
2145 dont_descend,
2146 ask_sharemode,
2147 smbd_dirptr_lanman2_match_fn,
2148 smbd_dirptr_lanman2_mode_fn,
2149 &state,
2150 &fname,
2151 &smb_fname,
2152 &mode,
2153 &prev_dirpos);
2154 if (!ok) {
2155 return false;
2158 *got_exact_match = state.got_exact_match;
2160 ok = smbd_marshall_dir_entry(ctx,
2161 conn,
2162 flags2,
2163 info_level,
2164 name_list,
2165 state.check_mangled_names,
2166 requires_resume_key,
2167 mode,
2168 fname,
2169 smb_fname,
2170 space_remaining,
2171 align,
2172 do_pad,
2173 base_data,
2174 ppdata,
2175 end_data,
2176 out_of_space,
2177 &last_entry_off);
2178 TALLOC_FREE(fname);
2179 TALLOC_FREE(smb_fname);
2180 if (*out_of_space) {
2181 dptr_SeekDir(dirptr, prev_dirpos);
2182 return false;
2184 if (!ok) {
2185 return false;
2188 *_last_entry_off = last_entry_off;
2189 return true;
2192 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2193 connection_struct *conn,
2194 struct dptr_struct *dirptr,
2195 uint16 flags2,
2196 const char *path_mask,
2197 uint32 dirtype,
2198 int info_level,
2199 bool requires_resume_key,
2200 bool dont_descend,
2201 bool ask_sharemode,
2202 char **ppdata,
2203 char *base_data,
2204 char *end_data,
2205 int space_remaining,
2206 bool *out_of_space,
2207 bool *got_exact_match,
2208 int *last_entry_off,
2209 struct ea_list *name_list)
2211 uint8_t align = 4;
2212 const bool do_pad = true;
2214 if (info_level >= 1 && info_level <= 3) {
2215 /* No alignment on earlier info levels. */
2216 align = 1;
2219 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2220 path_mask, dirtype, info_level,
2221 requires_resume_key, dont_descend, ask_sharemode,
2222 align, do_pad,
2223 ppdata, base_data, end_data,
2224 space_remaining,
2225 out_of_space, got_exact_match,
2226 last_entry_off, name_list);
2229 /****************************************************************************
2230 Reply to a TRANS2_FINDFIRST.
2231 ****************************************************************************/
2233 static void call_trans2findfirst(connection_struct *conn,
2234 struct smb_request *req,
2235 char **pparams, int total_params,
2236 char **ppdata, int total_data,
2237 unsigned int max_data_bytes)
2239 /* We must be careful here that we don't return more than the
2240 allowed number of data bytes. If this means returning fewer than
2241 maxentries then so be it. We assume that the redirector has
2242 enough room for the fixed number of parameter bytes it has
2243 requested. */
2244 struct smb_filename *smb_dname = NULL;
2245 char *params = *pparams;
2246 char *pdata = *ppdata;
2247 char *data_end;
2248 uint32 dirtype;
2249 int maxentries;
2250 uint16 findfirst_flags;
2251 bool close_after_first;
2252 bool close_if_end;
2253 bool requires_resume_key;
2254 int info_level;
2255 char *directory = NULL;
2256 char *mask = NULL;
2257 char *p;
2258 int last_entry_off=0;
2259 int dptr_num = -1;
2260 int numentries = 0;
2261 int i;
2262 bool finished = False;
2263 bool dont_descend = False;
2264 bool out_of_space = False;
2265 int space_remaining;
2266 bool mask_contains_wcard = False;
2267 struct ea_list *ea_list = NULL;
2268 NTSTATUS ntstatus = NT_STATUS_OK;
2269 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2270 TALLOC_CTX *ctx = talloc_tos();
2271 struct dptr_struct *dirptr = NULL;
2272 struct smbd_server_connection *sconn = req->sconn;
2274 if (total_params < 13) {
2275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2276 goto out;
2279 dirtype = SVAL(params,0);
2280 maxentries = SVAL(params,2);
2281 findfirst_flags = SVAL(params,4);
2282 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2283 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2284 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2285 info_level = SVAL(params,6);
2287 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2288 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2289 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2290 info_level, max_data_bytes));
2292 if (!maxentries) {
2293 /* W2K3 seems to treat zero as 1. */
2294 maxentries = 1;
2297 switch (info_level) {
2298 case SMB_FIND_INFO_STANDARD:
2299 case SMB_FIND_EA_SIZE:
2300 case SMB_FIND_EA_LIST:
2301 case SMB_FIND_FILE_DIRECTORY_INFO:
2302 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2303 case SMB_FIND_FILE_NAMES_INFO:
2304 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2305 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2306 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2307 break;
2308 case SMB_FIND_FILE_UNIX:
2309 case SMB_FIND_FILE_UNIX_INFO2:
2310 /* Always use filesystem for UNIX mtime query. */
2311 ask_sharemode = false;
2312 if (!lp_unix_extensions()) {
2313 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2314 goto out;
2316 break;
2317 default:
2318 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2319 goto out;
2322 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2323 params+12, total_params - 12,
2324 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2325 if (!NT_STATUS_IS_OK(ntstatus)) {
2326 reply_nterror(req, ntstatus);
2327 goto out;
2330 ntstatus = filename_convert(ctx, conn,
2331 req->flags2 & FLAGS2_DFS_PATHNAMES,
2332 directory,
2333 (UCF_SAVE_LCOMP |
2334 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2335 &mask_contains_wcard,
2336 &smb_dname);
2337 if (!NT_STATUS_IS_OK(ntstatus)) {
2338 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2339 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2340 ERRSRV, ERRbadpath);
2341 goto out;
2343 reply_nterror(req, ntstatus);
2344 goto out;
2347 mask = smb_dname->original_lcomp;
2349 directory = smb_dname->base_name;
2351 p = strrchr_m(directory,'/');
2352 if(p == NULL) {
2353 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2354 if((directory[0] == '.') && (directory[1] == '\0')) {
2355 mask = talloc_strdup(ctx,"*");
2356 if (!mask) {
2357 reply_nterror(req, NT_STATUS_NO_MEMORY);
2358 goto out;
2360 mask_contains_wcard = True;
2362 } else {
2363 *p = 0;
2366 if (p == NULL || p == directory) {
2367 /* Ensure we don't have a directory name of "". */
2368 directory = talloc_strdup(talloc_tos(), ".");
2369 if (!directory) {
2370 reply_nterror(req, NT_STATUS_NO_MEMORY);
2371 goto out;
2375 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2377 if (info_level == SMB_FIND_EA_LIST) {
2378 uint32 ea_size;
2380 if (total_data < 4) {
2381 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2382 goto out;
2385 ea_size = IVAL(pdata,0);
2386 if (ea_size != total_data) {
2387 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2388 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2389 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2390 goto out;
2393 if (!lp_ea_support(SNUM(conn))) {
2394 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2395 goto out;
2398 /* Pull out the list of names. */
2399 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2400 if (!ea_list) {
2401 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2402 goto out;
2406 *ppdata = (char *)SMB_REALLOC(
2407 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2408 if(*ppdata == NULL ) {
2409 reply_nterror(req, NT_STATUS_NO_MEMORY);
2410 goto out;
2412 pdata = *ppdata;
2413 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2415 /* Realloc the params space */
2416 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2417 if (*pparams == NULL) {
2418 reply_nterror(req, NT_STATUS_NO_MEMORY);
2419 goto out;
2421 params = *pparams;
2423 /* Save the wildcard match and attribs we are using on this directory -
2424 needed as lanman2 assumes these are being saved between calls */
2426 ntstatus = dptr_create(conn,
2427 NULL, /* fsp */
2428 directory,
2429 False,
2430 True,
2431 req->smbpid,
2432 mask,
2433 mask_contains_wcard,
2434 dirtype,
2435 &dirptr);
2437 if (!NT_STATUS_IS_OK(ntstatus)) {
2438 reply_nterror(req, ntstatus);
2439 goto out;
2442 dptr_num = dptr_dnum(dirptr);
2443 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2445 /* Initialize per TRANS2_FIND_FIRST operation data */
2446 dptr_init_search_op(dirptr);
2448 /* We don't need to check for VOL here as this is returned by
2449 a different TRANS2 call. */
2451 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2452 directory,lp_dontdescend(SNUM(conn))));
2453 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2454 dont_descend = True;
2456 p = pdata;
2457 space_remaining = max_data_bytes;
2458 out_of_space = False;
2460 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2461 bool got_exact_match = False;
2463 /* this is a heuristic to avoid seeking the dirptr except when
2464 absolutely necessary. It allows for a filename of about 40 chars */
2465 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2466 out_of_space = True;
2467 finished = False;
2468 } else {
2469 finished = !get_lanman2_dir_entry(ctx,
2470 conn,
2471 dirptr,
2472 req->flags2,
2473 mask,dirtype,info_level,
2474 requires_resume_key,dont_descend,
2475 ask_sharemode,
2476 &p,pdata,data_end,
2477 space_remaining, &out_of_space,
2478 &got_exact_match,
2479 &last_entry_off, ea_list);
2482 if (finished && out_of_space)
2483 finished = False;
2485 if (!finished && !out_of_space)
2486 numentries++;
2489 * As an optimisation if we know we aren't looking
2490 * for a wildcard name (ie. the name matches the wildcard exactly)
2491 * then we can finish on any (first) match.
2492 * This speeds up large directory searches. JRA.
2495 if(got_exact_match)
2496 finished = True;
2498 /* Ensure space_remaining never goes -ve. */
2499 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2500 space_remaining = 0;
2501 out_of_space = true;
2502 } else {
2503 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2507 /* Check if we can close the dirptr */
2508 if(close_after_first || (finished && close_if_end)) {
2509 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2510 dptr_close(sconn, &dptr_num);
2514 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2515 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2516 * the protocol level is less than NT1. Tested with smbclient. JRA.
2517 * This should fix the OS/2 client bug #2335.
2520 if(numentries == 0) {
2521 dptr_close(sconn, &dptr_num);
2522 if (get_Protocol() < PROTOCOL_NT1) {
2523 reply_force_doserror(req, ERRDOS, ERRnofiles);
2524 goto out;
2525 } else {
2526 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2527 ERRDOS, ERRbadfile);
2528 goto out;
2532 /* At this point pdata points to numentries directory entries. */
2534 /* Set up the return parameter block */
2535 SSVAL(params,0,dptr_num);
2536 SSVAL(params,2,numentries);
2537 SSVAL(params,4,finished);
2538 SSVAL(params,6,0); /* Never an EA error */
2539 SSVAL(params,8,last_entry_off);
2541 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2542 max_data_bytes);
2544 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2545 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2546 if (!directory) {
2547 reply_nterror(req, NT_STATUS_NO_MEMORY);
2551 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2552 smb_fn_name(req->cmd),
2553 mask, directory, dirtype, numentries ) );
2556 * Force a name mangle here to ensure that the
2557 * mask as an 8.3 name is top of the mangled cache.
2558 * The reasons for this are subtle. Don't remove
2559 * this code unless you know what you are doing
2560 * (see PR#13758). JRA.
2563 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2564 char mangled_name[13];
2565 name_to_8_3(mask, mangled_name, True, conn->params);
2567 out:
2568 TALLOC_FREE(smb_dname);
2569 return;
2572 /****************************************************************************
2573 Reply to a TRANS2_FINDNEXT.
2574 ****************************************************************************/
2576 static void call_trans2findnext(connection_struct *conn,
2577 struct smb_request *req,
2578 char **pparams, int total_params,
2579 char **ppdata, int total_data,
2580 unsigned int max_data_bytes)
2582 /* We must be careful here that we don't return more than the
2583 allowed number of data bytes. If this means returning fewer than
2584 maxentries then so be it. We assume that the redirector has
2585 enough room for the fixed number of parameter bytes it has
2586 requested. */
2587 char *params = *pparams;
2588 char *pdata = *ppdata;
2589 char *data_end;
2590 int dptr_num;
2591 int maxentries;
2592 uint16 info_level;
2593 uint32 resume_key;
2594 uint16 findnext_flags;
2595 bool close_after_request;
2596 bool close_if_end;
2597 bool requires_resume_key;
2598 bool continue_bit;
2599 bool mask_contains_wcard = False;
2600 char *resume_name = NULL;
2601 const char *mask = NULL;
2602 const char *directory = NULL;
2603 char *p = NULL;
2604 uint16 dirtype;
2605 int numentries = 0;
2606 int i, last_entry_off=0;
2607 bool finished = False;
2608 bool dont_descend = False;
2609 bool out_of_space = False;
2610 int space_remaining;
2611 struct ea_list *ea_list = NULL;
2612 NTSTATUS ntstatus = NT_STATUS_OK;
2613 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2614 TALLOC_CTX *ctx = talloc_tos();
2615 struct dptr_struct *dirptr;
2616 struct smbd_server_connection *sconn = req->sconn;
2618 if (total_params < 13) {
2619 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2620 return;
2623 dptr_num = SVAL(params,0);
2624 maxentries = SVAL(params,2);
2625 info_level = SVAL(params,4);
2626 resume_key = IVAL(params,6);
2627 findnext_flags = SVAL(params,10);
2628 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2629 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2630 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2631 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2633 if (!continue_bit) {
2634 /* We only need resume_name if continue_bit is zero. */
2635 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2636 params+12,
2637 total_params - 12, STR_TERMINATE, &ntstatus,
2638 &mask_contains_wcard);
2639 if (!NT_STATUS_IS_OK(ntstatus)) {
2640 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2641 complain (it thinks we're asking for the directory above the shared
2642 path or an invalid name). Catch this as the resume name is only compared, never used in
2643 a file access. JRA. */
2644 srvstr_pull_talloc(ctx, params, req->flags2,
2645 &resume_name, params+12,
2646 total_params - 12,
2647 STR_TERMINATE);
2649 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2650 reply_nterror(req, ntstatus);
2651 return;
2656 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2657 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2658 resume_key = %d resume name = %s continue=%d level = %d\n",
2659 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2660 requires_resume_key, resume_key,
2661 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2663 if (!maxentries) {
2664 /* W2K3 seems to treat zero as 1. */
2665 maxentries = 1;
2668 switch (info_level) {
2669 case SMB_FIND_INFO_STANDARD:
2670 case SMB_FIND_EA_SIZE:
2671 case SMB_FIND_EA_LIST:
2672 case SMB_FIND_FILE_DIRECTORY_INFO:
2673 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2674 case SMB_FIND_FILE_NAMES_INFO:
2675 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2676 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2677 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2678 break;
2679 case SMB_FIND_FILE_UNIX:
2680 case SMB_FIND_FILE_UNIX_INFO2:
2681 /* Always use filesystem for UNIX mtime query. */
2682 ask_sharemode = false;
2683 if (!lp_unix_extensions()) {
2684 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2685 return;
2687 break;
2688 default:
2689 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2690 return;
2693 if (info_level == SMB_FIND_EA_LIST) {
2694 uint32 ea_size;
2696 if (total_data < 4) {
2697 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2698 return;
2701 ea_size = IVAL(pdata,0);
2702 if (ea_size != total_data) {
2703 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2704 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2706 return;
2709 if (!lp_ea_support(SNUM(conn))) {
2710 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2711 return;
2714 /* Pull out the list of names. */
2715 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2716 if (!ea_list) {
2717 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2718 return;
2722 *ppdata = (char *)SMB_REALLOC(
2723 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2724 if(*ppdata == NULL) {
2725 reply_nterror(req, NT_STATUS_NO_MEMORY);
2726 return;
2729 pdata = *ppdata;
2730 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2732 /* Realloc the params space */
2733 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2734 if(*pparams == NULL ) {
2735 reply_nterror(req, NT_STATUS_NO_MEMORY);
2736 return;
2739 params = *pparams;
2741 /* Check that the dptr is valid */
2742 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2743 reply_nterror(req, STATUS_NO_MORE_FILES);
2744 return;
2747 directory = dptr_path(sconn, dptr_num);
2749 /* Get the wildcard mask from the dptr */
2750 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2751 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2752 reply_nterror(req, STATUS_NO_MORE_FILES);
2753 return;
2756 mask = p;
2758 /* Get the attr mask from the dptr */
2759 dirtype = dptr_attr(sconn, dptr_num);
2761 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2762 dptr_num, mask, dirtype,
2763 (long)dirptr,
2764 dptr_TellDir(dirptr)));
2766 /* Initialize per TRANS2_FIND_NEXT operation data */
2767 dptr_init_search_op(dirptr);
2769 /* We don't need to check for VOL here as this is returned by
2770 a different TRANS2 call. */
2772 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2773 directory,lp_dontdescend(SNUM(conn))));
2774 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2775 dont_descend = True;
2777 p = pdata;
2778 space_remaining = max_data_bytes;
2779 out_of_space = False;
2782 * Seek to the correct position. We no longer use the resume key but
2783 * depend on the last file name instead.
2786 if(!continue_bit && resume_name && *resume_name) {
2787 SMB_STRUCT_STAT st;
2789 long current_pos = 0;
2791 * Remember, name_to_8_3 is called by
2792 * get_lanman2_dir_entry(), so the resume name
2793 * could be mangled. Ensure we check the unmangled name.
2796 if (mangle_is_mangled(resume_name, conn->params)) {
2797 char *new_resume_name = NULL;
2798 mangle_lookup_name_from_8_3(ctx,
2799 resume_name,
2800 &new_resume_name,
2801 conn->params);
2802 if (new_resume_name) {
2803 resume_name = new_resume_name;
2808 * Fix for NT redirector problem triggered by resume key indexes
2809 * changing between directory scans. We now return a resume key of 0
2810 * and instead look for the filename to continue from (also given
2811 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2812 * findfirst/findnext (as is usual) then the directory pointer
2813 * should already be at the correct place.
2816 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2817 } /* end if resume_name && !continue_bit */
2819 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2820 bool got_exact_match = False;
2822 /* this is a heuristic to avoid seeking the dirptr except when
2823 absolutely necessary. It allows for a filename of about 40 chars */
2824 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2825 out_of_space = True;
2826 finished = False;
2827 } else {
2828 finished = !get_lanman2_dir_entry(ctx,
2829 conn,
2830 dirptr,
2831 req->flags2,
2832 mask,dirtype,info_level,
2833 requires_resume_key,dont_descend,
2834 ask_sharemode,
2835 &p,pdata,data_end,
2836 space_remaining, &out_of_space,
2837 &got_exact_match,
2838 &last_entry_off, ea_list);
2841 if (finished && out_of_space)
2842 finished = False;
2844 if (!finished && !out_of_space)
2845 numentries++;
2848 * As an optimisation if we know we aren't looking
2849 * for a wildcard name (ie. the name matches the wildcard exactly)
2850 * then we can finish on any (first) match.
2851 * This speeds up large directory searches. JRA.
2854 if(got_exact_match)
2855 finished = True;
2857 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2860 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2861 smb_fn_name(req->cmd),
2862 mask, directory, dirtype, numentries ) );
2864 /* Check if we can close the dirptr */
2865 if(close_after_request || (finished && close_if_end)) {
2866 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2867 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2870 /* Set up the return parameter block */
2871 SSVAL(params,0,numentries);
2872 SSVAL(params,2,finished);
2873 SSVAL(params,4,0); /* Never an EA error */
2874 SSVAL(params,6,last_entry_off);
2876 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2877 max_data_bytes);
2879 return;
2882 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2884 E_md4hash(lp_servicename(SNUM(conn)),objid);
2885 return objid;
2888 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2890 SMB_ASSERT(extended_info != NULL);
2892 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2893 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2894 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2895 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2896 #ifdef SAMBA_VERSION_REVISION
2897 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2898 #endif
2899 extended_info->samba_subversion = 0;
2900 #ifdef SAMBA_VERSION_RC_RELEASE
2901 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2902 #else
2903 #ifdef SAMBA_VERSION_PRE_RELEASE
2904 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2905 #endif
2906 #endif
2907 #ifdef SAMBA_VERSION_VENDOR_PATCH
2908 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2909 #endif
2910 extended_info->samba_gitcommitdate = 0;
2911 #ifdef SAMBA_VERSION_COMMIT_TIME
2912 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2913 #endif
2915 memset(extended_info->samba_version_string, 0,
2916 sizeof(extended_info->samba_version_string));
2918 snprintf (extended_info->samba_version_string,
2919 sizeof(extended_info->samba_version_string),
2920 "%s", samba_version_string());
2923 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2924 TALLOC_CTX *mem_ctx,
2925 uint16_t info_level,
2926 uint16_t flags2,
2927 unsigned int max_data_bytes,
2928 char **ppdata,
2929 int *ret_data_len)
2931 char *pdata, *end_data;
2932 int data_len = 0, len;
2933 const char *vname = volume_label(SNUM(conn));
2934 int snum = SNUM(conn);
2935 char *fstype = lp_fstype(SNUM(conn));
2936 uint32 additional_flags = 0;
2937 struct smb_filename smb_fname_dot;
2938 SMB_STRUCT_STAT st;
2940 if (IS_IPC(conn)) {
2941 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2942 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2943 "info level (0x%x) on IPC$.\n",
2944 (unsigned int)info_level));
2945 return NT_STATUS_ACCESS_DENIED;
2949 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2951 ZERO_STRUCT(smb_fname_dot);
2952 smb_fname_dot.base_name = discard_const_p(char, ".");
2954 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2955 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2956 return map_nt_error_from_unix(errno);
2959 st = smb_fname_dot.st;
2961 *ppdata = (char *)SMB_REALLOC(
2962 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2963 if (*ppdata == NULL) {
2964 return NT_STATUS_NO_MEMORY;
2967 pdata = *ppdata;
2968 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2969 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2971 switch (info_level) {
2972 case SMB_INFO_ALLOCATION:
2974 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2975 data_len = 18;
2976 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2977 return map_nt_error_from_unix(errno);
2980 block_size = lp_block_size(snum);
2981 if (bsize < block_size) {
2982 uint64_t factor = block_size/bsize;
2983 bsize = block_size;
2984 dsize /= factor;
2985 dfree /= factor;
2987 if (bsize > block_size) {
2988 uint64_t factor = bsize/block_size;
2989 bsize = block_size;
2990 dsize *= factor;
2991 dfree *= factor;
2993 bytes_per_sector = 512;
2994 sectors_per_unit = bsize/bytes_per_sector;
2996 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2997 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2998 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3000 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3001 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3002 SIVAL(pdata,l1_cUnit,dsize);
3003 SIVAL(pdata,l1_cUnitAvail,dfree);
3004 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3005 break;
3008 case SMB_INFO_VOLUME:
3009 /* Return volume name */
3011 * Add volume serial number - hash of a combination of
3012 * the called hostname and the service name.
3014 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3016 * Win2k3 and previous mess this up by sending a name length
3017 * one byte short. I believe only older clients (OS/2 Win9x) use
3018 * this call so try fixing this by adding a terminating null to
3019 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3021 len = srvstr_push(
3022 pdata, flags2,
3023 pdata+l2_vol_szVolLabel, vname,
3024 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3025 STR_NOALIGN|STR_TERMINATE);
3026 SCVAL(pdata,l2_vol_cch,len);
3027 data_len = l2_vol_szVolLabel + len;
3028 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3029 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3030 len, vname));
3031 break;
3033 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3034 case SMB_FS_ATTRIBUTE_INFORMATION:
3036 additional_flags = 0;
3037 #if defined(HAVE_SYS_QUOTAS)
3038 additional_flags |= FILE_VOLUME_QUOTAS;
3039 #endif
3041 if(lp_nt_acl_support(SNUM(conn))) {
3042 additional_flags |= FILE_PERSISTENT_ACLS;
3045 /* Capabilities are filled in at connection time through STATVFS call */
3046 additional_flags |= conn->fs_capabilities;
3047 additional_flags |= lp_parm_int(conn->params->service,
3048 "share", "fake_fscaps",
3051 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3052 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3053 additional_flags); /* FS ATTRIBUTES */
3055 SIVAL(pdata,4,255); /* Max filename component length */
3056 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3057 and will think we can't do long filenames */
3058 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3059 PTR_DIFF(end_data, pdata+12),
3060 STR_UNICODE);
3061 SIVAL(pdata,8,len);
3062 data_len = 12 + len;
3063 break;
3065 case SMB_QUERY_FS_LABEL_INFO:
3066 case SMB_FS_LABEL_INFORMATION:
3067 len = srvstr_push(pdata, flags2, pdata+4, vname,
3068 PTR_DIFF(end_data, pdata+4), 0);
3069 data_len = 4 + len;
3070 SIVAL(pdata,0,len);
3071 break;
3073 case SMB_QUERY_FS_VOLUME_INFO:
3074 case SMB_FS_VOLUME_INFORMATION:
3077 * Add volume serial number - hash of a combination of
3078 * the called hostname and the service name.
3080 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3081 (str_checksum(get_local_machine_name())<<16));
3083 /* Max label len is 32 characters. */
3084 len = srvstr_push(pdata, flags2, pdata+18, vname,
3085 PTR_DIFF(end_data, pdata+18),
3086 STR_UNICODE);
3087 SIVAL(pdata,12,len);
3088 data_len = 18+len;
3090 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3091 (int)strlen(vname),vname, lp_servicename(snum)));
3092 break;
3094 case SMB_QUERY_FS_SIZE_INFO:
3095 case SMB_FS_SIZE_INFORMATION:
3097 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3098 data_len = 24;
3099 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3100 return map_nt_error_from_unix(errno);
3102 block_size = lp_block_size(snum);
3103 if (bsize < block_size) {
3104 uint64_t factor = block_size/bsize;
3105 bsize = block_size;
3106 dsize /= factor;
3107 dfree /= factor;
3109 if (bsize > block_size) {
3110 uint64_t factor = bsize/block_size;
3111 bsize = block_size;
3112 dsize *= factor;
3113 dfree *= factor;
3115 bytes_per_sector = 512;
3116 sectors_per_unit = bsize/bytes_per_sector;
3117 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3118 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3119 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3120 SBIG_UINT(pdata,0,dsize);
3121 SBIG_UINT(pdata,8,dfree);
3122 SIVAL(pdata,16,sectors_per_unit);
3123 SIVAL(pdata,20,bytes_per_sector);
3124 break;
3127 case SMB_FS_FULL_SIZE_INFORMATION:
3129 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3130 data_len = 32;
3131 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3132 return map_nt_error_from_unix(errno);
3134 block_size = lp_block_size(snum);
3135 if (bsize < block_size) {
3136 uint64_t factor = block_size/bsize;
3137 bsize = block_size;
3138 dsize /= factor;
3139 dfree /= factor;
3141 if (bsize > block_size) {
3142 uint64_t factor = bsize/block_size;
3143 bsize = block_size;
3144 dsize *= factor;
3145 dfree *= factor;
3147 bytes_per_sector = 512;
3148 sectors_per_unit = bsize/bytes_per_sector;
3149 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3150 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3151 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3152 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3153 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3154 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3155 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3156 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3157 break;
3160 case SMB_QUERY_FS_DEVICE_INFO:
3161 case SMB_FS_DEVICE_INFORMATION:
3163 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3165 if (!CAN_WRITE(conn)) {
3166 characteristics |= FILE_READ_ONLY_DEVICE;
3168 data_len = 8;
3169 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3170 SIVAL(pdata,4,characteristics);
3171 break;
3174 #ifdef HAVE_SYS_QUOTAS
3175 case SMB_FS_QUOTA_INFORMATION:
3177 * what we have to send --metze:
3179 * Unknown1: 24 NULL bytes
3180 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3181 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3182 * Quota Flags: 2 byte :
3183 * Unknown3: 6 NULL bytes
3185 * 48 bytes total
3187 * details for Quota Flags:
3189 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3190 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3191 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3192 * 0x0001 Enable Quotas: enable quota for this fs
3196 /* we need to fake up a fsp here,
3197 * because its not send in this call
3199 files_struct fsp;
3200 SMB_NTQUOTA_STRUCT quotas;
3202 ZERO_STRUCT(fsp);
3203 ZERO_STRUCT(quotas);
3205 fsp.conn = conn;
3206 fsp.fnum = -1;
3208 /* access check */
3209 if (get_current_uid(conn) != 0) {
3210 DEBUG(0,("set_user_quota: access_denied "
3211 "service [%s] user [%s]\n",
3212 lp_servicename(SNUM(conn)),
3213 conn->session_info->unix_name));
3214 return NT_STATUS_ACCESS_DENIED;
3217 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3218 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3219 return map_nt_error_from_unix(errno);
3222 data_len = 48;
3224 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3225 lp_servicename(SNUM(conn))));
3227 /* Unknown1 24 NULL bytes*/
3228 SBIG_UINT(pdata,0,(uint64_t)0);
3229 SBIG_UINT(pdata,8,(uint64_t)0);
3230 SBIG_UINT(pdata,16,(uint64_t)0);
3232 /* Default Soft Quota 8 bytes */
3233 SBIG_UINT(pdata,24,quotas.softlim);
3235 /* Default Hard Quota 8 bytes */
3236 SBIG_UINT(pdata,32,quotas.hardlim);
3238 /* Quota flag 2 bytes */
3239 SSVAL(pdata,40,quotas.qflags);
3241 /* Unknown3 6 NULL bytes */
3242 SSVAL(pdata,42,0);
3243 SIVAL(pdata,44,0);
3245 break;
3247 #endif /* HAVE_SYS_QUOTAS */
3248 case SMB_FS_OBJECTID_INFORMATION:
3250 unsigned char objid[16];
3251 struct smb_extended_info extended_info;
3252 memcpy(pdata,create_volume_objectid(conn, objid),16);
3253 samba_extended_info_version (&extended_info);
3254 SIVAL(pdata,16,extended_info.samba_magic);
3255 SIVAL(pdata,20,extended_info.samba_version);
3256 SIVAL(pdata,24,extended_info.samba_subversion);
3257 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3258 memcpy(pdata+36,extended_info.samba_version_string,28);
3259 data_len = 64;
3260 break;
3264 * Query the version and capabilities of the CIFS UNIX extensions
3265 * in use.
3268 case SMB_QUERY_CIFS_UNIX_INFO:
3270 bool large_write = lp_min_receive_file_size() &&
3271 !srv_is_signing_active(conn->sconn);
3272 bool large_read = !srv_is_signing_active(conn->sconn);
3273 int encrypt_caps = 0;
3275 if (!lp_unix_extensions()) {
3276 return NT_STATUS_INVALID_LEVEL;
3279 switch (conn->encrypt_level) {
3280 case 0:
3281 encrypt_caps = 0;
3282 break;
3283 case 1:
3284 case Auto:
3285 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3286 break;
3287 case Required:
3288 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3289 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3290 large_write = false;
3291 large_read = false;
3292 break;
3295 data_len = 12;
3296 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3297 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3299 /* We have POSIX ACLs, pathname, encryption,
3300 * large read/write, and locking capability. */
3302 SBIG_UINT(pdata,4,((uint64_t)(
3303 CIFS_UNIX_POSIX_ACLS_CAP|
3304 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3305 CIFS_UNIX_FCNTL_LOCKS_CAP|
3306 CIFS_UNIX_EXTATTR_CAP|
3307 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3308 encrypt_caps|
3309 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3310 (large_write ?
3311 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3312 break;
3315 case SMB_QUERY_POSIX_FS_INFO:
3317 int rc;
3318 vfs_statvfs_struct svfs;
3320 if (!lp_unix_extensions()) {
3321 return NT_STATUS_INVALID_LEVEL;
3324 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3326 if (!rc) {
3327 data_len = 56;
3328 SIVAL(pdata,0,svfs.OptimalTransferSize);
3329 SIVAL(pdata,4,svfs.BlockSize);
3330 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3331 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3332 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3333 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3334 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3335 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3336 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3337 #ifdef EOPNOTSUPP
3338 } else if (rc == EOPNOTSUPP) {
3339 return NT_STATUS_INVALID_LEVEL;
3340 #endif /* EOPNOTSUPP */
3341 } else {
3342 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3343 return NT_STATUS_DOS(ERRSRV, ERRerror);
3345 break;
3348 case SMB_QUERY_POSIX_WHOAMI:
3350 uint32_t flags = 0;
3351 uint32_t sid_bytes;
3352 int i;
3354 if (!lp_unix_extensions()) {
3355 return NT_STATUS_INVALID_LEVEL;
3358 if (max_data_bytes < 40) {
3359 return NT_STATUS_BUFFER_TOO_SMALL;
3362 /* We ARE guest if global_sid_Builtin_Guests is
3363 * in our list of SIDs.
3365 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3366 conn->session_info->security_token)) {
3367 flags |= SMB_WHOAMI_GUEST;
3370 /* We are NOT guest if global_sid_Authenticated_Users
3371 * is in our list of SIDs.
3373 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3374 conn->session_info->security_token)) {
3375 flags &= ~SMB_WHOAMI_GUEST;
3378 /* NOTE: 8 bytes for UID/GID, irrespective of native
3379 * platform size. This matches
3380 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3382 data_len = 4 /* flags */
3383 + 4 /* flag mask */
3384 + 8 /* uid */
3385 + 8 /* gid */
3386 + 4 /* ngroups */
3387 + 4 /* num_sids */
3388 + 4 /* SID bytes */
3389 + 4 /* pad/reserved */
3390 + (conn->session_info->utok.ngroups * 8)
3391 /* groups list */
3392 + (conn->session_info->security_token->num_sids *
3393 SID_MAX_SIZE)
3394 /* SID list */;
3396 SIVAL(pdata, 0, flags);
3397 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3398 SBIG_UINT(pdata, 8,
3399 (uint64_t)conn->session_info->utok.uid);
3400 SBIG_UINT(pdata, 16,
3401 (uint64_t)conn->session_info->utok.gid);
3404 if (data_len >= max_data_bytes) {
3405 /* Potential overflow, skip the GIDs and SIDs. */
3407 SIVAL(pdata, 24, 0); /* num_groups */
3408 SIVAL(pdata, 28, 0); /* num_sids */
3409 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3410 SIVAL(pdata, 36, 0); /* reserved */
3412 data_len = 40;
3413 break;
3416 SIVAL(pdata, 24, conn->session_info->utok.ngroups);
3417 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3419 /* We walk the SID list twice, but this call is fairly
3420 * infrequent, and I don't expect that it's performance
3421 * sensitive -- jpeach
3423 for (i = 0, sid_bytes = 0;
3424 i < conn->session_info->security_token->num_sids; ++i) {
3425 sid_bytes += ndr_size_dom_sid(
3426 &conn->session_info->security_token->sids[i],
3430 /* SID list byte count */
3431 SIVAL(pdata, 32, sid_bytes);
3433 /* 4 bytes pad/reserved - must be zero */
3434 SIVAL(pdata, 36, 0);
3435 data_len = 40;
3437 /* GID list */
3438 for (i = 0; i < conn->session_info->utok.ngroups; ++i) {
3439 SBIG_UINT(pdata, data_len,
3440 (uint64_t)conn->session_info->utok.groups[i]);
3441 data_len += 8;
3444 /* SID list */
3445 for (i = 0;
3446 i < conn->session_info->security_token->num_sids; ++i) {
3447 int sid_len = ndr_size_dom_sid(
3448 &conn->session_info->security_token->sids[i],
3451 sid_linearize(pdata + data_len, sid_len,
3452 &conn->session_info->security_token->sids[i]);
3453 data_len += sid_len;
3456 break;
3459 case SMB_MAC_QUERY_FS_INFO:
3461 * Thursby MAC extension... ONLY on NTFS filesystems
3462 * once we do streams then we don't need this
3464 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3465 data_len = 88;
3466 SIVAL(pdata,84,0x100); /* Don't support mac... */
3467 break;
3469 /* drop through */
3470 default:
3471 return NT_STATUS_INVALID_LEVEL;
3474 *ret_data_len = data_len;
3475 return NT_STATUS_OK;
3478 /****************************************************************************
3479 Reply to a TRANS2_QFSINFO (query filesystem info).
3480 ****************************************************************************/
3482 static void call_trans2qfsinfo(connection_struct *conn,
3483 struct smb_request *req,
3484 char **pparams, int total_params,
3485 char **ppdata, int total_data,
3486 unsigned int max_data_bytes)
3488 char *params = *pparams;
3489 uint16_t info_level;
3490 int data_len = 0;
3491 NTSTATUS status;
3493 if (total_params < 2) {
3494 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3495 return;
3498 info_level = SVAL(params,0);
3500 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3501 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3502 DEBUG(0,("call_trans2qfsinfo: encryption required "
3503 "and info level 0x%x sent.\n",
3504 (unsigned int)info_level));
3505 exit_server_cleanly("encryption required "
3506 "on connection");
3507 return;
3511 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3513 status = smbd_do_qfsinfo(conn, req,
3514 info_level,
3515 req->flags2,
3516 max_data_bytes,
3517 ppdata, &data_len);
3518 if (!NT_STATUS_IS_OK(status)) {
3519 reply_nterror(req, status);
3520 return;
3523 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3524 max_data_bytes);
3526 DEBUG( 4, ( "%s info_level = %d\n",
3527 smb_fn_name(req->cmd), info_level) );
3529 return;
3532 /****************************************************************************
3533 Reply to a TRANS2_SETFSINFO (set filesystem info).
3534 ****************************************************************************/
3536 static void call_trans2setfsinfo(connection_struct *conn,
3537 struct smb_request *req,
3538 char **pparams, int total_params,
3539 char **ppdata, int total_data,
3540 unsigned int max_data_bytes)
3542 char *pdata = *ppdata;
3543 char *params = *pparams;
3544 uint16 info_level;
3546 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3548 /* */
3549 if (total_params < 4) {
3550 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3551 total_params));
3552 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3553 return;
3556 info_level = SVAL(params,2);
3558 if (IS_IPC(conn)) {
3559 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3560 info_level != SMB_SET_CIFS_UNIX_INFO) {
3561 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3562 "info level (0x%x) on IPC$.\n",
3563 (unsigned int)info_level));
3564 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3565 return;
3569 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3570 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3571 DEBUG(0,("call_trans2setfsinfo: encryption required "
3572 "and info level 0x%x sent.\n",
3573 (unsigned int)info_level));
3574 exit_server_cleanly("encryption required "
3575 "on connection");
3576 return;
3580 switch(info_level) {
3581 case SMB_SET_CIFS_UNIX_INFO:
3583 uint16 client_unix_major;
3584 uint16 client_unix_minor;
3585 uint32 client_unix_cap_low;
3586 uint32 client_unix_cap_high;
3588 if (!lp_unix_extensions()) {
3589 reply_nterror(req,
3590 NT_STATUS_INVALID_LEVEL);
3591 return;
3594 /* There should be 12 bytes of capabilities set. */
3595 if (total_data < 8) {
3596 reply_nterror(
3597 req,
3598 NT_STATUS_INVALID_PARAMETER);
3599 return;
3601 client_unix_major = SVAL(pdata,0);
3602 client_unix_minor = SVAL(pdata,2);
3603 client_unix_cap_low = IVAL(pdata,4);
3604 client_unix_cap_high = IVAL(pdata,8);
3605 /* Just print these values for now. */
3606 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3607 cap_low = 0x%x, cap_high = 0x%x\n",
3608 (unsigned int)client_unix_major,
3609 (unsigned int)client_unix_minor,
3610 (unsigned int)client_unix_cap_low,
3611 (unsigned int)client_unix_cap_high ));
3613 /* Here is where we must switch to posix pathname processing... */
3614 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3615 lp_set_posix_pathnames();
3616 mangle_change_to_posix();
3619 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3620 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3621 /* Client that knows how to do posix locks,
3622 * but not posix open/mkdir operations. Set a
3623 * default type for read/write checks. */
3625 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3628 break;
3631 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3633 NTSTATUS status;
3634 size_t param_len = 0;
3635 size_t data_len = total_data;
3637 if (!lp_unix_extensions()) {
3638 reply_nterror(
3639 req,
3640 NT_STATUS_INVALID_LEVEL);
3641 return;
3644 if (lp_smb_encrypt(SNUM(conn)) == false) {
3645 reply_nterror(
3646 req,
3647 NT_STATUS_NOT_SUPPORTED);
3648 return;
3651 if (req->sconn->smb1.echo_handler.trusted_fde) {
3652 DEBUG( 2,("call_trans2setfsinfo: "
3653 "request transport encryption disabled"
3654 "with 'fork echo handler = yes'\n"));
3655 reply_nterror(
3656 req,
3657 NT_STATUS_NOT_SUPPORTED);
3658 return;
3661 DEBUG( 4,("call_trans2setfsinfo: "
3662 "request transport encryption.\n"));
3664 status = srv_request_encryption_setup(conn,
3665 (unsigned char **)ppdata,
3666 &data_len,
3667 (unsigned char **)pparams,
3668 &param_len);
3670 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3671 !NT_STATUS_IS_OK(status)) {
3672 reply_nterror(req, status);
3673 return;
3676 send_trans2_replies(conn, req,
3677 *pparams,
3678 param_len,
3679 *ppdata,
3680 data_len,
3681 max_data_bytes);
3683 if (NT_STATUS_IS_OK(status)) {
3684 /* Server-side transport
3685 * encryption is now *on*. */
3686 status = srv_encryption_start(conn);
3687 if (!NT_STATUS_IS_OK(status)) {
3688 exit_server_cleanly(
3689 "Failure in setting "
3690 "up encrypted transport");
3693 return;
3696 case SMB_FS_QUOTA_INFORMATION:
3698 files_struct *fsp = NULL;
3699 SMB_NTQUOTA_STRUCT quotas;
3701 ZERO_STRUCT(quotas);
3703 /* access check */
3704 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3705 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3706 lp_servicename(SNUM(conn)),
3707 conn->session_info->unix_name));
3708 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3709 return;
3712 /* note: normaly there're 48 bytes,
3713 * but we didn't use the last 6 bytes for now
3714 * --metze
3716 fsp = file_fsp(req, SVAL(params,0));
3718 if (!check_fsp_ntquota_handle(conn, req,
3719 fsp)) {
3720 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3721 reply_nterror(
3722 req, NT_STATUS_INVALID_HANDLE);
3723 return;
3726 if (total_data < 42) {
3727 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3728 total_data));
3729 reply_nterror(
3730 req,
3731 NT_STATUS_INVALID_PARAMETER);
3732 return;
3735 /* unknown_1 24 NULL bytes in pdata*/
3737 /* the soft quotas 8 bytes (uint64_t)*/
3738 quotas.softlim = BVAL(pdata,24);
3740 /* the hard quotas 8 bytes (uint64_t)*/
3741 quotas.hardlim = BVAL(pdata,32);
3743 /* quota_flags 2 bytes **/
3744 quotas.qflags = SVAL(pdata,40);
3746 /* unknown_2 6 NULL bytes follow*/
3748 /* now set the quotas */
3749 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3750 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3751 reply_nterror(req, map_nt_error_from_unix(errno));
3752 return;
3755 break;
3757 default:
3758 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3759 info_level));
3760 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3761 return;
3762 break;
3766 * sending this reply works fine,
3767 * but I'm not sure it's the same
3768 * like windows do...
3769 * --metze
3771 reply_outbuf(req, 10, 0);
3774 #if defined(HAVE_POSIX_ACLS)
3775 /****************************************************************************
3776 Utility function to count the number of entries in a POSIX acl.
3777 ****************************************************************************/
3779 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3781 unsigned int ace_count = 0;
3782 int entry_id = SMB_ACL_FIRST_ENTRY;
3783 SMB_ACL_ENTRY_T entry;
3785 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3786 /* get_next... */
3787 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3788 entry_id = SMB_ACL_NEXT_ENTRY;
3790 ace_count++;
3792 return ace_count;
3795 /****************************************************************************
3796 Utility function to marshall a POSIX acl into wire format.
3797 ****************************************************************************/
3799 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3801 int entry_id = SMB_ACL_FIRST_ENTRY;
3802 SMB_ACL_ENTRY_T entry;
3804 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3805 SMB_ACL_TAG_T tagtype;
3806 SMB_ACL_PERMSET_T permset;
3807 unsigned char perms = 0;
3808 unsigned int own_grp;
3810 /* get_next... */
3811 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3812 entry_id = SMB_ACL_NEXT_ENTRY;
3815 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3816 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3817 return False;
3820 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3821 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3822 return False;
3825 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3826 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3827 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3829 SCVAL(pdata,1,perms);
3831 switch (tagtype) {
3832 case SMB_ACL_USER_OBJ:
3833 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3834 own_grp = (unsigned int)pst->st_ex_uid;
3835 SIVAL(pdata,2,own_grp);
3836 SIVAL(pdata,6,0);
3837 break;
3838 case SMB_ACL_USER:
3840 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3841 if (!puid) {
3842 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3843 return False;
3845 own_grp = (unsigned int)*puid;
3846 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3847 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3848 SIVAL(pdata,2,own_grp);
3849 SIVAL(pdata,6,0);
3850 break;
3852 case SMB_ACL_GROUP_OBJ:
3853 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3854 own_grp = (unsigned int)pst->st_ex_gid;
3855 SIVAL(pdata,2,own_grp);
3856 SIVAL(pdata,6,0);
3857 break;
3858 case SMB_ACL_GROUP:
3860 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3861 if (!pgid) {
3862 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3863 return False;
3865 own_grp = (unsigned int)*pgid;
3866 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3867 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3868 SIVAL(pdata,2,own_grp);
3869 SIVAL(pdata,6,0);
3870 break;
3872 case SMB_ACL_MASK:
3873 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3874 SIVAL(pdata,2,0xFFFFFFFF);
3875 SIVAL(pdata,6,0xFFFFFFFF);
3876 break;
3877 case SMB_ACL_OTHER:
3878 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3879 SIVAL(pdata,2,0xFFFFFFFF);
3880 SIVAL(pdata,6,0xFFFFFFFF);
3881 break;
3882 default:
3883 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3884 return False;
3886 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3889 return True;
3891 #endif
3893 /****************************************************************************
3894 Store the FILE_UNIX_BASIC info.
3895 ****************************************************************************/
3897 static char *store_file_unix_basic(connection_struct *conn,
3898 char *pdata,
3899 files_struct *fsp,
3900 const SMB_STRUCT_STAT *psbuf)
3902 uint64_t file_index = get_FileIndex(conn, psbuf);
3904 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3905 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3907 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3908 pdata += 8;
3910 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3911 pdata += 8;
3913 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3914 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3915 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3916 pdata += 24;
3918 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3919 SIVAL(pdata,4,0);
3920 pdata += 8;
3922 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3923 SIVAL(pdata,4,0);
3924 pdata += 8;
3926 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3927 pdata += 4;
3929 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3930 SIVAL(pdata,4,0);
3931 pdata += 8;
3933 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3934 SIVAL(pdata,4,0);
3935 pdata += 8;
3937 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3938 pdata += 8;
3940 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3941 SIVAL(pdata,4,0);
3942 pdata += 8;
3944 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3945 SIVAL(pdata,4,0);
3946 pdata += 8;
3948 return pdata;
3951 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3952 * the chflags(2) (or equivalent) flags.
3954 * XXX: this really should be behind the VFS interface. To do this, we would
3955 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3956 * Each VFS module could then implement its own mapping as appropriate for the
3957 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3959 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3960 info2_flags_map[] =
3962 #ifdef UF_NODUMP
3963 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3964 #endif
3966 #ifdef UF_IMMUTABLE
3967 { UF_IMMUTABLE, EXT_IMMUTABLE },
3968 #endif
3970 #ifdef UF_APPEND
3971 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3972 #endif
3974 #ifdef UF_HIDDEN
3975 { UF_HIDDEN, EXT_HIDDEN },
3976 #endif
3978 /* Do not remove. We need to guarantee that this array has at least one
3979 * entry to build on HP-UX.
3981 { 0, 0 }
3985 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3986 uint32 *smb_fflags, uint32 *smb_fmask)
3988 int i;
3990 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3991 *smb_fmask |= info2_flags_map[i].smb_fflag;
3992 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3993 *smb_fflags |= info2_flags_map[i].smb_fflag;
3998 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3999 const uint32 smb_fflags,
4000 const uint32 smb_fmask,
4001 int *stat_fflags)
4003 uint32 max_fmask = 0;
4004 int i;
4006 *stat_fflags = psbuf->st_ex_flags;
4008 /* For each flags requested in smb_fmask, check the state of the
4009 * corresponding flag in smb_fflags and set or clear the matching
4010 * stat flag.
4013 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4014 max_fmask |= info2_flags_map[i].smb_fflag;
4015 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4016 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4017 *stat_fflags |= info2_flags_map[i].stat_fflag;
4018 } else {
4019 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4024 /* If smb_fmask is asking to set any bits that are not supported by
4025 * our flag mappings, we should fail.
4027 if ((smb_fmask & max_fmask) != smb_fmask) {
4028 return False;
4031 return True;
4035 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4036 * of file flags and birth (create) time.
4038 static char *store_file_unix_basic_info2(connection_struct *conn,
4039 char *pdata,
4040 files_struct *fsp,
4041 const SMB_STRUCT_STAT *psbuf)
4043 uint32 file_flags = 0;
4044 uint32 flags_mask = 0;
4046 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4048 /* Create (birth) time 64 bit */
4049 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4050 pdata += 8;
4052 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4053 SIVAL(pdata, 0, file_flags); /* flags */
4054 SIVAL(pdata, 4, flags_mask); /* mask */
4055 pdata += 8;
4057 return pdata;
4060 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4061 const struct stream_struct *streams,
4062 char *data,
4063 unsigned int max_data_bytes,
4064 unsigned int *data_size)
4066 unsigned int i;
4067 unsigned int ofs = 0;
4069 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4070 unsigned int next_offset;
4071 size_t namelen;
4072 smb_ucs2_t *namebuf;
4074 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4075 streams[i].name, &namelen) ||
4076 namelen <= 2)
4078 return NT_STATUS_INVALID_PARAMETER;
4082 * name_buf is now null-terminated, we need to marshall as not
4083 * terminated
4086 namelen -= 2;
4088 SIVAL(data, ofs+4, namelen);
4089 SOFF_T(data, ofs+8, streams[i].size);
4090 SOFF_T(data, ofs+16, streams[i].alloc_size);
4091 memcpy(data+ofs+24, namebuf, namelen);
4092 TALLOC_FREE(namebuf);
4094 next_offset = ofs + 24 + namelen;
4096 if (i == num_streams-1) {
4097 SIVAL(data, ofs, 0);
4099 else {
4100 unsigned int align = ndr_align_size(next_offset, 8);
4102 memset(data+next_offset, 0, align);
4103 next_offset += align;
4105 SIVAL(data, ofs, next_offset - ofs);
4106 ofs = next_offset;
4109 ofs = next_offset;
4112 *data_size = ofs;
4114 return NT_STATUS_OK;
4117 /****************************************************************************
4118 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4119 ****************************************************************************/
4121 static void call_trans2qpipeinfo(connection_struct *conn,
4122 struct smb_request *req,
4123 unsigned int tran_call,
4124 char **pparams, int total_params,
4125 char **ppdata, int total_data,
4126 unsigned int max_data_bytes)
4128 char *params = *pparams;
4129 char *pdata = *ppdata;
4130 unsigned int data_size = 0;
4131 unsigned int param_size = 2;
4132 uint16 info_level;
4133 files_struct *fsp;
4135 if (!params) {
4136 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4137 return;
4140 if (total_params < 4) {
4141 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4142 return;
4145 fsp = file_fsp(req, SVAL(params,0));
4146 if (!fsp_is_np(fsp)) {
4147 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4148 return;
4151 info_level = SVAL(params,2);
4153 *pparams = (char *)SMB_REALLOC(*pparams,2);
4154 if (*pparams == NULL) {
4155 reply_nterror(req, NT_STATUS_NO_MEMORY);
4156 return;
4158 params = *pparams;
4159 SSVAL(params,0,0);
4160 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4161 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4162 if (*ppdata == NULL ) {
4163 reply_nterror(req, NT_STATUS_NO_MEMORY);
4164 return;
4166 pdata = *ppdata;
4168 switch (info_level) {
4169 case SMB_FILE_STANDARD_INFORMATION:
4170 memset(pdata,0,24);
4171 SOFF_T(pdata,0,4096LL);
4172 SIVAL(pdata,16,1);
4173 SIVAL(pdata,20,1);
4174 data_size = 24;
4175 break;
4177 default:
4178 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4179 return;
4182 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4183 max_data_bytes);
4185 return;
4188 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4189 TALLOC_CTX *mem_ctx,
4190 uint16_t info_level,
4191 files_struct *fsp,
4192 struct smb_filename *smb_fname,
4193 bool delete_pending,
4194 struct timespec write_time_ts,
4195 struct ea_list *ea_list,
4196 int lock_data_count,
4197 char *lock_data,
4198 uint16_t flags2,
4199 unsigned int max_data_bytes,
4200 char **ppdata,
4201 unsigned int *pdata_size)
4203 char *pdata = *ppdata;
4204 char *dstart, *dend;
4205 unsigned int data_size;
4206 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4207 time_t create_time, mtime, atime, c_time;
4208 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4209 char *p;
4210 char *base_name;
4211 char *dos_fname;
4212 int mode;
4213 int nlink;
4214 NTSTATUS status;
4215 uint64_t file_size = 0;
4216 uint64_t pos = 0;
4217 uint64_t allocation_size = 0;
4218 uint64_t file_index = 0;
4219 uint32_t access_mask = 0;
4221 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4222 return NT_STATUS_INVALID_LEVEL;
4225 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4226 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4227 info_level, max_data_bytes));
4229 mode = dos_mode(conn, smb_fname);
4230 nlink = psbuf->st_ex_nlink;
4232 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4233 nlink = 1;
4236 if ((nlink > 0) && delete_pending) {
4237 nlink -= 1;
4240 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4241 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4242 if (*ppdata == NULL) {
4243 return NT_STATUS_NO_MEMORY;
4245 pdata = *ppdata;
4246 dstart = pdata;
4247 dend = dstart + data_size - 1;
4249 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4250 update_stat_ex_mtime(psbuf, write_time_ts);
4253 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4254 mtime_ts = psbuf->st_ex_mtime;
4255 atime_ts = psbuf->st_ex_atime;
4256 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4258 if (lp_dos_filetime_resolution(SNUM(conn))) {
4259 dos_filetime_timespec(&create_time_ts);
4260 dos_filetime_timespec(&mtime_ts);
4261 dos_filetime_timespec(&atime_ts);
4262 dos_filetime_timespec(&ctime_ts);
4265 create_time = convert_timespec_to_time_t(create_time_ts);
4266 mtime = convert_timespec_to_time_t(mtime_ts);
4267 atime = convert_timespec_to_time_t(atime_ts);
4268 c_time = convert_timespec_to_time_t(ctime_ts);
4270 p = strrchr_m(smb_fname->base_name,'/');
4271 if (!p)
4272 base_name = smb_fname->base_name;
4273 else
4274 base_name = p+1;
4276 /* NT expects the name to be in an exact form of the *full*
4277 filename. See the trans2 torture test */
4278 if (ISDOT(base_name)) {
4279 dos_fname = talloc_strdup(mem_ctx, "\\");
4280 if (!dos_fname) {
4281 return NT_STATUS_NO_MEMORY;
4283 } else {
4284 dos_fname = talloc_asprintf(mem_ctx,
4285 "\\%s",
4286 smb_fname->base_name);
4287 if (!dos_fname) {
4288 return NT_STATUS_NO_MEMORY;
4290 if (is_ntfs_stream_smb_fname(smb_fname)) {
4291 dos_fname = talloc_asprintf(dos_fname, "%s",
4292 smb_fname->stream_name);
4293 if (!dos_fname) {
4294 return NT_STATUS_NO_MEMORY;
4298 string_replace(dos_fname, '/', '\\');
4301 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4303 if (!fsp) {
4304 /* Do we have this path open ? */
4305 files_struct *fsp1;
4306 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4307 fsp1 = file_find_di_first(conn->sconn, fileid);
4308 if (fsp1 && fsp1->initial_allocation_size) {
4309 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4313 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4314 file_size = get_file_size_stat(psbuf);
4317 if (fsp) {
4318 pos = fsp->fh->position_information;
4321 if (fsp) {
4322 access_mask = fsp->access_mask;
4323 } else {
4324 /* GENERIC_EXECUTE mapping from Windows */
4325 access_mask = 0x12019F;
4328 /* This should be an index number - looks like
4329 dev/ino to me :-)
4331 I think this causes us to fail the IFSKIT
4332 BasicFileInformationTest. -tpot */
4333 file_index = get_FileIndex(conn, psbuf);
4335 switch (info_level) {
4336 case SMB_INFO_STANDARD:
4337 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4338 data_size = 22;
4339 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4340 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4341 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4342 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4343 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4344 SSVAL(pdata,l1_attrFile,mode);
4345 break;
4347 case SMB_INFO_QUERY_EA_SIZE:
4349 unsigned int ea_size =
4350 estimate_ea_size(conn, fsp,
4351 smb_fname->base_name);
4352 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4353 data_size = 26;
4354 srv_put_dos_date2(pdata,0,create_time);
4355 srv_put_dos_date2(pdata,4,atime);
4356 srv_put_dos_date2(pdata,8,mtime); /* write time */
4357 SIVAL(pdata,12,(uint32)file_size);
4358 SIVAL(pdata,16,(uint32)allocation_size);
4359 SSVAL(pdata,20,mode);
4360 SIVAL(pdata,22,ea_size);
4361 break;
4364 case SMB_INFO_IS_NAME_VALID:
4365 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4366 if (fsp) {
4367 /* os/2 needs this ? really ?*/
4368 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4370 /* This is only reached for qpathinfo */
4371 data_size = 0;
4372 break;
4374 case SMB_INFO_QUERY_EAS_FROM_LIST:
4376 size_t total_ea_len = 0;
4377 struct ea_list *ea_file_list = NULL;
4379 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4381 ea_file_list =
4382 get_ea_list_from_file(mem_ctx, conn, fsp,
4383 smb_fname->base_name,
4384 &total_ea_len);
4385 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4387 if (!ea_list || (total_ea_len > data_size)) {
4388 data_size = 4;
4389 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4390 break;
4393 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4394 break;
4397 case SMB_INFO_QUERY_ALL_EAS:
4399 /* We have data_size bytes to put EA's into. */
4400 size_t total_ea_len = 0;
4402 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4404 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4405 smb_fname->base_name,
4406 &total_ea_len);
4407 if (!ea_list || (total_ea_len > data_size)) {
4408 data_size = 4;
4409 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4410 break;
4413 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4414 break;
4417 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4419 /* This is FileFullEaInformation - 0xF which maps to
4420 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4422 /* We have data_size bytes to put EA's into. */
4423 size_t total_ea_len = 0;
4424 struct ea_list *ea_file_list = NULL;
4426 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4428 /*TODO: add filtering and index handling */
4430 ea_file_list =
4431 get_ea_list_from_file(mem_ctx, conn, fsp,
4432 smb_fname->base_name,
4433 &total_ea_len);
4434 if (!ea_file_list) {
4435 return NT_STATUS_NO_EAS_ON_FILE;
4438 status = fill_ea_chained_buffer(mem_ctx,
4439 pdata,
4440 data_size,
4441 &data_size,
4442 conn, ea_file_list);
4443 if (!NT_STATUS_IS_OK(status)) {
4444 return status;
4446 break;
4449 case SMB_FILE_BASIC_INFORMATION:
4450 case SMB_QUERY_FILE_BASIC_INFO:
4452 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4453 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4454 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4455 } else {
4456 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4457 data_size = 40;
4458 SIVAL(pdata,36,0);
4460 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4461 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4462 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4463 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4464 SIVAL(pdata,32,mode);
4466 DEBUG(5,("SMB_QFBI - "));
4467 DEBUG(5,("create: %s ", ctime(&create_time)));
4468 DEBUG(5,("access: %s ", ctime(&atime)));
4469 DEBUG(5,("write: %s ", ctime(&mtime)));
4470 DEBUG(5,("change: %s ", ctime(&c_time)));
4471 DEBUG(5,("mode: %x\n", mode));
4472 break;
4474 case SMB_FILE_STANDARD_INFORMATION:
4475 case SMB_QUERY_FILE_STANDARD_INFO:
4477 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4478 data_size = 24;
4479 SOFF_T(pdata,0,allocation_size);
4480 SOFF_T(pdata,8,file_size);
4481 SIVAL(pdata,16,nlink);
4482 SCVAL(pdata,20,delete_pending?1:0);
4483 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4484 SSVAL(pdata,22,0); /* Padding. */
4485 break;
4487 case SMB_FILE_EA_INFORMATION:
4488 case SMB_QUERY_FILE_EA_INFO:
4490 unsigned int ea_size =
4491 estimate_ea_size(conn, fsp, smb_fname->base_name);
4492 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4493 data_size = 4;
4494 SIVAL(pdata,0,ea_size);
4495 break;
4498 /* Get the 8.3 name - used if NT SMB was negotiated. */
4499 case SMB_QUERY_FILE_ALT_NAME_INFO:
4500 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4502 int len;
4503 char mangled_name[13];
4504 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4505 if (!name_to_8_3(base_name,mangled_name,
4506 True,conn->params)) {
4507 return NT_STATUS_NO_MEMORY;
4509 len = srvstr_push(dstart, flags2,
4510 pdata+4, mangled_name,
4511 PTR_DIFF(dend, pdata+4),
4512 STR_UNICODE);
4513 data_size = 4 + len;
4514 SIVAL(pdata,0,len);
4515 break;
4518 case SMB_QUERY_FILE_NAME_INFO:
4520 int len;
4522 this must be *exactly* right for ACLs on mapped drives to work
4524 len = srvstr_push(dstart, flags2,
4525 pdata+4, dos_fname,
4526 PTR_DIFF(dend, pdata+4),
4527 STR_UNICODE);
4528 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4529 data_size = 4 + len;
4530 SIVAL(pdata,0,len);
4531 break;
4534 case SMB_FILE_ALLOCATION_INFORMATION:
4535 case SMB_QUERY_FILE_ALLOCATION_INFO:
4536 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4537 data_size = 8;
4538 SOFF_T(pdata,0,allocation_size);
4539 break;
4541 case SMB_FILE_END_OF_FILE_INFORMATION:
4542 case SMB_QUERY_FILE_END_OF_FILEINFO:
4543 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4544 data_size = 8;
4545 SOFF_T(pdata,0,file_size);
4546 break;
4548 case SMB_QUERY_FILE_ALL_INFO:
4549 case SMB_FILE_ALL_INFORMATION:
4551 int len;
4552 unsigned int ea_size =
4553 estimate_ea_size(conn, fsp, smb_fname->base_name);
4554 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4555 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4556 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4557 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4558 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4559 SIVAL(pdata,32,mode);
4560 SIVAL(pdata,36,0); /* padding. */
4561 pdata += 40;
4562 SOFF_T(pdata,0,allocation_size);
4563 SOFF_T(pdata,8,file_size);
4564 SIVAL(pdata,16,nlink);
4565 SCVAL(pdata,20,delete_pending);
4566 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4567 SSVAL(pdata,22,0);
4568 pdata += 24;
4569 SIVAL(pdata,0,ea_size);
4570 pdata += 4; /* EA info */
4571 len = srvstr_push(dstart, flags2,
4572 pdata+4, dos_fname,
4573 PTR_DIFF(dend, pdata+4),
4574 STR_UNICODE);
4575 SIVAL(pdata,0,len);
4576 pdata += 4 + len;
4577 data_size = PTR_DIFF(pdata,(*ppdata));
4578 break;
4581 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4583 int len;
4584 unsigned int ea_size =
4585 estimate_ea_size(conn, fsp, smb_fname->base_name);
4586 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4587 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4588 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4589 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4590 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4591 SIVAL(pdata, 0x20, mode);
4592 SIVAL(pdata, 0x24, 0); /* padding. */
4593 SBVAL(pdata, 0x28, allocation_size);
4594 SBVAL(pdata, 0x30, file_size);
4595 SIVAL(pdata, 0x38, nlink);
4596 SCVAL(pdata, 0x3C, delete_pending);
4597 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4598 SSVAL(pdata, 0x3E, 0); /* padding */
4599 SBVAL(pdata, 0x40, file_index);
4600 SIVAL(pdata, 0x48, ea_size);
4601 SIVAL(pdata, 0x4C, access_mask);
4602 SBVAL(pdata, 0x50, pos);
4603 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4604 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4606 pdata += 0x60;
4608 len = srvstr_push(dstart, flags2,
4609 pdata+4, dos_fname,
4610 PTR_DIFF(dend, pdata+4),
4611 STR_UNICODE);
4612 SIVAL(pdata,0,len);
4613 pdata += 4 + len;
4614 data_size = PTR_DIFF(pdata,(*ppdata));
4615 break;
4617 case SMB_FILE_INTERNAL_INFORMATION:
4619 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4620 SBVAL(pdata, 0, file_index);
4621 data_size = 8;
4622 break;
4624 case SMB_FILE_ACCESS_INFORMATION:
4625 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4626 SIVAL(pdata, 0, access_mask);
4627 data_size = 4;
4628 break;
4630 case SMB_FILE_NAME_INFORMATION:
4631 /* Pathname with leading '\'. */
4633 size_t byte_len;
4634 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4635 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4636 SIVAL(pdata,0,byte_len);
4637 data_size = 4 + byte_len;
4638 break;
4641 case SMB_FILE_DISPOSITION_INFORMATION:
4642 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4643 data_size = 1;
4644 SCVAL(pdata,0,delete_pending);
4645 break;
4647 case SMB_FILE_POSITION_INFORMATION:
4648 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4649 data_size = 8;
4650 SOFF_T(pdata,0,pos);
4651 break;
4653 case SMB_FILE_MODE_INFORMATION:
4654 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4655 SIVAL(pdata,0,mode);
4656 data_size = 4;
4657 break;
4659 case SMB_FILE_ALIGNMENT_INFORMATION:
4660 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4661 SIVAL(pdata,0,0); /* No alignment needed. */
4662 data_size = 4;
4663 break;
4666 * NT4 server just returns "invalid query" to this - if we try
4667 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4668 * want this. JRA.
4670 /* The first statement above is false - verified using Thursby
4671 * client against NT4 -- gcolley.
4673 case SMB_QUERY_FILE_STREAM_INFO:
4674 case SMB_FILE_STREAM_INFORMATION: {
4675 unsigned int num_streams;
4676 struct stream_struct *streams;
4678 DEBUG(10,("smbd_do_qfilepathinfo: "
4679 "SMB_FILE_STREAM_INFORMATION\n"));
4681 if (is_ntfs_stream_smb_fname(smb_fname)) {
4682 return NT_STATUS_INVALID_PARAMETER;
4685 status = SMB_VFS_STREAMINFO(
4686 conn, fsp, smb_fname->base_name, talloc_tos(),
4687 &num_streams, &streams);
4689 if (!NT_STATUS_IS_OK(status)) {
4690 DEBUG(10, ("could not get stream info: %s\n",
4691 nt_errstr(status)));
4692 return status;
4695 status = marshall_stream_info(num_streams, streams,
4696 pdata, max_data_bytes,
4697 &data_size);
4699 if (!NT_STATUS_IS_OK(status)) {
4700 DEBUG(10, ("marshall_stream_info failed: %s\n",
4701 nt_errstr(status)));
4702 return status;
4705 TALLOC_FREE(streams);
4707 break;
4709 case SMB_QUERY_COMPRESSION_INFO:
4710 case SMB_FILE_COMPRESSION_INFORMATION:
4711 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4712 SOFF_T(pdata,0,file_size);
4713 SIVAL(pdata,8,0); /* ??? */
4714 SIVAL(pdata,12,0); /* ??? */
4715 data_size = 16;
4716 break;
4718 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4719 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4720 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4721 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4722 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4723 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4724 SOFF_T(pdata,32,allocation_size);
4725 SOFF_T(pdata,40,file_size);
4726 SIVAL(pdata,48,mode);
4727 SIVAL(pdata,52,0); /* ??? */
4728 data_size = 56;
4729 break;
4731 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4732 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4733 SIVAL(pdata,0,mode);
4734 SIVAL(pdata,4,0);
4735 data_size = 8;
4736 break;
4739 * CIFS UNIX Extensions.
4742 case SMB_QUERY_FILE_UNIX_BASIC:
4744 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4745 data_size = PTR_DIFF(pdata,(*ppdata));
4747 DEBUG(4,("smbd_do_qfilepathinfo: "
4748 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4749 dump_data(4, (uint8_t *)(*ppdata), data_size);
4751 break;
4753 case SMB_QUERY_FILE_UNIX_INFO2:
4755 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4756 data_size = PTR_DIFF(pdata,(*ppdata));
4759 int i;
4760 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4762 for (i=0; i<100; i++)
4763 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4764 DEBUG(4,("\n"));
4767 break;
4769 case SMB_QUERY_FILE_UNIX_LINK:
4771 int len;
4772 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4774 if (!buffer) {
4775 return NT_STATUS_NO_MEMORY;
4778 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4779 #ifdef S_ISLNK
4780 if(!S_ISLNK(psbuf->st_ex_mode)) {
4781 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4783 #else
4784 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4785 #endif
4786 len = SMB_VFS_READLINK(conn,
4787 smb_fname->base_name,
4788 buffer, PATH_MAX);
4789 if (len == -1) {
4790 return map_nt_error_from_unix(errno);
4792 buffer[len] = 0;
4793 len = srvstr_push(dstart, flags2,
4794 pdata, buffer,
4795 PTR_DIFF(dend, pdata),
4796 STR_TERMINATE);
4797 pdata += len;
4798 data_size = PTR_DIFF(pdata,(*ppdata));
4800 break;
4803 #if defined(HAVE_POSIX_ACLS)
4804 case SMB_QUERY_POSIX_ACL:
4806 SMB_ACL_T file_acl = NULL;
4807 SMB_ACL_T def_acl = NULL;
4808 uint16 num_file_acls = 0;
4809 uint16 num_def_acls = 0;
4811 if (fsp && fsp->fh->fd != -1) {
4812 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4813 } else {
4814 file_acl =
4815 SMB_VFS_SYS_ACL_GET_FILE(conn,
4816 smb_fname->base_name,
4817 SMB_ACL_TYPE_ACCESS);
4820 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4821 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4822 "not implemented on "
4823 "filesystem containing %s\n",
4824 smb_fname->base_name));
4825 return NT_STATUS_NOT_IMPLEMENTED;
4828 if (S_ISDIR(psbuf->st_ex_mode)) {
4829 if (fsp && fsp->is_directory) {
4830 def_acl =
4831 SMB_VFS_SYS_ACL_GET_FILE(
4832 conn,
4833 fsp->fsp_name->base_name,
4834 SMB_ACL_TYPE_DEFAULT);
4835 } else {
4836 def_acl =
4837 SMB_VFS_SYS_ACL_GET_FILE(
4838 conn,
4839 smb_fname->base_name,
4840 SMB_ACL_TYPE_DEFAULT);
4842 def_acl = free_empty_sys_acl(conn, def_acl);
4845 num_file_acls = count_acl_entries(conn, file_acl);
4846 num_def_acls = count_acl_entries(conn, def_acl);
4848 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4849 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4850 data_size,
4851 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4852 SMB_POSIX_ACL_HEADER_SIZE) ));
4853 if (file_acl) {
4854 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4856 if (def_acl) {
4857 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4859 return NT_STATUS_BUFFER_TOO_SMALL;
4862 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4863 SSVAL(pdata,2,num_file_acls);
4864 SSVAL(pdata,4,num_def_acls);
4865 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4866 if (file_acl) {
4867 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4869 if (def_acl) {
4870 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4872 return NT_STATUS_INTERNAL_ERROR;
4874 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4875 if (file_acl) {
4876 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4878 if (def_acl) {
4879 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4881 return NT_STATUS_INTERNAL_ERROR;
4884 if (file_acl) {
4885 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4887 if (def_acl) {
4888 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4890 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4891 break;
4893 #endif
4896 case SMB_QUERY_POSIX_LOCK:
4898 uint64_t count;
4899 uint64_t offset;
4900 uint64_t smblctx;
4901 enum brl_type lock_type;
4903 /* We need an open file with a real fd for this. */
4904 if (!fsp || fsp->fh->fd == -1) {
4905 return NT_STATUS_INVALID_LEVEL;
4908 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4909 return NT_STATUS_INVALID_PARAMETER;
4912 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4913 case POSIX_LOCK_TYPE_READ:
4914 lock_type = READ_LOCK;
4915 break;
4916 case POSIX_LOCK_TYPE_WRITE:
4917 lock_type = WRITE_LOCK;
4918 break;
4919 case POSIX_LOCK_TYPE_UNLOCK:
4920 default:
4921 /* There's no point in asking for an unlock... */
4922 return NT_STATUS_INVALID_PARAMETER;
4925 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4926 #if defined(HAVE_LONGLONG)
4927 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4928 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4929 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4930 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4931 #else /* HAVE_LONGLONG */
4932 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4933 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4934 #endif /* HAVE_LONGLONG */
4936 status = query_lock(fsp,
4937 &smblctx,
4938 &count,
4939 &offset,
4940 &lock_type,
4941 POSIX_LOCK);
4943 if (ERROR_WAS_LOCK_DENIED(status)) {
4944 /* Here we need to report who has it locked... */
4945 data_size = POSIX_LOCK_DATA_SIZE;
4947 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4948 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4949 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4950 #if defined(HAVE_LONGLONG)
4951 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4952 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4953 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4954 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4955 #else /* HAVE_LONGLONG */
4956 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4957 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4958 #endif /* HAVE_LONGLONG */
4960 } else if (NT_STATUS_IS_OK(status)) {
4961 /* For success we just return a copy of what we sent
4962 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4963 data_size = POSIX_LOCK_DATA_SIZE;
4964 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4965 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4966 } else {
4967 return status;
4969 break;
4972 default:
4973 return NT_STATUS_INVALID_LEVEL;
4976 *pdata_size = data_size;
4977 return NT_STATUS_OK;
4980 /****************************************************************************
4981 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4982 file name or file id).
4983 ****************************************************************************/
4985 static void call_trans2qfilepathinfo(connection_struct *conn,
4986 struct smb_request *req,
4987 unsigned int tran_call,
4988 char **pparams, int total_params,
4989 char **ppdata, int total_data,
4990 unsigned int max_data_bytes)
4992 char *params = *pparams;
4993 char *pdata = *ppdata;
4994 uint16 info_level;
4995 unsigned int data_size = 0;
4996 unsigned int param_size = 2;
4997 struct smb_filename *smb_fname = NULL;
4998 bool delete_pending = False;
4999 struct timespec write_time_ts;
5000 files_struct *fsp = NULL;
5001 struct file_id fileid;
5002 struct ea_list *ea_list = NULL;
5003 int lock_data_count = 0;
5004 char *lock_data = NULL;
5005 NTSTATUS status = NT_STATUS_OK;
5007 if (!params) {
5008 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5009 return;
5012 ZERO_STRUCT(write_time_ts);
5014 if (tran_call == TRANSACT2_QFILEINFO) {
5015 if (total_params < 4) {
5016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5017 return;
5020 if (IS_IPC(conn)) {
5021 call_trans2qpipeinfo(conn, req, tran_call,
5022 pparams, total_params,
5023 ppdata, total_data,
5024 max_data_bytes);
5025 return;
5028 fsp = file_fsp(req, SVAL(params,0));
5029 info_level = SVAL(params,2);
5031 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5033 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5034 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5035 return;
5038 /* Initial check for valid fsp ptr. */
5039 if (!check_fsp_open(conn, req, fsp)) {
5040 return;
5043 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5044 &smb_fname);
5045 if (!NT_STATUS_IS_OK(status)) {
5046 reply_nterror(req, status);
5047 return;
5050 if(fsp->fake_file_handle) {
5052 * This is actually for the QUOTA_FAKE_FILE --metze
5055 /* We know this name is ok, it's already passed the checks. */
5057 } else if(fsp->fh->fd == -1) {
5059 * This is actually a QFILEINFO on a directory
5060 * handle (returned from an NT SMB). NT5.0 seems
5061 * to do this call. JRA.
5064 if (INFO_LEVEL_IS_UNIX(info_level)) {
5065 /* Always do lstat for UNIX calls. */
5066 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5067 DEBUG(3,("call_trans2qfilepathinfo: "
5068 "SMB_VFS_LSTAT of %s failed "
5069 "(%s)\n",
5070 smb_fname_str_dbg(smb_fname),
5071 strerror(errno)));
5072 reply_nterror(req,
5073 map_nt_error_from_unix(errno));
5074 return;
5076 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5077 DEBUG(3,("call_trans2qfilepathinfo: "
5078 "SMB_VFS_STAT of %s failed (%s)\n",
5079 smb_fname_str_dbg(smb_fname),
5080 strerror(errno)));
5081 reply_nterror(req,
5082 map_nt_error_from_unix(errno));
5083 return;
5086 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5087 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5088 } else {
5090 * Original code - this is an open file.
5092 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5093 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5094 fsp->fnum, strerror(errno)));
5095 reply_nterror(req,
5096 map_nt_error_from_unix(errno));
5097 return;
5099 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5100 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5103 } else {
5104 uint32_t name_hash;
5105 char *fname = NULL;
5107 /* qpathinfo */
5108 if (total_params < 7) {
5109 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5110 return;
5113 info_level = SVAL(params,0);
5115 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5117 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5118 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5119 return;
5122 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5123 total_params - 6,
5124 STR_TERMINATE, &status);
5125 if (!NT_STATUS_IS_OK(status)) {
5126 reply_nterror(req, status);
5127 return;
5130 status = filename_convert(req,
5131 conn,
5132 req->flags2 & FLAGS2_DFS_PATHNAMES,
5133 fname,
5135 NULL,
5136 &smb_fname);
5137 if (!NT_STATUS_IS_OK(status)) {
5138 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5139 reply_botherror(req,
5140 NT_STATUS_PATH_NOT_COVERED,
5141 ERRSRV, ERRbadpath);
5142 return;
5144 reply_nterror(req, status);
5145 return;
5148 /* If this is a stream, check if there is a delete_pending. */
5149 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5150 && is_ntfs_stream_smb_fname(smb_fname)) {
5151 struct smb_filename *smb_fname_base = NULL;
5153 /* Create an smb_filename with stream_name == NULL. */
5154 status =
5155 create_synthetic_smb_fname(talloc_tos(),
5156 smb_fname->base_name,
5157 NULL, NULL,
5158 &smb_fname_base);
5159 if (!NT_STATUS_IS_OK(status)) {
5160 reply_nterror(req, status);
5161 return;
5164 if (INFO_LEVEL_IS_UNIX(info_level)) {
5165 /* Always do lstat for UNIX calls. */
5166 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5167 DEBUG(3,("call_trans2qfilepathinfo: "
5168 "SMB_VFS_LSTAT of %s failed "
5169 "(%s)\n",
5170 smb_fname_str_dbg(smb_fname_base),
5171 strerror(errno)));
5172 TALLOC_FREE(smb_fname_base);
5173 reply_nterror(req,
5174 map_nt_error_from_unix(errno));
5175 return;
5177 } else {
5178 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5179 DEBUG(3,("call_trans2qfilepathinfo: "
5180 "fileinfo of %s failed "
5181 "(%s)\n",
5182 smb_fname_str_dbg(smb_fname_base),
5183 strerror(errno)));
5184 TALLOC_FREE(smb_fname_base);
5185 reply_nterror(req,
5186 map_nt_error_from_unix(errno));
5187 return;
5191 status = file_name_hash(conn,
5192 smb_fname_str_dbg(smb_fname_base),
5193 &name_hash);
5194 if (!NT_STATUS_IS_OK(status)) {
5195 TALLOC_FREE(smb_fname_base);
5196 reply_nterror(req, status);
5197 return;
5200 fileid = vfs_file_id_from_sbuf(conn,
5201 &smb_fname_base->st);
5202 TALLOC_FREE(smb_fname_base);
5203 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5204 if (delete_pending) {
5205 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5206 return;
5210 if (INFO_LEVEL_IS_UNIX(info_level)) {
5211 /* Always do lstat for UNIX calls. */
5212 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5213 DEBUG(3,("call_trans2qfilepathinfo: "
5214 "SMB_VFS_LSTAT of %s failed (%s)\n",
5215 smb_fname_str_dbg(smb_fname),
5216 strerror(errno)));
5217 reply_nterror(req,
5218 map_nt_error_from_unix(errno));
5219 return;
5222 } else {
5223 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5224 DEBUG(3,("call_trans2qfilepathinfo: "
5225 "SMB_VFS_STAT of %s failed (%s)\n",
5226 smb_fname_str_dbg(smb_fname),
5227 strerror(errno)));
5228 reply_nterror(req,
5229 map_nt_error_from_unix(errno));
5230 return;
5234 status = file_name_hash(conn,
5235 smb_fname_str_dbg(smb_fname),
5236 &name_hash);
5237 if (!NT_STATUS_IS_OK(status)) {
5238 reply_nterror(req, status);
5239 return;
5242 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5243 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5244 if (delete_pending) {
5245 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5246 return;
5250 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5251 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5252 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5254 /* Pull out any data sent here before we realloc. */
5255 switch (info_level) {
5256 case SMB_INFO_QUERY_EAS_FROM_LIST:
5258 /* Pull any EA list from the data portion. */
5259 uint32 ea_size;
5261 if (total_data < 4) {
5262 reply_nterror(
5263 req, NT_STATUS_INVALID_PARAMETER);
5264 return;
5266 ea_size = IVAL(pdata,0);
5268 if (total_data > 0 && ea_size != total_data) {
5269 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5270 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5271 reply_nterror(
5272 req, NT_STATUS_INVALID_PARAMETER);
5273 return;
5276 if (!lp_ea_support(SNUM(conn))) {
5277 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5278 return;
5281 /* Pull out the list of names. */
5282 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5283 if (!ea_list) {
5284 reply_nterror(
5285 req, NT_STATUS_INVALID_PARAMETER);
5286 return;
5288 break;
5291 case SMB_QUERY_POSIX_LOCK:
5293 if (fsp == NULL || fsp->fh->fd == -1) {
5294 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5295 return;
5298 if (total_data != POSIX_LOCK_DATA_SIZE) {
5299 reply_nterror(
5300 req, NT_STATUS_INVALID_PARAMETER);
5301 return;
5304 /* Copy the lock range data. */
5305 lock_data = (char *)TALLOC_MEMDUP(
5306 req, pdata, total_data);
5307 if (!lock_data) {
5308 reply_nterror(req, NT_STATUS_NO_MEMORY);
5309 return;
5311 lock_data_count = total_data;
5313 default:
5314 break;
5317 *pparams = (char *)SMB_REALLOC(*pparams,2);
5318 if (*pparams == NULL) {
5319 reply_nterror(req, NT_STATUS_NO_MEMORY);
5320 return;
5322 params = *pparams;
5323 SSVAL(params,0,0);
5326 * draft-leach-cifs-v1-spec-02.txt
5327 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5328 * says:
5330 * The requested information is placed in the Data portion of the
5331 * transaction response. For the information levels greater than 0x100,
5332 * the transaction response has 1 parameter word which should be
5333 * ignored by the client.
5335 * However Windows only follows this rule for the IS_NAME_VALID call.
5337 switch (info_level) {
5338 case SMB_INFO_IS_NAME_VALID:
5339 param_size = 0;
5340 break;
5343 if ((info_level & 0xFF00) == 0xFF00) {
5345 * We use levels that start with 0xFF00
5346 * internally to represent SMB2 specific levels
5348 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5349 return;
5352 status = smbd_do_qfilepathinfo(conn, req, info_level,
5353 fsp, smb_fname,
5354 delete_pending, write_time_ts,
5355 ea_list,
5356 lock_data_count, lock_data,
5357 req->flags2, max_data_bytes,
5358 ppdata, &data_size);
5359 if (!NT_STATUS_IS_OK(status)) {
5360 reply_nterror(req, status);
5361 return;
5364 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5365 max_data_bytes);
5367 return;
5370 /****************************************************************************
5371 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5372 code.
5373 ****************************************************************************/
5375 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5376 connection_struct *conn,
5377 struct smb_request *req,
5378 bool overwrite_if_exists,
5379 const struct smb_filename *smb_fname_old,
5380 struct smb_filename *smb_fname_new)
5382 NTSTATUS status = NT_STATUS_OK;
5384 /* source must already exist. */
5385 if (!VALID_STAT(smb_fname_old->st)) {
5386 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5389 if (VALID_STAT(smb_fname_new->st)) {
5390 if (overwrite_if_exists) {
5391 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5392 return NT_STATUS_FILE_IS_A_DIRECTORY;
5394 status = unlink_internals(conn,
5395 req,
5396 FILE_ATTRIBUTE_NORMAL,
5397 smb_fname_new,
5398 false);
5399 if (!NT_STATUS_IS_OK(status)) {
5400 return status;
5402 } else {
5403 /* Disallow if newname already exists. */
5404 return NT_STATUS_OBJECT_NAME_COLLISION;
5408 /* No links from a directory. */
5409 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5410 return NT_STATUS_FILE_IS_A_DIRECTORY;
5413 /* Setting a hardlink to/from a stream isn't currently supported. */
5414 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5415 is_ntfs_stream_smb_fname(smb_fname_new)) {
5416 return NT_STATUS_INVALID_PARAMETER;
5419 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5420 smb_fname_old->base_name, smb_fname_new->base_name));
5422 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5423 smb_fname_new->base_name) != 0) {
5424 status = map_nt_error_from_unix(errno);
5425 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5426 nt_errstr(status), smb_fname_old->base_name,
5427 smb_fname_new->base_name));
5429 return status;
5432 /****************************************************************************
5433 Deal with setting the time from any of the setfilepathinfo functions.
5434 ****************************************************************************/
5436 NTSTATUS smb_set_file_time(connection_struct *conn,
5437 files_struct *fsp,
5438 const struct smb_filename *smb_fname,
5439 struct smb_file_time *ft,
5440 bool setting_write_time)
5442 struct smb_filename smb_fname_base;
5443 uint32 action =
5444 FILE_NOTIFY_CHANGE_LAST_ACCESS
5445 |FILE_NOTIFY_CHANGE_LAST_WRITE
5446 |FILE_NOTIFY_CHANGE_CREATION;
5448 if (!VALID_STAT(smb_fname->st)) {
5449 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5452 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5453 return NT_STATUS_ACCESS_DENIED;
5456 /* get some defaults (no modifications) if any info is zero or -1. */
5457 if (null_timespec(ft->create_time)) {
5458 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5461 if (null_timespec(ft->atime)) {
5462 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5465 if (null_timespec(ft->mtime)) {
5466 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5469 if (!setting_write_time) {
5470 /* ft->mtime comes from change time, not write time. */
5471 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5474 /* Ensure the resolution is the correct for
5475 * what we can store on this filesystem. */
5477 round_timespec(conn->ts_res, &ft->create_time);
5478 round_timespec(conn->ts_res, &ft->ctime);
5479 round_timespec(conn->ts_res, &ft->atime);
5480 round_timespec(conn->ts_res, &ft->mtime);
5482 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5483 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5484 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5485 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5486 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5487 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5488 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5489 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5491 if (setting_write_time) {
5493 * This was a Windows setfileinfo on an open file.
5494 * NT does this a lot. We also need to
5495 * set the time here, as it can be read by
5496 * FindFirst/FindNext and with the patch for bug #2045
5497 * in smbd/fileio.c it ensures that this timestamp is
5498 * kept sticky even after a write. We save the request
5499 * away and will set it on file close and after a write. JRA.
5502 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5503 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5505 if (fsp != NULL) {
5506 if (fsp->base_fsp) {
5507 set_sticky_write_time_fsp(fsp->base_fsp,
5508 ft->mtime);
5509 } else {
5510 set_sticky_write_time_fsp(fsp, ft->mtime);
5512 } else {
5513 set_sticky_write_time_path(
5514 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5515 ft->mtime);
5519 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5521 /* Always call ntimes on the base, even if a stream was passed in. */
5522 smb_fname_base = *smb_fname;
5523 smb_fname_base.stream_name = NULL;
5525 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5526 return map_nt_error_from_unix(errno);
5529 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5530 smb_fname->base_name);
5531 return NT_STATUS_OK;
5534 /****************************************************************************
5535 Deal with setting the dosmode from any of the setfilepathinfo functions.
5536 ****************************************************************************/
5538 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5539 const struct smb_filename *smb_fname,
5540 uint32 dosmode)
5542 struct smb_filename *smb_fname_base = NULL;
5543 NTSTATUS status;
5545 if (!VALID_STAT(smb_fname->st)) {
5546 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5549 /* Always operate on the base_name, even if a stream was passed in. */
5550 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5551 NULL, &smb_fname->st,
5552 &smb_fname_base);
5553 if (!NT_STATUS_IS_OK(status)) {
5554 return status;
5557 if (dosmode) {
5558 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5559 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5560 } else {
5561 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5565 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5567 /* check the mode isn't different, before changing it */
5568 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5569 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5570 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5571 (unsigned int)dosmode));
5573 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5574 false)) {
5575 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5576 "%s failed (%s)\n",
5577 smb_fname_str_dbg(smb_fname_base),
5578 strerror(errno)));
5579 status = map_nt_error_from_unix(errno);
5580 goto out;
5583 status = NT_STATUS_OK;
5584 out:
5585 TALLOC_FREE(smb_fname_base);
5586 return status;
5589 /****************************************************************************
5590 Deal with setting the size from any of the setfilepathinfo functions.
5591 ****************************************************************************/
5593 static NTSTATUS smb_set_file_size(connection_struct *conn,
5594 struct smb_request *req,
5595 files_struct *fsp,
5596 const struct smb_filename *smb_fname,
5597 const SMB_STRUCT_STAT *psbuf,
5598 SMB_OFF_T size,
5599 bool fail_after_createfile)
5601 NTSTATUS status = NT_STATUS_OK;
5602 struct smb_filename *smb_fname_tmp = NULL;
5603 files_struct *new_fsp = NULL;
5605 if (!VALID_STAT(*psbuf)) {
5606 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5609 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5610 return NT_STATUS_ACCESS_DENIED;
5613 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5615 if (size == get_file_size_stat(psbuf)) {
5616 return NT_STATUS_OK;
5619 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5620 smb_fname_str_dbg(smb_fname), (double)size));
5622 if (fsp && fsp->fh->fd != -1) {
5623 /* Handle based call. */
5624 if (vfs_set_filelen(fsp, size) == -1) {
5625 return map_nt_error_from_unix(errno);
5627 trigger_write_time_update_immediate(fsp);
5628 return NT_STATUS_OK;
5631 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5632 if (!NT_STATUS_IS_OK(status)) {
5633 return status;
5636 smb_fname_tmp->st = *psbuf;
5638 status = SMB_VFS_CREATE_FILE(
5639 conn, /* conn */
5640 req, /* req */
5641 0, /* root_dir_fid */
5642 smb_fname_tmp, /* fname */
5643 FILE_WRITE_DATA, /* access_mask */
5644 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5645 FILE_SHARE_DELETE),
5646 FILE_OPEN, /* create_disposition*/
5647 0, /* create_options */
5648 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5649 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5650 0, /* allocation_size */
5651 0, /* private_flags */
5652 NULL, /* sd */
5653 NULL, /* ea_list */
5654 &new_fsp, /* result */
5655 NULL); /* pinfo */
5657 TALLOC_FREE(smb_fname_tmp);
5659 if (!NT_STATUS_IS_OK(status)) {
5660 /* NB. We check for open_was_deferred in the caller. */
5661 return status;
5664 /* See RAW-SFILEINFO-END-OF-FILE */
5665 if (fail_after_createfile) {
5666 close_file(req, new_fsp,NORMAL_CLOSE);
5667 return NT_STATUS_INVALID_LEVEL;
5670 if (vfs_set_filelen(new_fsp, size) == -1) {
5671 status = map_nt_error_from_unix(errno);
5672 close_file(req, new_fsp,NORMAL_CLOSE);
5673 return status;
5676 trigger_write_time_update_immediate(new_fsp);
5677 close_file(req, new_fsp,NORMAL_CLOSE);
5678 return NT_STATUS_OK;
5681 /****************************************************************************
5682 Deal with SMB_INFO_SET_EA.
5683 ****************************************************************************/
5685 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5686 const char *pdata,
5687 int total_data,
5688 files_struct *fsp,
5689 const struct smb_filename *smb_fname)
5691 struct ea_list *ea_list = NULL;
5692 TALLOC_CTX *ctx = NULL;
5693 NTSTATUS status = NT_STATUS_OK;
5695 if (total_data < 10) {
5697 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5698 length. They seem to have no effect. Bug #3212. JRA */
5700 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5701 /* We're done. We only get EA info in this call. */
5702 return NT_STATUS_OK;
5705 return NT_STATUS_INVALID_PARAMETER;
5708 if (IVAL(pdata,0) > total_data) {
5709 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5710 IVAL(pdata,0), (unsigned int)total_data));
5711 return NT_STATUS_INVALID_PARAMETER;
5714 ctx = talloc_tos();
5715 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5716 if (!ea_list) {
5717 return NT_STATUS_INVALID_PARAMETER;
5720 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5721 return NT_STATUS_ACCESS_DENIED;
5724 status = set_ea(conn, fsp, smb_fname, ea_list);
5726 return status;
5729 /****************************************************************************
5730 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5731 ****************************************************************************/
5733 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5734 const char *pdata,
5735 int total_data,
5736 files_struct *fsp)
5738 struct ea_list *ea_list = NULL;
5739 NTSTATUS status;
5741 if (!fsp) {
5742 return NT_STATUS_INVALID_HANDLE;
5745 if (!lp_ea_support(SNUM(conn))) {
5746 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5747 "EA's not supported.\n",
5748 (unsigned int)total_data));
5749 return NT_STATUS_EAS_NOT_SUPPORTED;
5752 if (total_data < 10) {
5753 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5754 "too small.\n",
5755 (unsigned int)total_data));
5756 return NT_STATUS_INVALID_PARAMETER;
5759 ea_list = read_nttrans_ea_list(talloc_tos(),
5760 pdata,
5761 total_data);
5763 if (!ea_list) {
5764 return NT_STATUS_INVALID_PARAMETER;
5767 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5768 return NT_STATUS_ACCESS_DENIED;
5771 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5773 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5774 smb_fname_str_dbg(fsp->fsp_name),
5775 nt_errstr(status) ));
5777 return status;
5781 /****************************************************************************
5782 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5783 ****************************************************************************/
5785 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5786 const char *pdata,
5787 int total_data,
5788 files_struct *fsp,
5789 struct smb_filename *smb_fname)
5791 NTSTATUS status = NT_STATUS_OK;
5792 bool delete_on_close;
5793 uint32 dosmode = 0;
5795 if (total_data < 1) {
5796 return NT_STATUS_INVALID_PARAMETER;
5799 if (fsp == NULL) {
5800 return NT_STATUS_INVALID_HANDLE;
5803 delete_on_close = (CVAL(pdata,0) ? True : False);
5804 dosmode = dos_mode(conn, smb_fname);
5806 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5807 "delete_on_close = %u\n",
5808 smb_fname_str_dbg(smb_fname),
5809 (unsigned int)dosmode,
5810 (unsigned int)delete_on_close ));
5812 if (delete_on_close) {
5813 status = can_set_delete_on_close(fsp, dosmode);
5814 if (!NT_STATUS_IS_OK(status)) {
5815 return status;
5819 /* The set is across all open files on this dev/inode pair. */
5820 if (!set_delete_on_close(fsp, delete_on_close,
5821 &conn->session_info->utok)) {
5822 return NT_STATUS_ACCESS_DENIED;
5824 return NT_STATUS_OK;
5827 /****************************************************************************
5828 Deal with SMB_FILE_POSITION_INFORMATION.
5829 ****************************************************************************/
5831 static NTSTATUS smb_file_position_information(connection_struct *conn,
5832 const char *pdata,
5833 int total_data,
5834 files_struct *fsp)
5836 uint64_t position_information;
5838 if (total_data < 8) {
5839 return NT_STATUS_INVALID_PARAMETER;
5842 if (fsp == NULL) {
5843 /* Ignore on pathname based set. */
5844 return NT_STATUS_OK;
5847 position_information = (uint64_t)IVAL(pdata,0);
5848 #ifdef LARGE_SMB_OFF_T
5849 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5850 #else /* LARGE_SMB_OFF_T */
5851 if (IVAL(pdata,4) != 0) {
5852 /* more than 32 bits? */
5853 return NT_STATUS_INVALID_PARAMETER;
5855 #endif /* LARGE_SMB_OFF_T */
5857 DEBUG(10,("smb_file_position_information: Set file position "
5858 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5859 (double)position_information));
5860 fsp->fh->position_information = position_information;
5861 return NT_STATUS_OK;
5864 /****************************************************************************
5865 Deal with SMB_FILE_MODE_INFORMATION.
5866 ****************************************************************************/
5868 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5869 const char *pdata,
5870 int total_data)
5872 uint32 mode;
5874 if (total_data < 4) {
5875 return NT_STATUS_INVALID_PARAMETER;
5877 mode = IVAL(pdata,0);
5878 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5879 return NT_STATUS_INVALID_PARAMETER;
5881 return NT_STATUS_OK;
5884 /****************************************************************************
5885 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5886 ****************************************************************************/
5888 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5889 struct smb_request *req,
5890 const char *pdata,
5891 int total_data,
5892 const struct smb_filename *smb_fname)
5894 char *link_target = NULL;
5895 const char *newname = smb_fname->base_name;
5896 TALLOC_CTX *ctx = talloc_tos();
5898 /* Set a symbolic link. */
5899 /* Don't allow this if follow links is false. */
5901 if (total_data == 0) {
5902 return NT_STATUS_INVALID_PARAMETER;
5905 if (!lp_symlinks(SNUM(conn))) {
5906 return NT_STATUS_ACCESS_DENIED;
5909 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5910 total_data, STR_TERMINATE);
5912 if (!link_target) {
5913 return NT_STATUS_INVALID_PARAMETER;
5916 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5917 newname, link_target ));
5919 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5920 return map_nt_error_from_unix(errno);
5923 return NT_STATUS_OK;
5926 /****************************************************************************
5927 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5928 ****************************************************************************/
5930 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5931 struct smb_request *req,
5932 const char *pdata, int total_data,
5933 struct smb_filename *smb_fname_new)
5935 char *oldname = NULL;
5936 struct smb_filename *smb_fname_old = NULL;
5937 TALLOC_CTX *ctx = talloc_tos();
5938 NTSTATUS status = NT_STATUS_OK;
5940 /* Set a hard link. */
5941 if (total_data == 0) {
5942 return NT_STATUS_INVALID_PARAMETER;
5945 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5946 total_data, STR_TERMINATE, &status);
5947 if (!NT_STATUS_IS_OK(status)) {
5948 return status;
5951 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5952 smb_fname_str_dbg(smb_fname_new), oldname));
5954 status = filename_convert(ctx,
5955 conn,
5956 req->flags2 & FLAGS2_DFS_PATHNAMES,
5957 oldname,
5959 NULL,
5960 &smb_fname_old);
5961 if (!NT_STATUS_IS_OK(status)) {
5962 return status;
5965 return hardlink_internals(ctx, conn, req, false,
5966 smb_fname_old, smb_fname_new);
5969 /****************************************************************************
5970 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5971 ****************************************************************************/
5973 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5974 struct smb_request *req,
5975 const char *pdata,
5976 int total_data,
5977 files_struct *fsp,
5978 struct smb_filename *smb_fname_src)
5980 bool overwrite;
5981 uint32_t len;
5982 char *newname = NULL;
5983 struct smb_filename *smb_fname_dst = NULL;
5984 NTSTATUS status = NT_STATUS_OK;
5985 TALLOC_CTX *ctx = talloc_tos();
5987 if (!fsp) {
5988 return NT_STATUS_INVALID_HANDLE;
5991 if (total_data < 20) {
5992 return NT_STATUS_INVALID_PARAMETER;
5995 overwrite = (CVAL(pdata,0) ? True : False);
5996 len = IVAL(pdata,16);
5998 if (len > (total_data - 20) || (len == 0)) {
5999 return NT_STATUS_INVALID_PARAMETER;
6002 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6003 &pdata[20], len, STR_TERMINATE,
6004 &status);
6005 if (!NT_STATUS_IS_OK(status)) {
6006 return status;
6009 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6010 newname));
6012 status = filename_convert(ctx,
6013 conn,
6014 req->flags2 & FLAGS2_DFS_PATHNAMES,
6015 newname,
6016 UCF_SAVE_LCOMP,
6017 NULL,
6018 &smb_fname_dst);
6019 if (!NT_STATUS_IS_OK(status)) {
6020 return status;
6023 if (fsp->base_fsp) {
6024 /* newname must be a stream name. */
6025 if (newname[0] != ':') {
6026 return NT_STATUS_NOT_SUPPORTED;
6029 /* Create an smb_fname to call rename_internals_fsp() with. */
6030 status = create_synthetic_smb_fname(talloc_tos(),
6031 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6032 &smb_fname_dst);
6033 if (!NT_STATUS_IS_OK(status)) {
6034 goto out;
6038 * Set the original last component, since
6039 * rename_internals_fsp() requires it.
6041 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6042 newname);
6043 if (smb_fname_dst->original_lcomp == NULL) {
6044 status = NT_STATUS_NO_MEMORY;
6045 goto out;
6050 DEBUG(10,("smb2_file_rename_information: "
6051 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6052 fsp->fnum, fsp_str_dbg(fsp),
6053 smb_fname_str_dbg(smb_fname_dst)));
6054 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6055 overwrite);
6057 out:
6058 TALLOC_FREE(smb_fname_dst);
6059 return status;
6062 static NTSTATUS smb_file_link_information(connection_struct *conn,
6063 struct smb_request *req,
6064 const char *pdata,
6065 int total_data,
6066 files_struct *fsp,
6067 struct smb_filename *smb_fname_src)
6069 bool overwrite;
6070 uint32_t len;
6071 char *newname = NULL;
6072 struct smb_filename *smb_fname_dst = NULL;
6073 NTSTATUS status = NT_STATUS_OK;
6074 TALLOC_CTX *ctx = talloc_tos();
6076 if (!fsp) {
6077 return NT_STATUS_INVALID_HANDLE;
6080 if (total_data < 20) {
6081 return NT_STATUS_INVALID_PARAMETER;
6084 overwrite = (CVAL(pdata,0) ? true : false);
6085 len = IVAL(pdata,16);
6087 if (len > (total_data - 20) || (len == 0)) {
6088 return NT_STATUS_INVALID_PARAMETER;
6091 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6092 &pdata[20], len, STR_TERMINATE,
6093 &status);
6094 if (!NT_STATUS_IS_OK(status)) {
6095 return status;
6098 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6099 newname));
6101 status = filename_convert(ctx,
6102 conn,
6103 req->flags2 & FLAGS2_DFS_PATHNAMES,
6104 newname,
6105 UCF_SAVE_LCOMP,
6106 NULL,
6107 &smb_fname_dst);
6108 if (!NT_STATUS_IS_OK(status)) {
6109 return status;
6112 if (fsp->base_fsp) {
6113 /* No stream names. */
6114 return NT_STATUS_NOT_SUPPORTED;
6117 DEBUG(10,("smb_file_link_information: "
6118 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6119 fsp->fnum, fsp_str_dbg(fsp),
6120 smb_fname_str_dbg(smb_fname_dst)));
6121 status = hardlink_internals(ctx,
6122 conn,
6123 req,
6124 overwrite,
6125 fsp->fsp_name,
6126 smb_fname_dst);
6128 TALLOC_FREE(smb_fname_dst);
6129 return status;
6132 /****************************************************************************
6133 Deal with SMB_FILE_RENAME_INFORMATION.
6134 ****************************************************************************/
6136 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6137 struct smb_request *req,
6138 const char *pdata,
6139 int total_data,
6140 files_struct *fsp,
6141 struct smb_filename *smb_fname_src)
6143 bool overwrite;
6144 uint32 root_fid;
6145 uint32 len;
6146 char *newname = NULL;
6147 struct smb_filename *smb_fname_dst = NULL;
6148 bool dest_has_wcard = False;
6149 NTSTATUS status = NT_STATUS_OK;
6150 char *p;
6151 TALLOC_CTX *ctx = talloc_tos();
6153 if (total_data < 13) {
6154 return NT_STATUS_INVALID_PARAMETER;
6157 overwrite = (CVAL(pdata,0) ? True : False);
6158 root_fid = IVAL(pdata,4);
6159 len = IVAL(pdata,8);
6161 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6162 return NT_STATUS_INVALID_PARAMETER;
6165 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6166 len, 0, &status,
6167 &dest_has_wcard);
6168 if (!NT_STATUS_IS_OK(status)) {
6169 return status;
6172 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6173 newname));
6175 status = resolve_dfspath_wcard(ctx, conn,
6176 req->flags2 & FLAGS2_DFS_PATHNAMES,
6177 newname,
6178 true,
6179 &newname,
6180 &dest_has_wcard);
6181 if (!NT_STATUS_IS_OK(status)) {
6182 return status;
6185 /* Check the new name has no '/' characters. */
6186 if (strchr_m(newname, '/')) {
6187 return NT_STATUS_NOT_SUPPORTED;
6190 if (fsp && fsp->base_fsp) {
6191 /* newname must be a stream name. */
6192 if (newname[0] != ':') {
6193 return NT_STATUS_NOT_SUPPORTED;
6196 /* Create an smb_fname to call rename_internals_fsp() with. */
6197 status = create_synthetic_smb_fname(talloc_tos(),
6198 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6199 &smb_fname_dst);
6200 if (!NT_STATUS_IS_OK(status)) {
6201 goto out;
6205 * Set the original last component, since
6206 * rename_internals_fsp() requires it.
6208 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6209 newname);
6210 if (smb_fname_dst->original_lcomp == NULL) {
6211 status = NT_STATUS_NO_MEMORY;
6212 goto out;
6215 } else {
6217 * Build up an smb_fname_dst based on the filename passed in.
6218 * We basically just strip off the last component, and put on
6219 * the newname instead.
6221 char *base_name = NULL;
6223 /* newname must *not* be a stream name. */
6224 if (newname[0] == ':') {
6225 return NT_STATUS_NOT_SUPPORTED;
6229 * Strip off the last component (filename) of the path passed
6230 * in.
6232 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6233 if (!base_name) {
6234 return NT_STATUS_NO_MEMORY;
6236 p = strrchr_m(base_name, '/');
6237 if (p) {
6238 p[1] = '\0';
6239 } else {
6240 base_name = talloc_strdup(ctx, "");
6241 if (!base_name) {
6242 return NT_STATUS_NO_MEMORY;
6245 /* Append the new name. */
6246 base_name = talloc_asprintf_append(base_name,
6247 "%s",
6248 newname);
6249 if (!base_name) {
6250 return NT_STATUS_NO_MEMORY;
6253 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6254 (UCF_SAVE_LCOMP |
6255 (dest_has_wcard ?
6256 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6257 0)));
6259 /* If an error we expect this to be
6260 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6262 if (!NT_STATUS_IS_OK(status)) {
6263 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6264 status)) {
6265 goto out;
6267 /* Create an smb_fname to call rename_internals_fsp() */
6268 status = create_synthetic_smb_fname(ctx,
6269 base_name, NULL,
6270 NULL,
6271 &smb_fname_dst);
6272 if (!NT_STATUS_IS_OK(status)) {
6273 goto out;
6278 if (fsp) {
6279 DEBUG(10,("smb_file_rename_information: "
6280 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6281 fsp->fnum, fsp_str_dbg(fsp),
6282 smb_fname_str_dbg(smb_fname_dst)));
6283 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6284 overwrite);
6285 } else {
6286 DEBUG(10,("smb_file_rename_information: "
6287 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6288 smb_fname_str_dbg(smb_fname_src),
6289 smb_fname_str_dbg(smb_fname_dst)));
6290 status = rename_internals(ctx, conn, req, smb_fname_src,
6291 smb_fname_dst, 0, overwrite, false,
6292 dest_has_wcard,
6293 FILE_WRITE_ATTRIBUTES);
6295 out:
6296 TALLOC_FREE(smb_fname_dst);
6297 return status;
6300 /****************************************************************************
6301 Deal with SMB_SET_POSIX_ACL.
6302 ****************************************************************************/
6304 #if defined(HAVE_POSIX_ACLS)
6305 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6306 const char *pdata,
6307 int total_data,
6308 files_struct *fsp,
6309 const struct smb_filename *smb_fname)
6311 uint16 posix_acl_version;
6312 uint16 num_file_acls;
6313 uint16 num_def_acls;
6314 bool valid_file_acls = True;
6315 bool valid_def_acls = True;
6317 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6318 return NT_STATUS_INVALID_PARAMETER;
6320 posix_acl_version = SVAL(pdata,0);
6321 num_file_acls = SVAL(pdata,2);
6322 num_def_acls = SVAL(pdata,4);
6324 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6325 valid_file_acls = False;
6326 num_file_acls = 0;
6329 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6330 valid_def_acls = False;
6331 num_def_acls = 0;
6334 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6335 return NT_STATUS_INVALID_PARAMETER;
6338 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6339 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6340 return NT_STATUS_INVALID_PARAMETER;
6343 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6344 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6345 (unsigned int)num_file_acls,
6346 (unsigned int)num_def_acls));
6348 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6349 smb_fname->base_name, num_file_acls,
6350 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6351 return map_nt_error_from_unix(errno);
6354 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6355 smb_fname->base_name, &smb_fname->st, num_def_acls,
6356 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6357 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6358 return map_nt_error_from_unix(errno);
6360 return NT_STATUS_OK;
6362 #endif
6364 /****************************************************************************
6365 Deal with SMB_SET_POSIX_LOCK.
6366 ****************************************************************************/
6368 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6369 struct smb_request *req,
6370 const char *pdata,
6371 int total_data,
6372 files_struct *fsp)
6374 uint64_t count;
6375 uint64_t offset;
6376 uint64_t smblctx;
6377 bool blocking_lock = False;
6378 enum brl_type lock_type;
6380 NTSTATUS status = NT_STATUS_OK;
6382 if (fsp == NULL || fsp->fh->fd == -1) {
6383 return NT_STATUS_INVALID_HANDLE;
6386 if (total_data != POSIX_LOCK_DATA_SIZE) {
6387 return NT_STATUS_INVALID_PARAMETER;
6390 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6391 case POSIX_LOCK_TYPE_READ:
6392 lock_type = READ_LOCK;
6393 break;
6394 case POSIX_LOCK_TYPE_WRITE:
6395 /* Return the right POSIX-mappable error code for files opened read-only. */
6396 if (!fsp->can_write) {
6397 return NT_STATUS_INVALID_HANDLE;
6399 lock_type = WRITE_LOCK;
6400 break;
6401 case POSIX_LOCK_TYPE_UNLOCK:
6402 lock_type = UNLOCK_LOCK;
6403 break;
6404 default:
6405 return NT_STATUS_INVALID_PARAMETER;
6408 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6409 blocking_lock = False;
6410 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6411 blocking_lock = True;
6412 } else {
6413 return NT_STATUS_INVALID_PARAMETER;
6416 if (!lp_blocking_locks(SNUM(conn))) {
6417 blocking_lock = False;
6420 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6421 #if defined(HAVE_LONGLONG)
6422 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6423 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6424 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6425 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6426 #else /* HAVE_LONGLONG */
6427 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6428 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6429 #endif /* HAVE_LONGLONG */
6431 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6432 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6433 fsp_str_dbg(fsp),
6434 (unsigned int)lock_type,
6435 (unsigned long long)smblctx,
6436 (double)count,
6437 (double)offset ));
6439 if (lock_type == UNLOCK_LOCK) {
6440 status = do_unlock(req->sconn->msg_ctx,
6441 fsp,
6442 smblctx,
6443 count,
6444 offset,
6445 POSIX_LOCK);
6446 } else {
6447 uint64_t block_smblctx;
6449 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6450 fsp,
6451 smblctx,
6452 count,
6453 offset,
6454 lock_type,
6455 POSIX_LOCK,
6456 blocking_lock,
6457 &status,
6458 &block_smblctx,
6459 NULL);
6461 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6463 * A blocking lock was requested. Package up
6464 * this smb into a queued request and push it
6465 * onto the blocking lock queue.
6467 if(push_blocking_lock_request(br_lck,
6468 req,
6469 fsp,
6470 -1, /* infinite timeout. */
6472 smblctx,
6473 lock_type,
6474 POSIX_LOCK,
6475 offset,
6476 count,
6477 block_smblctx)) {
6478 TALLOC_FREE(br_lck);
6479 return status;
6482 TALLOC_FREE(br_lck);
6485 return status;
6488 /****************************************************************************
6489 Deal with SMB_SET_FILE_BASIC_INFO.
6490 ****************************************************************************/
6492 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6493 const char *pdata,
6494 int total_data,
6495 files_struct *fsp,
6496 const struct smb_filename *smb_fname)
6498 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6499 struct smb_file_time ft;
6500 uint32 dosmode = 0;
6501 NTSTATUS status = NT_STATUS_OK;
6503 ZERO_STRUCT(ft);
6505 if (total_data < 36) {
6506 return NT_STATUS_INVALID_PARAMETER;
6509 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6510 return NT_STATUS_ACCESS_DENIED;
6513 /* Set the attributes */
6514 dosmode = IVAL(pdata,32);
6515 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6516 if (!NT_STATUS_IS_OK(status)) {
6517 return status;
6520 /* create time */
6521 ft.create_time = interpret_long_date(pdata);
6523 /* access time */
6524 ft.atime = interpret_long_date(pdata+8);
6526 /* write time. */
6527 ft.mtime = interpret_long_date(pdata+16);
6529 /* change time. */
6530 ft.ctime = interpret_long_date(pdata+24);
6532 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6533 smb_fname_str_dbg(smb_fname)));
6535 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6536 true);
6539 /****************************************************************************
6540 Deal with SMB_INFO_STANDARD.
6541 ****************************************************************************/
6543 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6544 const char *pdata,
6545 int total_data,
6546 files_struct *fsp,
6547 const struct smb_filename *smb_fname)
6549 struct smb_file_time ft;
6551 ZERO_STRUCT(ft);
6553 if (total_data < 12) {
6554 return NT_STATUS_INVALID_PARAMETER;
6557 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6558 return NT_STATUS_ACCESS_DENIED;
6561 /* create time */
6562 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6563 /* access time */
6564 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6565 /* write time */
6566 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6568 DEBUG(10,("smb_set_info_standard: file %s\n",
6569 smb_fname_str_dbg(smb_fname)));
6571 return smb_set_file_time(conn,
6572 fsp,
6573 smb_fname,
6574 &ft,
6575 true);
6578 /****************************************************************************
6579 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6580 ****************************************************************************/
6582 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6583 struct smb_request *req,
6584 const char *pdata,
6585 int total_data,
6586 files_struct *fsp,
6587 struct smb_filename *smb_fname)
6589 uint64_t allocation_size = 0;
6590 NTSTATUS status = NT_STATUS_OK;
6591 files_struct *new_fsp = NULL;
6593 if (!VALID_STAT(smb_fname->st)) {
6594 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6597 if (total_data < 8) {
6598 return NT_STATUS_INVALID_PARAMETER;
6601 allocation_size = (uint64_t)IVAL(pdata,0);
6602 #ifdef LARGE_SMB_OFF_T
6603 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6604 #else /* LARGE_SMB_OFF_T */
6605 if (IVAL(pdata,4) != 0) {
6606 /* more than 32 bits? */
6607 return NT_STATUS_INVALID_PARAMETER;
6609 #endif /* LARGE_SMB_OFF_T */
6611 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6612 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6613 (double)allocation_size));
6615 if (allocation_size) {
6616 allocation_size = smb_roundup(conn, allocation_size);
6619 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6620 return NT_STATUS_ACCESS_DENIED;
6623 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6624 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6625 (double)allocation_size));
6627 if (fsp && fsp->fh->fd != -1) {
6628 /* Open file handle. */
6629 /* Only change if needed. */
6630 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6631 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6632 return map_nt_error_from_unix(errno);
6635 /* But always update the time. */
6637 * This is equivalent to a write. Ensure it's seen immediately
6638 * if there are no pending writes.
6640 trigger_write_time_update_immediate(fsp);
6641 return NT_STATUS_OK;
6644 /* Pathname or stat or directory file. */
6645 status = SMB_VFS_CREATE_FILE(
6646 conn, /* conn */
6647 req, /* req */
6648 0, /* root_dir_fid */
6649 smb_fname, /* fname */
6650 FILE_WRITE_DATA, /* access_mask */
6651 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6652 FILE_SHARE_DELETE),
6653 FILE_OPEN, /* create_disposition*/
6654 0, /* create_options */
6655 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6656 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6657 0, /* allocation_size */
6658 0, /* private_flags */
6659 NULL, /* sd */
6660 NULL, /* ea_list */
6661 &new_fsp, /* result */
6662 NULL); /* pinfo */
6664 if (!NT_STATUS_IS_OK(status)) {
6665 /* NB. We check for open_was_deferred in the caller. */
6666 return status;
6669 /* Only change if needed. */
6670 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6671 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6672 status = map_nt_error_from_unix(errno);
6673 close_file(req, new_fsp, NORMAL_CLOSE);
6674 return status;
6678 /* Changing the allocation size should set the last mod time. */
6680 * This is equivalent to a write. Ensure it's seen immediately
6681 * if there are no pending writes.
6683 trigger_write_time_update_immediate(new_fsp);
6685 close_file(req, new_fsp, NORMAL_CLOSE);
6686 return NT_STATUS_OK;
6689 /****************************************************************************
6690 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6691 ****************************************************************************/
6693 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6694 struct smb_request *req,
6695 const char *pdata,
6696 int total_data,
6697 files_struct *fsp,
6698 const struct smb_filename *smb_fname,
6699 bool fail_after_createfile)
6701 SMB_OFF_T size;
6703 if (total_data < 8) {
6704 return NT_STATUS_INVALID_PARAMETER;
6707 size = IVAL(pdata,0);
6708 #ifdef LARGE_SMB_OFF_T
6709 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6710 #else /* LARGE_SMB_OFF_T */
6711 if (IVAL(pdata,4) != 0) {
6712 /* more than 32 bits? */
6713 return NT_STATUS_INVALID_PARAMETER;
6715 #endif /* LARGE_SMB_OFF_T */
6716 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6717 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6718 (double)size));
6720 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6721 return NT_STATUS_ACCESS_DENIED;
6724 return smb_set_file_size(conn, req,
6725 fsp,
6726 smb_fname,
6727 &smb_fname->st,
6728 size,
6729 fail_after_createfile);
6732 /****************************************************************************
6733 Allow a UNIX info mknod.
6734 ****************************************************************************/
6736 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6737 const char *pdata,
6738 int total_data,
6739 const struct smb_filename *smb_fname)
6741 uint32 file_type = IVAL(pdata,56);
6742 #if defined(HAVE_MAKEDEV)
6743 uint32 dev_major = IVAL(pdata,60);
6744 uint32 dev_minor = IVAL(pdata,68);
6745 #endif
6746 SMB_DEV_T dev = (SMB_DEV_T)0;
6747 uint32 raw_unixmode = IVAL(pdata,84);
6748 NTSTATUS status;
6749 mode_t unixmode;
6751 if (total_data < 100) {
6752 return NT_STATUS_INVALID_PARAMETER;
6755 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6756 PERM_NEW_FILE, &unixmode);
6757 if (!NT_STATUS_IS_OK(status)) {
6758 return status;
6761 #if defined(HAVE_MAKEDEV)
6762 dev = makedev(dev_major, dev_minor);
6763 #endif
6765 switch (file_type) {
6766 #if defined(S_IFIFO)
6767 case UNIX_TYPE_FIFO:
6768 unixmode |= S_IFIFO;
6769 break;
6770 #endif
6771 #if defined(S_IFSOCK)
6772 case UNIX_TYPE_SOCKET:
6773 unixmode |= S_IFSOCK;
6774 break;
6775 #endif
6776 #if defined(S_IFCHR)
6777 case UNIX_TYPE_CHARDEV:
6778 unixmode |= S_IFCHR;
6779 break;
6780 #endif
6781 #if defined(S_IFBLK)
6782 case UNIX_TYPE_BLKDEV:
6783 unixmode |= S_IFBLK;
6784 break;
6785 #endif
6786 default:
6787 return NT_STATUS_INVALID_PARAMETER;
6790 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6791 "%.0f mode 0%o for file %s\n", (double)dev,
6792 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6794 /* Ok - do the mknod. */
6795 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6796 return map_nt_error_from_unix(errno);
6799 /* If any of the other "set" calls fail we
6800 * don't want to end up with a half-constructed mknod.
6803 if (lp_inherit_perms(SNUM(conn))) {
6804 char *parent;
6805 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6806 &parent, NULL)) {
6807 return NT_STATUS_NO_MEMORY;
6809 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6810 unixmode);
6811 TALLOC_FREE(parent);
6814 return NT_STATUS_OK;
6817 /****************************************************************************
6818 Deal with SMB_SET_FILE_UNIX_BASIC.
6819 ****************************************************************************/
6821 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6822 struct smb_request *req,
6823 const char *pdata,
6824 int total_data,
6825 files_struct *fsp,
6826 const struct smb_filename *smb_fname)
6828 struct smb_file_time ft;
6829 uint32 raw_unixmode;
6830 mode_t unixmode;
6831 SMB_OFF_T size = 0;
6832 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6833 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6834 NTSTATUS status = NT_STATUS_OK;
6835 bool delete_on_fail = False;
6836 enum perm_type ptype;
6837 files_struct *all_fsps = NULL;
6838 bool modify_mtime = true;
6839 struct file_id id;
6840 struct smb_filename *smb_fname_tmp = NULL;
6841 SMB_STRUCT_STAT sbuf;
6843 ZERO_STRUCT(ft);
6845 if (total_data < 100) {
6846 return NT_STATUS_INVALID_PARAMETER;
6849 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6850 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6851 size=IVAL(pdata,0); /* first 8 Bytes are size */
6852 #ifdef LARGE_SMB_OFF_T
6853 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6854 #else /* LARGE_SMB_OFF_T */
6855 if (IVAL(pdata,4) != 0) {
6856 /* more than 32 bits? */
6857 return NT_STATUS_INVALID_PARAMETER;
6859 #endif /* LARGE_SMB_OFF_T */
6862 ft.atime = interpret_long_date(pdata+24); /* access_time */
6863 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6864 set_owner = (uid_t)IVAL(pdata,40);
6865 set_grp = (gid_t)IVAL(pdata,48);
6866 raw_unixmode = IVAL(pdata,84);
6868 if (VALID_STAT(smb_fname->st)) {
6869 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6870 ptype = PERM_EXISTING_DIR;
6871 } else {
6872 ptype = PERM_EXISTING_FILE;
6874 } else {
6875 ptype = PERM_NEW_FILE;
6878 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6879 ptype, &unixmode);
6880 if (!NT_STATUS_IS_OK(status)) {
6881 return status;
6884 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6885 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6886 smb_fname_str_dbg(smb_fname), (double)size,
6887 (unsigned int)set_owner, (unsigned int)set_grp,
6888 (int)raw_unixmode));
6890 sbuf = smb_fname->st;
6892 if (!VALID_STAT(sbuf)) {
6894 * The only valid use of this is to create character and block
6895 * devices, and named pipes. This is deprecated (IMHO) and
6896 * a new info level should be used for mknod. JRA.
6899 status = smb_unix_mknod(conn,
6900 pdata,
6901 total_data,
6902 smb_fname);
6903 if (!NT_STATUS_IS_OK(status)) {
6904 return status;
6907 status = copy_smb_filename(talloc_tos(), smb_fname,
6908 &smb_fname_tmp);
6909 if (!NT_STATUS_IS_OK(status)) {
6910 return status;
6913 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6914 status = map_nt_error_from_unix(errno);
6915 TALLOC_FREE(smb_fname_tmp);
6916 SMB_VFS_UNLINK(conn, smb_fname);
6917 return status;
6920 sbuf = smb_fname_tmp->st;
6921 smb_fname = smb_fname_tmp;
6923 /* Ensure we don't try and change anything else. */
6924 raw_unixmode = SMB_MODE_NO_CHANGE;
6925 size = get_file_size_stat(&sbuf);
6926 ft.atime = sbuf.st_ex_atime;
6927 ft.mtime = sbuf.st_ex_mtime;
6929 * We continue here as we might want to change the
6930 * owner uid/gid.
6932 delete_on_fail = True;
6935 #if 1
6936 /* Horrible backwards compatibility hack as an old server bug
6937 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6938 * */
6940 if (!size) {
6941 size = get_file_size_stat(&sbuf);
6943 #endif
6946 * Deal with the UNIX specific mode set.
6949 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6950 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6951 "setting mode 0%o for file %s\n",
6952 (unsigned int)unixmode,
6953 smb_fname_str_dbg(smb_fname)));
6954 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6955 return map_nt_error_from_unix(errno);
6960 * Deal with the UNIX specific uid set.
6963 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6964 (sbuf.st_ex_uid != set_owner)) {
6965 int ret;
6967 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6968 "changing owner %u for path %s\n",
6969 (unsigned int)set_owner,
6970 smb_fname_str_dbg(smb_fname)));
6972 if (S_ISLNK(sbuf.st_ex_mode)) {
6973 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6974 set_owner, (gid_t)-1);
6975 } else {
6976 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6977 set_owner, (gid_t)-1);
6980 if (ret != 0) {
6981 status = map_nt_error_from_unix(errno);
6982 if (delete_on_fail) {
6983 SMB_VFS_UNLINK(conn, smb_fname);
6985 return status;
6990 * Deal with the UNIX specific gid set.
6993 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6994 (sbuf.st_ex_gid != set_grp)) {
6995 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6996 "changing group %u for file %s\n",
6997 (unsigned int)set_owner,
6998 smb_fname_str_dbg(smb_fname)));
6999 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7000 set_grp) != 0) {
7001 status = map_nt_error_from_unix(errno);
7002 if (delete_on_fail) {
7003 SMB_VFS_UNLINK(conn, smb_fname);
7005 return status;
7009 /* Deal with any size changes. */
7011 status = smb_set_file_size(conn, req,
7012 fsp,
7013 smb_fname,
7014 &sbuf,
7015 size,
7016 false);
7017 if (!NT_STATUS_IS_OK(status)) {
7018 return status;
7021 /* Deal with any time changes. */
7022 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7023 /* No change, don't cancel anything. */
7024 return status;
7027 id = vfs_file_id_from_sbuf(conn, &sbuf);
7028 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7029 all_fsps = file_find_di_next(all_fsps)) {
7031 * We're setting the time explicitly for UNIX.
7032 * Cancel any pending changes over all handles.
7034 all_fsps->update_write_time_on_close = false;
7035 TALLOC_FREE(all_fsps->update_write_time_event);
7039 * Override the "setting_write_time"
7040 * parameter here as it almost does what
7041 * we need. Just remember if we modified
7042 * mtime and send the notify ourselves.
7044 if (null_timespec(ft.mtime)) {
7045 modify_mtime = false;
7048 status = smb_set_file_time(conn,
7049 fsp,
7050 smb_fname,
7051 &ft,
7052 false);
7053 if (modify_mtime) {
7054 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7055 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7057 return status;
7060 /****************************************************************************
7061 Deal with SMB_SET_FILE_UNIX_INFO2.
7062 ****************************************************************************/
7064 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7065 struct smb_request *req,
7066 const char *pdata,
7067 int total_data,
7068 files_struct *fsp,
7069 const struct smb_filename *smb_fname)
7071 NTSTATUS status;
7072 uint32 smb_fflags;
7073 uint32 smb_fmask;
7075 if (total_data < 116) {
7076 return NT_STATUS_INVALID_PARAMETER;
7079 /* Start by setting all the fields that are common between UNIX_BASIC
7080 * and UNIX_INFO2.
7082 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7083 fsp, smb_fname);
7084 if (!NT_STATUS_IS_OK(status)) {
7085 return status;
7088 smb_fflags = IVAL(pdata, 108);
7089 smb_fmask = IVAL(pdata, 112);
7091 /* NB: We should only attempt to alter the file flags if the client
7092 * sends a non-zero mask.
7094 if (smb_fmask != 0) {
7095 int stat_fflags = 0;
7097 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7098 smb_fmask, &stat_fflags)) {
7099 /* Client asked to alter a flag we don't understand. */
7100 return NT_STATUS_INVALID_PARAMETER;
7103 if (fsp && fsp->fh->fd != -1) {
7104 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7105 return NT_STATUS_NOT_SUPPORTED;
7106 } else {
7107 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7108 stat_fflags) != 0) {
7109 return map_nt_error_from_unix(errno);
7114 /* XXX: need to add support for changing the create_time here. You
7115 * can do this for paths on Darwin with setattrlist(2). The right way
7116 * to hook this up is probably by extending the VFS utimes interface.
7119 return NT_STATUS_OK;
7122 /****************************************************************************
7123 Create a directory with POSIX semantics.
7124 ****************************************************************************/
7126 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7127 struct smb_request *req,
7128 char **ppdata,
7129 int total_data,
7130 struct smb_filename *smb_fname,
7131 int *pdata_return_size)
7133 NTSTATUS status = NT_STATUS_OK;
7134 uint32 raw_unixmode = 0;
7135 uint32 mod_unixmode = 0;
7136 mode_t unixmode = (mode_t)0;
7137 files_struct *fsp = NULL;
7138 uint16 info_level_return = 0;
7139 int info;
7140 char *pdata = *ppdata;
7142 if (total_data < 18) {
7143 return NT_STATUS_INVALID_PARAMETER;
7146 raw_unixmode = IVAL(pdata,8);
7147 /* Next 4 bytes are not yet defined. */
7149 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7150 PERM_NEW_DIR, &unixmode);
7151 if (!NT_STATUS_IS_OK(status)) {
7152 return status;
7155 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7157 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7158 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7160 status = SMB_VFS_CREATE_FILE(
7161 conn, /* conn */
7162 req, /* req */
7163 0, /* root_dir_fid */
7164 smb_fname, /* fname */
7165 FILE_READ_ATTRIBUTES, /* access_mask */
7166 FILE_SHARE_NONE, /* share_access */
7167 FILE_CREATE, /* create_disposition*/
7168 FILE_DIRECTORY_FILE, /* create_options */
7169 mod_unixmode, /* file_attributes */
7170 0, /* oplock_request */
7171 0, /* allocation_size */
7172 0, /* private_flags */
7173 NULL, /* sd */
7174 NULL, /* ea_list */
7175 &fsp, /* result */
7176 &info); /* pinfo */
7178 if (NT_STATUS_IS_OK(status)) {
7179 close_file(req, fsp, NORMAL_CLOSE);
7182 info_level_return = SVAL(pdata,16);
7184 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7185 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7186 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7187 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7188 } else {
7189 *pdata_return_size = 12;
7192 /* Realloc the data size */
7193 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7194 if (*ppdata == NULL) {
7195 *pdata_return_size = 0;
7196 return NT_STATUS_NO_MEMORY;
7198 pdata = *ppdata;
7200 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7201 SSVAL(pdata,2,0); /* No fnum. */
7202 SIVAL(pdata,4,info); /* Was directory created. */
7204 switch (info_level_return) {
7205 case SMB_QUERY_FILE_UNIX_BASIC:
7206 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7207 SSVAL(pdata,10,0); /* Padding. */
7208 store_file_unix_basic(conn, pdata + 12, fsp,
7209 &smb_fname->st);
7210 break;
7211 case SMB_QUERY_FILE_UNIX_INFO2:
7212 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7213 SSVAL(pdata,10,0); /* Padding. */
7214 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7215 &smb_fname->st);
7216 break;
7217 default:
7218 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7219 SSVAL(pdata,10,0); /* Padding. */
7220 break;
7223 return status;
7226 /****************************************************************************
7227 Open/Create a file with POSIX semantics.
7228 ****************************************************************************/
7230 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7231 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7233 static NTSTATUS smb_posix_open(connection_struct *conn,
7234 struct smb_request *req,
7235 char **ppdata,
7236 int total_data,
7237 struct smb_filename *smb_fname,
7238 int *pdata_return_size)
7240 bool extended_oplock_granted = False;
7241 char *pdata = *ppdata;
7242 uint32 flags = 0;
7243 uint32 wire_open_mode = 0;
7244 uint32 raw_unixmode = 0;
7245 uint32 mod_unixmode = 0;
7246 uint32 create_disp = 0;
7247 uint32 access_mask = 0;
7248 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7249 NTSTATUS status = NT_STATUS_OK;
7250 mode_t unixmode = (mode_t)0;
7251 files_struct *fsp = NULL;
7252 int oplock_request = 0;
7253 int info = 0;
7254 uint16 info_level_return = 0;
7256 if (total_data < 18) {
7257 return NT_STATUS_INVALID_PARAMETER;
7260 flags = IVAL(pdata,0);
7261 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7262 if (oplock_request) {
7263 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7266 wire_open_mode = IVAL(pdata,4);
7268 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7269 return smb_posix_mkdir(conn, req,
7270 ppdata,
7271 total_data,
7272 smb_fname,
7273 pdata_return_size);
7276 switch (wire_open_mode & SMB_ACCMODE) {
7277 case SMB_O_RDONLY:
7278 access_mask = SMB_O_RDONLY_MAPPING;
7279 break;
7280 case SMB_O_WRONLY:
7281 access_mask = SMB_O_WRONLY_MAPPING;
7282 break;
7283 case SMB_O_RDWR:
7284 access_mask = (SMB_O_RDONLY_MAPPING|
7285 SMB_O_WRONLY_MAPPING);
7286 break;
7287 default:
7288 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7289 (unsigned int)wire_open_mode ));
7290 return NT_STATUS_INVALID_PARAMETER;
7293 wire_open_mode &= ~SMB_ACCMODE;
7295 /* First take care of O_CREAT|O_EXCL interactions. */
7296 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7297 case (SMB_O_CREAT | SMB_O_EXCL):
7298 /* File exists fail. File not exist create. */
7299 create_disp = FILE_CREATE;
7300 break;
7301 case SMB_O_CREAT:
7302 /* File exists open. File not exist create. */
7303 create_disp = FILE_OPEN_IF;
7304 break;
7305 case 0:
7306 /* File exists open. File not exist fail. */
7307 create_disp = FILE_OPEN;
7308 break;
7309 case SMB_O_EXCL:
7310 /* O_EXCL on its own without O_CREAT is undefined. */
7311 default:
7312 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7313 (unsigned int)wire_open_mode ));
7314 return NT_STATUS_INVALID_PARAMETER;
7317 /* Next factor in the effects of O_TRUNC. */
7318 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7320 if (wire_open_mode & SMB_O_TRUNC) {
7321 switch (create_disp) {
7322 case FILE_CREATE:
7323 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7324 /* Leave create_disp alone as
7325 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7327 /* File exists fail. File not exist create. */
7328 break;
7329 case FILE_OPEN_IF:
7330 /* SMB_O_CREAT | SMB_O_TRUNC */
7331 /* File exists overwrite. File not exist create. */
7332 create_disp = FILE_OVERWRITE_IF;
7333 break;
7334 case FILE_OPEN:
7335 /* SMB_O_TRUNC */
7336 /* File exists overwrite. File not exist fail. */
7337 create_disp = FILE_OVERWRITE;
7338 break;
7339 default:
7340 /* Cannot get here. */
7341 smb_panic("smb_posix_open: logic error");
7342 return NT_STATUS_INVALID_PARAMETER;
7346 raw_unixmode = IVAL(pdata,8);
7347 /* Next 4 bytes are not yet defined. */
7349 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7350 (VALID_STAT(smb_fname->st) ?
7351 PERM_EXISTING_FILE : PERM_NEW_FILE),
7352 &unixmode);
7354 if (!NT_STATUS_IS_OK(status)) {
7355 return status;
7358 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7360 if (wire_open_mode & SMB_O_SYNC) {
7361 create_options |= FILE_WRITE_THROUGH;
7363 if (wire_open_mode & SMB_O_APPEND) {
7364 access_mask |= FILE_APPEND_DATA;
7366 if (wire_open_mode & SMB_O_DIRECT) {
7367 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7370 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7371 VALID_STAT_OF_DIR(smb_fname->st)) {
7372 if (access_mask != SMB_O_RDONLY_MAPPING) {
7373 return NT_STATUS_FILE_IS_A_DIRECTORY;
7375 create_options &= ~FILE_NON_DIRECTORY_FILE;
7376 create_options |= FILE_DIRECTORY_FILE;
7379 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7380 smb_fname_str_dbg(smb_fname),
7381 (unsigned int)wire_open_mode,
7382 (unsigned int)unixmode ));
7384 status = SMB_VFS_CREATE_FILE(
7385 conn, /* conn */
7386 req, /* req */
7387 0, /* root_dir_fid */
7388 smb_fname, /* fname */
7389 access_mask, /* access_mask */
7390 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7391 FILE_SHARE_DELETE),
7392 create_disp, /* create_disposition*/
7393 create_options, /* create_options */
7394 mod_unixmode, /* file_attributes */
7395 oplock_request, /* oplock_request */
7396 0, /* allocation_size */
7397 0, /* private_flags */
7398 NULL, /* sd */
7399 NULL, /* ea_list */
7400 &fsp, /* result */
7401 &info); /* pinfo */
7403 if (!NT_STATUS_IS_OK(status)) {
7404 return status;
7407 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7408 extended_oplock_granted = True;
7411 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7412 extended_oplock_granted = True;
7415 info_level_return = SVAL(pdata,16);
7417 /* Allocate the correct return size. */
7419 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7420 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7421 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7422 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7423 } else {
7424 *pdata_return_size = 12;
7427 /* Realloc the data size */
7428 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7429 if (*ppdata == NULL) {
7430 close_file(req, fsp, ERROR_CLOSE);
7431 *pdata_return_size = 0;
7432 return NT_STATUS_NO_MEMORY;
7434 pdata = *ppdata;
7436 if (extended_oplock_granted) {
7437 if (flags & REQUEST_BATCH_OPLOCK) {
7438 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7439 } else {
7440 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7442 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7443 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7444 } else {
7445 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7448 SSVAL(pdata,2,fsp->fnum);
7449 SIVAL(pdata,4,info); /* Was file created etc. */
7451 switch (info_level_return) {
7452 case SMB_QUERY_FILE_UNIX_BASIC:
7453 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7454 SSVAL(pdata,10,0); /* padding. */
7455 store_file_unix_basic(conn, pdata + 12, fsp,
7456 &smb_fname->st);
7457 break;
7458 case SMB_QUERY_FILE_UNIX_INFO2:
7459 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7460 SSVAL(pdata,10,0); /* padding. */
7461 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7462 &smb_fname->st);
7463 break;
7464 default:
7465 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7466 SSVAL(pdata,10,0); /* padding. */
7467 break;
7469 return NT_STATUS_OK;
7472 /****************************************************************************
7473 Delete a file with POSIX semantics.
7474 ****************************************************************************/
7476 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7477 struct smb_request *req,
7478 const char *pdata,
7479 int total_data,
7480 struct smb_filename *smb_fname)
7482 NTSTATUS status = NT_STATUS_OK;
7483 files_struct *fsp = NULL;
7484 uint16 flags = 0;
7485 char del = 1;
7486 int info = 0;
7487 int create_options = 0;
7488 int i;
7489 struct share_mode_lock *lck = NULL;
7491 if (total_data < 2) {
7492 return NT_STATUS_INVALID_PARAMETER;
7495 flags = SVAL(pdata,0);
7497 if (!VALID_STAT(smb_fname->st)) {
7498 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7501 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7502 !VALID_STAT_OF_DIR(smb_fname->st)) {
7503 return NT_STATUS_NOT_A_DIRECTORY;
7506 DEBUG(10,("smb_posix_unlink: %s %s\n",
7507 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7508 smb_fname_str_dbg(smb_fname)));
7510 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7511 create_options |= FILE_DIRECTORY_FILE;
7514 status = SMB_VFS_CREATE_FILE(
7515 conn, /* conn */
7516 req, /* req */
7517 0, /* root_dir_fid */
7518 smb_fname, /* fname */
7519 DELETE_ACCESS, /* access_mask */
7520 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7521 FILE_SHARE_DELETE),
7522 FILE_OPEN, /* create_disposition*/
7523 create_options, /* create_options */
7524 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7525 0, /* oplock_request */
7526 0, /* allocation_size */
7527 0, /* private_flags */
7528 NULL, /* sd */
7529 NULL, /* ea_list */
7530 &fsp, /* result */
7531 &info); /* pinfo */
7533 if (!NT_STATUS_IS_OK(status)) {
7534 return status;
7538 * Don't lie to client. If we can't really delete due to
7539 * non-POSIX opens return SHARING_VIOLATION.
7542 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7543 NULL);
7544 if (lck == NULL) {
7545 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7546 "lock for file %s\n", fsp_str_dbg(fsp)));
7547 close_file(req, fsp, NORMAL_CLOSE);
7548 return NT_STATUS_INVALID_PARAMETER;
7552 * See if others still have the file open. If this is the case, then
7553 * don't delete. If all opens are POSIX delete we can set the delete
7554 * on close disposition.
7556 for (i=0; i<lck->num_share_modes; i++) {
7557 struct share_mode_entry *e = &lck->share_modes[i];
7558 if (is_valid_share_mode_entry(e)) {
7559 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7560 continue;
7562 /* Fail with sharing violation. */
7563 close_file(req, fsp, NORMAL_CLOSE);
7564 TALLOC_FREE(lck);
7565 return NT_STATUS_SHARING_VIOLATION;
7570 * Set the delete on close.
7572 status = smb_set_file_disposition_info(conn,
7573 &del,
7575 fsp,
7576 smb_fname);
7578 if (!NT_STATUS_IS_OK(status)) {
7579 close_file(req, fsp, NORMAL_CLOSE);
7580 TALLOC_FREE(lck);
7581 return status;
7583 TALLOC_FREE(lck);
7584 return close_file(req, fsp, NORMAL_CLOSE);
7587 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7588 struct smb_request *req,
7589 TALLOC_CTX *mem_ctx,
7590 uint16_t info_level,
7591 files_struct *fsp,
7592 struct smb_filename *smb_fname,
7593 char **ppdata, int total_data,
7594 int *ret_data_size)
7596 char *pdata = *ppdata;
7597 NTSTATUS status = NT_STATUS_OK;
7598 int data_return_size = 0;
7600 *ret_data_size = 0;
7602 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7603 return NT_STATUS_INVALID_LEVEL;
7606 if (!CAN_WRITE(conn)) {
7607 /* Allow POSIX opens. The open path will deny
7608 * any non-readonly opens. */
7609 if (info_level != SMB_POSIX_PATH_OPEN) {
7610 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7614 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7615 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7616 fsp ? fsp->fnum : -1, info_level, total_data));
7618 switch (info_level) {
7620 case SMB_INFO_STANDARD:
7622 status = smb_set_info_standard(conn,
7623 pdata,
7624 total_data,
7625 fsp,
7626 smb_fname);
7627 break;
7630 case SMB_INFO_SET_EA:
7632 status = smb_info_set_ea(conn,
7633 pdata,
7634 total_data,
7635 fsp,
7636 smb_fname);
7637 break;
7640 case SMB_SET_FILE_BASIC_INFO:
7641 case SMB_FILE_BASIC_INFORMATION:
7643 status = smb_set_file_basic_info(conn,
7644 pdata,
7645 total_data,
7646 fsp,
7647 smb_fname);
7648 break;
7651 case SMB_FILE_ALLOCATION_INFORMATION:
7652 case SMB_SET_FILE_ALLOCATION_INFO:
7654 status = smb_set_file_allocation_info(conn, req,
7655 pdata,
7656 total_data,
7657 fsp,
7658 smb_fname);
7659 break;
7662 case SMB_FILE_END_OF_FILE_INFORMATION:
7663 case SMB_SET_FILE_END_OF_FILE_INFO:
7666 * XP/Win7 both fail after the createfile with
7667 * SMB_SET_FILE_END_OF_FILE_INFO but not
7668 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7669 * The level is known here, so pass it down
7670 * appropriately.
7672 bool should_fail =
7673 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7675 status = smb_set_file_end_of_file_info(conn, req,
7676 pdata,
7677 total_data,
7678 fsp,
7679 smb_fname,
7680 should_fail);
7681 break;
7684 case SMB_FILE_DISPOSITION_INFORMATION:
7685 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7687 #if 0
7688 /* JRA - We used to just ignore this on a path ?
7689 * Shouldn't this be invalid level on a pathname
7690 * based call ?
7692 if (tran_call != TRANSACT2_SETFILEINFO) {
7693 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7695 #endif
7696 status = smb_set_file_disposition_info(conn,
7697 pdata,
7698 total_data,
7699 fsp,
7700 smb_fname);
7701 break;
7704 case SMB_FILE_POSITION_INFORMATION:
7706 status = smb_file_position_information(conn,
7707 pdata,
7708 total_data,
7709 fsp);
7710 break;
7713 case SMB_FILE_FULL_EA_INFORMATION:
7715 status = smb_set_file_full_ea_info(conn,
7716 pdata,
7717 total_data,
7718 fsp);
7719 break;
7722 /* From tridge Samba4 :
7723 * MODE_INFORMATION in setfileinfo (I have no
7724 * idea what "mode information" on a file is - it takes a value of 0,
7725 * 2, 4 or 6. What could it be?).
7728 case SMB_FILE_MODE_INFORMATION:
7730 status = smb_file_mode_information(conn,
7731 pdata,
7732 total_data);
7733 break;
7737 * CIFS UNIX extensions.
7740 case SMB_SET_FILE_UNIX_BASIC:
7742 status = smb_set_file_unix_basic(conn, req,
7743 pdata,
7744 total_data,
7745 fsp,
7746 smb_fname);
7747 break;
7750 case SMB_SET_FILE_UNIX_INFO2:
7752 status = smb_set_file_unix_info2(conn, req,
7753 pdata,
7754 total_data,
7755 fsp,
7756 smb_fname);
7757 break;
7760 case SMB_SET_FILE_UNIX_LINK:
7762 if (fsp) {
7763 /* We must have a pathname for this. */
7764 return NT_STATUS_INVALID_LEVEL;
7766 status = smb_set_file_unix_link(conn, req, pdata,
7767 total_data, smb_fname);
7768 break;
7771 case SMB_SET_FILE_UNIX_HLINK:
7773 if (fsp) {
7774 /* We must have a pathname for this. */
7775 return NT_STATUS_INVALID_LEVEL;
7777 status = smb_set_file_unix_hlink(conn, req,
7778 pdata, total_data,
7779 smb_fname);
7780 break;
7783 case SMB_FILE_RENAME_INFORMATION:
7785 status = smb_file_rename_information(conn, req,
7786 pdata, total_data,
7787 fsp, smb_fname);
7788 break;
7791 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7793 /* SMB2 rename information. */
7794 status = smb2_file_rename_information(conn, req,
7795 pdata, total_data,
7796 fsp, smb_fname);
7797 break;
7800 case SMB_FILE_LINK_INFORMATION:
7802 status = smb_file_link_information(conn, req,
7803 pdata, total_data,
7804 fsp, smb_fname);
7805 break;
7808 #if defined(HAVE_POSIX_ACLS)
7809 case SMB_SET_POSIX_ACL:
7811 status = smb_set_posix_acl(conn,
7812 pdata,
7813 total_data,
7814 fsp,
7815 smb_fname);
7816 break;
7818 #endif
7820 case SMB_SET_POSIX_LOCK:
7822 if (!fsp) {
7823 return NT_STATUS_INVALID_LEVEL;
7825 status = smb_set_posix_lock(conn, req,
7826 pdata, total_data, fsp);
7827 break;
7830 case SMB_POSIX_PATH_OPEN:
7832 if (fsp) {
7833 /* We must have a pathname for this. */
7834 return NT_STATUS_INVALID_LEVEL;
7837 status = smb_posix_open(conn, req,
7838 ppdata,
7839 total_data,
7840 smb_fname,
7841 &data_return_size);
7842 break;
7845 case SMB_POSIX_PATH_UNLINK:
7847 if (fsp) {
7848 /* We must have a pathname for this. */
7849 return NT_STATUS_INVALID_LEVEL;
7852 status = smb_posix_unlink(conn, req,
7853 pdata,
7854 total_data,
7855 smb_fname);
7856 break;
7859 default:
7860 return NT_STATUS_INVALID_LEVEL;
7863 if (!NT_STATUS_IS_OK(status)) {
7864 return status;
7867 *ret_data_size = data_return_size;
7868 return NT_STATUS_OK;
7871 /****************************************************************************
7872 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7873 ****************************************************************************/
7875 static void call_trans2setfilepathinfo(connection_struct *conn,
7876 struct smb_request *req,
7877 unsigned int tran_call,
7878 char **pparams, int total_params,
7879 char **ppdata, int total_data,
7880 unsigned int max_data_bytes)
7882 char *params = *pparams;
7883 char *pdata = *ppdata;
7884 uint16 info_level;
7885 struct smb_filename *smb_fname = NULL;
7886 files_struct *fsp = NULL;
7887 NTSTATUS status = NT_STATUS_OK;
7888 int data_return_size = 0;
7890 if (!params) {
7891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7892 return;
7895 if (tran_call == TRANSACT2_SETFILEINFO) {
7896 if (total_params < 4) {
7897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7898 return;
7901 fsp = file_fsp(req, SVAL(params,0));
7902 /* Basic check for non-null fsp. */
7903 if (!check_fsp_open(conn, req, fsp)) {
7904 return;
7906 info_level = SVAL(params,2);
7908 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7909 &smb_fname);
7910 if (!NT_STATUS_IS_OK(status)) {
7911 reply_nterror(req, status);
7912 return;
7915 if(fsp->fh->fd == -1) {
7917 * This is actually a SETFILEINFO on a directory
7918 * handle (returned from an NT SMB). NT5.0 seems
7919 * to do this call. JRA.
7921 if (INFO_LEVEL_IS_UNIX(info_level)) {
7922 /* Always do lstat for UNIX calls. */
7923 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7924 DEBUG(3,("call_trans2setfilepathinfo: "
7925 "SMB_VFS_LSTAT of %s failed "
7926 "(%s)\n",
7927 smb_fname_str_dbg(smb_fname),
7928 strerror(errno)));
7929 reply_nterror(req, map_nt_error_from_unix(errno));
7930 return;
7932 } else {
7933 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7934 DEBUG(3,("call_trans2setfilepathinfo: "
7935 "fileinfo of %s failed (%s)\n",
7936 smb_fname_str_dbg(smb_fname),
7937 strerror(errno)));
7938 reply_nterror(req, map_nt_error_from_unix(errno));
7939 return;
7942 } else if (fsp->print_file) {
7944 * Doing a DELETE_ON_CLOSE should cancel a print job.
7946 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7947 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7949 DEBUG(3,("call_trans2setfilepathinfo: "
7950 "Cancelling print job (%s)\n",
7951 fsp_str_dbg(fsp)));
7953 SSVAL(params,0,0);
7954 send_trans2_replies(conn, req, params, 2,
7955 *ppdata, 0,
7956 max_data_bytes);
7957 return;
7958 } else {
7959 reply_nterror(req,
7960 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7961 return;
7963 } else {
7965 * Original code - this is an open file.
7967 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7968 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7969 "of fnum %d failed (%s)\n", fsp->fnum,
7970 strerror(errno)));
7971 reply_nterror(req, map_nt_error_from_unix(errno));
7972 return;
7975 } else {
7976 char *fname = NULL;
7978 /* set path info */
7979 if (total_params < 7) {
7980 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7981 return;
7984 info_level = SVAL(params,0);
7985 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7986 total_params - 6, STR_TERMINATE,
7987 &status);
7988 if (!NT_STATUS_IS_OK(status)) {
7989 reply_nterror(req, status);
7990 return;
7993 status = filename_convert(req, conn,
7994 req->flags2 & FLAGS2_DFS_PATHNAMES,
7995 fname,
7997 NULL,
7998 &smb_fname);
7999 if (!NT_STATUS_IS_OK(status)) {
8000 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8001 reply_botherror(req,
8002 NT_STATUS_PATH_NOT_COVERED,
8003 ERRSRV, ERRbadpath);
8004 return;
8006 reply_nterror(req, status);
8007 return;
8010 if (INFO_LEVEL_IS_UNIX(info_level)) {
8012 * For CIFS UNIX extensions the target name may not exist.
8015 /* Always do lstat for UNIX calls. */
8016 SMB_VFS_LSTAT(conn, smb_fname);
8018 } else if (!VALID_STAT(smb_fname->st) &&
8019 SMB_VFS_STAT(conn, smb_fname)) {
8020 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8021 "%s failed (%s)\n",
8022 smb_fname_str_dbg(smb_fname),
8023 strerror(errno)));
8024 reply_nterror(req, map_nt_error_from_unix(errno));
8025 return;
8029 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8030 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8031 fsp ? fsp->fnum : -1, info_level,total_data));
8033 /* Realloc the parameter size */
8034 *pparams = (char *)SMB_REALLOC(*pparams,2);
8035 if (*pparams == NULL) {
8036 reply_nterror(req, NT_STATUS_NO_MEMORY);
8037 return;
8039 params = *pparams;
8041 SSVAL(params,0,0);
8043 status = smbd_do_setfilepathinfo(conn, req, req,
8044 info_level,
8045 fsp,
8046 smb_fname,
8047 ppdata, total_data,
8048 &data_return_size);
8049 if (!NT_STATUS_IS_OK(status)) {
8050 if (open_was_deferred(req->mid)) {
8051 /* We have re-scheduled this call. */
8052 return;
8054 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8055 /* We have re-scheduled this call. */
8056 return;
8058 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8059 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8060 ERRSRV, ERRbadpath);
8061 return;
8063 if (info_level == SMB_POSIX_PATH_OPEN) {
8064 reply_openerror(req, status);
8065 return;
8068 reply_nterror(req, status);
8069 return;
8072 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8073 max_data_bytes);
8075 return;
8078 /****************************************************************************
8079 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8080 ****************************************************************************/
8082 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8083 char **pparams, int total_params,
8084 char **ppdata, int total_data,
8085 unsigned int max_data_bytes)
8087 struct smb_filename *smb_dname = NULL;
8088 char *params = *pparams;
8089 char *pdata = *ppdata;
8090 char *directory = NULL;
8091 NTSTATUS status = NT_STATUS_OK;
8092 struct ea_list *ea_list = NULL;
8093 TALLOC_CTX *ctx = talloc_tos();
8095 if (!CAN_WRITE(conn)) {
8096 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8097 return;
8100 if (total_params < 5) {
8101 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8102 return;
8105 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8106 total_params - 4, STR_TERMINATE,
8107 &status);
8108 if (!NT_STATUS_IS_OK(status)) {
8109 reply_nterror(req, status);
8110 return;
8113 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8115 status = filename_convert(ctx,
8116 conn,
8117 req->flags2 & FLAGS2_DFS_PATHNAMES,
8118 directory,
8120 NULL,
8121 &smb_dname);
8123 if (!NT_STATUS_IS_OK(status)) {
8124 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8125 reply_botherror(req,
8126 NT_STATUS_PATH_NOT_COVERED,
8127 ERRSRV, ERRbadpath);
8128 return;
8130 reply_nterror(req, status);
8131 return;
8135 * OS/2 workplace shell seems to send SET_EA requests of "null"
8136 * length (4 bytes containing IVAL 4).
8137 * They seem to have no effect. Bug #3212. JRA.
8140 if (total_data && (total_data != 4)) {
8141 /* Any data in this call is an EA list. */
8142 if (total_data < 10) {
8143 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8144 goto out;
8147 if (IVAL(pdata,0) > total_data) {
8148 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8149 IVAL(pdata,0), (unsigned int)total_data));
8150 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8151 goto out;
8154 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8155 total_data - 4);
8156 if (!ea_list) {
8157 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8158 goto out;
8161 if (!lp_ea_support(SNUM(conn))) {
8162 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8163 goto out;
8166 /* If total_data == 4 Windows doesn't care what values
8167 * are placed in that field, it just ignores them.
8168 * The System i QNTC IBM SMB client puts bad values here,
8169 * so ignore them. */
8171 status = create_directory(conn, req, smb_dname);
8173 if (!NT_STATUS_IS_OK(status)) {
8174 reply_nterror(req, status);
8175 goto out;
8178 /* Try and set any given EA. */
8179 if (ea_list) {
8180 status = set_ea(conn, NULL, smb_dname, ea_list);
8181 if (!NT_STATUS_IS_OK(status)) {
8182 reply_nterror(req, status);
8183 goto out;
8187 /* Realloc the parameter and data sizes */
8188 *pparams = (char *)SMB_REALLOC(*pparams,2);
8189 if(*pparams == NULL) {
8190 reply_nterror(req, NT_STATUS_NO_MEMORY);
8191 goto out;
8193 params = *pparams;
8195 SSVAL(params,0,0);
8197 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8199 out:
8200 TALLOC_FREE(smb_dname);
8201 return;
8204 /****************************************************************************
8205 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8206 We don't actually do this - we just send a null response.
8207 ****************************************************************************/
8209 static void call_trans2findnotifyfirst(connection_struct *conn,
8210 struct smb_request *req,
8211 char **pparams, int total_params,
8212 char **ppdata, int total_data,
8213 unsigned int max_data_bytes)
8215 char *params = *pparams;
8216 uint16 info_level;
8218 if (total_params < 6) {
8219 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8220 return;
8223 info_level = SVAL(params,4);
8224 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8226 switch (info_level) {
8227 case 1:
8228 case 2:
8229 break;
8230 default:
8231 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8232 return;
8235 /* Realloc the parameter and data sizes */
8236 *pparams = (char *)SMB_REALLOC(*pparams,6);
8237 if (*pparams == NULL) {
8238 reply_nterror(req, NT_STATUS_NO_MEMORY);
8239 return;
8241 params = *pparams;
8243 SSVAL(params,0,fnf_handle);
8244 SSVAL(params,2,0); /* No changes */
8245 SSVAL(params,4,0); /* No EA errors */
8247 fnf_handle++;
8249 if(fnf_handle == 0)
8250 fnf_handle = 257;
8252 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8254 return;
8257 /****************************************************************************
8258 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8259 changes). Currently this does nothing.
8260 ****************************************************************************/
8262 static void call_trans2findnotifynext(connection_struct *conn,
8263 struct smb_request *req,
8264 char **pparams, int total_params,
8265 char **ppdata, int total_data,
8266 unsigned int max_data_bytes)
8268 char *params = *pparams;
8270 DEBUG(3,("call_trans2findnotifynext\n"));
8272 /* Realloc the parameter and data sizes */
8273 *pparams = (char *)SMB_REALLOC(*pparams,4);
8274 if (*pparams == NULL) {
8275 reply_nterror(req, NT_STATUS_NO_MEMORY);
8276 return;
8278 params = *pparams;
8280 SSVAL(params,0,0); /* No changes */
8281 SSVAL(params,2,0); /* No EA errors */
8283 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8285 return;
8288 /****************************************************************************
8289 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8290 ****************************************************************************/
8292 static void call_trans2getdfsreferral(connection_struct *conn,
8293 struct smb_request *req,
8294 char **pparams, int total_params,
8295 char **ppdata, int total_data,
8296 unsigned int max_data_bytes)
8298 char *params = *pparams;
8299 char *pathname = NULL;
8300 int reply_size = 0;
8301 int max_referral_level;
8302 NTSTATUS status = NT_STATUS_OK;
8303 TALLOC_CTX *ctx = talloc_tos();
8305 DEBUG(10,("call_trans2getdfsreferral\n"));
8307 if (total_params < 3) {
8308 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8309 return;
8312 max_referral_level = SVAL(params,0);
8314 if(!lp_host_msdfs()) {
8315 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8316 return;
8319 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8320 total_params - 2, STR_TERMINATE);
8321 if (!pathname) {
8322 reply_nterror(req, NT_STATUS_NOT_FOUND);
8323 return;
8325 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8326 ppdata,&status)) < 0) {
8327 reply_nterror(req, status);
8328 return;
8331 SSVAL(req->inbuf, smb_flg2,
8332 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8333 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8335 return;
8338 #define LMCAT_SPL 0x53
8339 #define LMFUNC_GETJOBID 0x60
8341 /****************************************************************************
8342 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8343 ****************************************************************************/
8345 static void call_trans2ioctl(connection_struct *conn,
8346 struct smb_request *req,
8347 char **pparams, int total_params,
8348 char **ppdata, int total_data,
8349 unsigned int max_data_bytes)
8351 char *pdata = *ppdata;
8352 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8354 /* check for an invalid fid before proceeding */
8356 if (!fsp) {
8357 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8358 return;
8361 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8362 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8363 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8364 if (*ppdata == NULL) {
8365 reply_nterror(req, NT_STATUS_NO_MEMORY);
8366 return;
8368 pdata = *ppdata;
8370 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8371 CAN ACCEPT THIS IN UNICODE. JRA. */
8373 /* Job number */
8374 if (fsp->print_file) {
8375 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8376 } else {
8377 SSVAL(pdata, 0, 0);
8379 srvstr_push(pdata, req->flags2, pdata + 2,
8380 global_myname(), 15,
8381 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8382 srvstr_push(pdata, req->flags2, pdata+18,
8383 lp_servicename(SNUM(conn)), 13,
8384 STR_ASCII|STR_TERMINATE); /* Service name */
8385 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8386 max_data_bytes);
8387 return;
8390 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8391 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8394 /****************************************************************************
8395 Reply to a SMBfindclose (stop trans2 directory search).
8396 ****************************************************************************/
8398 void reply_findclose(struct smb_request *req)
8400 int dptr_num;
8401 struct smbd_server_connection *sconn = req->sconn;
8403 START_PROFILE(SMBfindclose);
8405 if (req->wct < 1) {
8406 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8407 END_PROFILE(SMBfindclose);
8408 return;
8411 dptr_num = SVALS(req->vwv+0, 0);
8413 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8415 dptr_close(sconn, &dptr_num);
8417 reply_outbuf(req, 0, 0);
8419 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8421 END_PROFILE(SMBfindclose);
8422 return;
8425 /****************************************************************************
8426 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8427 ****************************************************************************/
8429 void reply_findnclose(struct smb_request *req)
8431 int dptr_num;
8433 START_PROFILE(SMBfindnclose);
8435 if (req->wct < 1) {
8436 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8437 END_PROFILE(SMBfindnclose);
8438 return;
8441 dptr_num = SVAL(req->vwv+0, 0);
8443 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8445 /* We never give out valid handles for a
8446 findnotifyfirst - so any dptr_num is ok here.
8447 Just ignore it. */
8449 reply_outbuf(req, 0, 0);
8451 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8453 END_PROFILE(SMBfindnclose);
8454 return;
8457 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8458 struct trans_state *state)
8460 if (get_Protocol() >= PROTOCOL_NT1) {
8461 req->flags2 |= 0x40; /* IS_LONG_NAME */
8462 SSVAL(req->inbuf,smb_flg2,req->flags2);
8465 if (conn->encrypt_level == Required && !req->encrypted) {
8466 if (state->call != TRANSACT2_QFSINFO &&
8467 state->call != TRANSACT2_SETFSINFO) {
8468 DEBUG(0,("handle_trans2: encryption required "
8469 "with call 0x%x\n",
8470 (unsigned int)state->call));
8471 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8472 return;
8476 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8478 /* Now we must call the relevant TRANS2 function */
8479 switch(state->call) {
8480 case TRANSACT2_OPEN:
8482 START_PROFILE(Trans2_open);
8483 call_trans2open(conn, req,
8484 &state->param, state->total_param,
8485 &state->data, state->total_data,
8486 state->max_data_return);
8487 END_PROFILE(Trans2_open);
8488 break;
8491 case TRANSACT2_FINDFIRST:
8493 START_PROFILE(Trans2_findfirst);
8494 call_trans2findfirst(conn, req,
8495 &state->param, state->total_param,
8496 &state->data, state->total_data,
8497 state->max_data_return);
8498 END_PROFILE(Trans2_findfirst);
8499 break;
8502 case TRANSACT2_FINDNEXT:
8504 START_PROFILE(Trans2_findnext);
8505 call_trans2findnext(conn, req,
8506 &state->param, state->total_param,
8507 &state->data, state->total_data,
8508 state->max_data_return);
8509 END_PROFILE(Trans2_findnext);
8510 break;
8513 case TRANSACT2_QFSINFO:
8515 START_PROFILE(Trans2_qfsinfo);
8516 call_trans2qfsinfo(conn, req,
8517 &state->param, state->total_param,
8518 &state->data, state->total_data,
8519 state->max_data_return);
8520 END_PROFILE(Trans2_qfsinfo);
8521 break;
8524 case TRANSACT2_SETFSINFO:
8526 START_PROFILE(Trans2_setfsinfo);
8527 call_trans2setfsinfo(conn, req,
8528 &state->param, state->total_param,
8529 &state->data, state->total_data,
8530 state->max_data_return);
8531 END_PROFILE(Trans2_setfsinfo);
8532 break;
8535 case TRANSACT2_QPATHINFO:
8536 case TRANSACT2_QFILEINFO:
8538 START_PROFILE(Trans2_qpathinfo);
8539 call_trans2qfilepathinfo(conn, req, state->call,
8540 &state->param, state->total_param,
8541 &state->data, state->total_data,
8542 state->max_data_return);
8543 END_PROFILE(Trans2_qpathinfo);
8544 break;
8547 case TRANSACT2_SETPATHINFO:
8548 case TRANSACT2_SETFILEINFO:
8550 START_PROFILE(Trans2_setpathinfo);
8551 call_trans2setfilepathinfo(conn, req, state->call,
8552 &state->param, state->total_param,
8553 &state->data, state->total_data,
8554 state->max_data_return);
8555 END_PROFILE(Trans2_setpathinfo);
8556 break;
8559 case TRANSACT2_FINDNOTIFYFIRST:
8561 START_PROFILE(Trans2_findnotifyfirst);
8562 call_trans2findnotifyfirst(conn, req,
8563 &state->param, state->total_param,
8564 &state->data, state->total_data,
8565 state->max_data_return);
8566 END_PROFILE(Trans2_findnotifyfirst);
8567 break;
8570 case TRANSACT2_FINDNOTIFYNEXT:
8572 START_PROFILE(Trans2_findnotifynext);
8573 call_trans2findnotifynext(conn, req,
8574 &state->param, state->total_param,
8575 &state->data, state->total_data,
8576 state->max_data_return);
8577 END_PROFILE(Trans2_findnotifynext);
8578 break;
8581 case TRANSACT2_MKDIR:
8583 START_PROFILE(Trans2_mkdir);
8584 call_trans2mkdir(conn, req,
8585 &state->param, state->total_param,
8586 &state->data, state->total_data,
8587 state->max_data_return);
8588 END_PROFILE(Trans2_mkdir);
8589 break;
8592 case TRANSACT2_GET_DFS_REFERRAL:
8594 START_PROFILE(Trans2_get_dfs_referral);
8595 call_trans2getdfsreferral(conn, req,
8596 &state->param, state->total_param,
8597 &state->data, state->total_data,
8598 state->max_data_return);
8599 END_PROFILE(Trans2_get_dfs_referral);
8600 break;
8603 case TRANSACT2_IOCTL:
8605 START_PROFILE(Trans2_ioctl);
8606 call_trans2ioctl(conn, req,
8607 &state->param, state->total_param,
8608 &state->data, state->total_data,
8609 state->max_data_return);
8610 END_PROFILE(Trans2_ioctl);
8611 break;
8614 default:
8615 /* Error in request */
8616 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8617 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8621 /****************************************************************************
8622 Reply to a SMBtrans2.
8623 ****************************************************************************/
8625 void reply_trans2(struct smb_request *req)
8627 connection_struct *conn = req->conn;
8628 unsigned int dsoff;
8629 unsigned int dscnt;
8630 unsigned int psoff;
8631 unsigned int pscnt;
8632 unsigned int tran_call;
8633 struct trans_state *state;
8634 NTSTATUS result;
8636 START_PROFILE(SMBtrans2);
8638 if (req->wct < 14) {
8639 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8640 END_PROFILE(SMBtrans2);
8641 return;
8644 dsoff = SVAL(req->vwv+12, 0);
8645 dscnt = SVAL(req->vwv+11, 0);
8646 psoff = SVAL(req->vwv+10, 0);
8647 pscnt = SVAL(req->vwv+9, 0);
8648 tran_call = SVAL(req->vwv+14, 0);
8650 result = allow_new_trans(conn->pending_trans, req->mid);
8651 if (!NT_STATUS_IS_OK(result)) {
8652 DEBUG(2, ("Got invalid trans2 request: %s\n",
8653 nt_errstr(result)));
8654 reply_nterror(req, result);
8655 END_PROFILE(SMBtrans2);
8656 return;
8659 if (IS_IPC(conn)) {
8660 switch (tran_call) {
8661 /* List the allowed trans2 calls on IPC$ */
8662 case TRANSACT2_OPEN:
8663 case TRANSACT2_GET_DFS_REFERRAL:
8664 case TRANSACT2_QFILEINFO:
8665 case TRANSACT2_QFSINFO:
8666 case TRANSACT2_SETFSINFO:
8667 break;
8668 default:
8669 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8670 END_PROFILE(SMBtrans2);
8671 return;
8675 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8676 DEBUG(0, ("talloc failed\n"));
8677 reply_nterror(req, NT_STATUS_NO_MEMORY);
8678 END_PROFILE(SMBtrans2);
8679 return;
8682 state->cmd = SMBtrans2;
8684 state->mid = req->mid;
8685 state->vuid = req->vuid;
8686 state->setup_count = SVAL(req->vwv+13, 0);
8687 state->setup = NULL;
8688 state->total_param = SVAL(req->vwv+0, 0);
8689 state->param = NULL;
8690 state->total_data = SVAL(req->vwv+1, 0);
8691 state->data = NULL;
8692 state->max_param_return = SVAL(req->vwv+2, 0);
8693 state->max_data_return = SVAL(req->vwv+3, 0);
8694 state->max_setup_return = SVAL(req->vwv+4, 0);
8695 state->close_on_completion = BITSETW(req->vwv+5, 0);
8696 state->one_way = BITSETW(req->vwv+5, 1);
8698 state->call = tran_call;
8700 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8701 is so as a sanity check */
8702 if (state->setup_count != 1) {
8704 * Need to have rc=0 for ioctl to get job id for OS/2.
8705 * Network printing will fail if function is not successful.
8706 * Similar function in reply.c will be used if protocol
8707 * is LANMAN1.0 instead of LM1.2X002.
8708 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8709 * outbuf doesn't have to be set(only job id is used).
8711 if ( (state->setup_count == 4)
8712 && (tran_call == TRANSACT2_IOCTL)
8713 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8714 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8715 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8716 } else {
8717 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8718 DEBUG(2,("Transaction is %d\n",tran_call));
8719 TALLOC_FREE(state);
8720 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8721 END_PROFILE(SMBtrans2);
8722 return;
8726 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8727 goto bad_param;
8729 if (state->total_data) {
8731 if (trans_oob(state->total_data, 0, dscnt)
8732 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8733 goto bad_param;
8736 /* Can't use talloc here, the core routines do realloc on the
8737 * params and data. */
8738 state->data = (char *)SMB_MALLOC(state->total_data);
8739 if (state->data == NULL) {
8740 DEBUG(0,("reply_trans2: data malloc fail for %u "
8741 "bytes !\n", (unsigned int)state->total_data));
8742 TALLOC_FREE(state);
8743 reply_nterror(req, NT_STATUS_NO_MEMORY);
8744 END_PROFILE(SMBtrans2);
8745 return;
8748 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8751 if (state->total_param) {
8753 if (trans_oob(state->total_param, 0, pscnt)
8754 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8755 goto bad_param;
8758 /* Can't use talloc here, the core routines do realloc on the
8759 * params and data. */
8760 state->param = (char *)SMB_MALLOC(state->total_param);
8761 if (state->param == NULL) {
8762 DEBUG(0,("reply_trans: param malloc fail for %u "
8763 "bytes !\n", (unsigned int)state->total_param));
8764 SAFE_FREE(state->data);
8765 TALLOC_FREE(state);
8766 reply_nterror(req, NT_STATUS_NO_MEMORY);
8767 END_PROFILE(SMBtrans2);
8768 return;
8771 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8774 state->received_data = dscnt;
8775 state->received_param = pscnt;
8777 if ((state->received_param == state->total_param) &&
8778 (state->received_data == state->total_data)) {
8780 handle_trans2(conn, req, state);
8782 SAFE_FREE(state->data);
8783 SAFE_FREE(state->param);
8784 TALLOC_FREE(state);
8785 END_PROFILE(SMBtrans2);
8786 return;
8789 DLIST_ADD(conn->pending_trans, state);
8791 /* We need to send an interim response then receive the rest
8792 of the parameter/data bytes */
8793 reply_outbuf(req, 0, 0);
8794 show_msg((char *)req->outbuf);
8795 END_PROFILE(SMBtrans2);
8796 return;
8798 bad_param:
8800 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8801 SAFE_FREE(state->data);
8802 SAFE_FREE(state->param);
8803 TALLOC_FREE(state);
8804 END_PROFILE(SMBtrans2);
8805 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8809 /****************************************************************************
8810 Reply to a SMBtranss2
8811 ****************************************************************************/
8813 void reply_transs2(struct smb_request *req)
8815 connection_struct *conn = req->conn;
8816 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8817 struct trans_state *state;
8819 START_PROFILE(SMBtranss2);
8821 show_msg((char *)req->inbuf);
8823 if (req->wct < 8) {
8824 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8825 END_PROFILE(SMBtranss2);
8826 return;
8829 for (state = conn->pending_trans; state != NULL;
8830 state = state->next) {
8831 if (state->mid == req->mid) {
8832 break;
8836 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8837 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8838 END_PROFILE(SMBtranss2);
8839 return;
8842 /* Revise state->total_param and state->total_data in case they have
8843 changed downwards */
8845 if (SVAL(req->vwv+0, 0) < state->total_param)
8846 state->total_param = SVAL(req->vwv+0, 0);
8847 if (SVAL(req->vwv+1, 0) < state->total_data)
8848 state->total_data = SVAL(req->vwv+1, 0);
8850 pcnt = SVAL(req->vwv+2, 0);
8851 poff = SVAL(req->vwv+3, 0);
8852 pdisp = SVAL(req->vwv+4, 0);
8854 dcnt = SVAL(req->vwv+5, 0);
8855 doff = SVAL(req->vwv+6, 0);
8856 ddisp = SVAL(req->vwv+7, 0);
8858 state->received_param += pcnt;
8859 state->received_data += dcnt;
8861 if ((state->received_data > state->total_data) ||
8862 (state->received_param > state->total_param))
8863 goto bad_param;
8865 if (pcnt) {
8866 if (trans_oob(state->total_param, pdisp, pcnt)
8867 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8868 goto bad_param;
8870 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8873 if (dcnt) {
8874 if (trans_oob(state->total_data, ddisp, dcnt)
8875 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8876 goto bad_param;
8878 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8881 if ((state->received_param < state->total_param) ||
8882 (state->received_data < state->total_data)) {
8883 END_PROFILE(SMBtranss2);
8884 return;
8887 handle_trans2(conn, req, state);
8889 DLIST_REMOVE(conn->pending_trans, state);
8890 SAFE_FREE(state->data);
8891 SAFE_FREE(state->param);
8892 TALLOC_FREE(state);
8894 END_PROFILE(SMBtranss2);
8895 return;
8897 bad_param:
8899 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8900 DLIST_REMOVE(conn->pending_trans, state);
8901 SAFE_FREE(state->data);
8902 SAFE_FREE(state->param);
8903 TALLOC_FREE(state);
8904 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8905 END_PROFILE(SMBtranss2);
8906 return;