Implement missing info level SMB_FILE_LINK_INFORMATION.
[Samba/id10ts.git] / source3 / smbd / trans2.c
blobdec9d7f8f977ac9d02a8833ccbd9ba3c43805657
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "version.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
30 #include "../librpc/gen_ndr/xattr.h"
32 #define DIR_ENTRY_SAFETY_MARGIN 4096
34 static char *store_file_unix_basic(connection_struct *conn,
35 char *pdata,
36 files_struct *fsp,
37 const SMB_STRUCT_STAT *psbuf);
39 static char *store_file_unix_basic_info2(connection_struct *conn,
40 char *pdata,
41 files_struct *fsp,
42 const SMB_STRUCT_STAT *psbuf);
44 /********************************************************************
45 Roundup a value to the nearest allocation roundup size boundary.
46 Only do this for Windows clients.
47 ********************************************************************/
49 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
51 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
53 /* Only roundup for Windows clients. */
54 enum remote_arch_types ra_type = get_remote_arch();
55 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
56 val = SMB_ROUNDUP(val,rval);
58 return val;
61 /****************************************************************************
62 Utility functions for dealing with extended attributes.
63 ****************************************************************************/
65 /****************************************************************************
66 Refuse to allow clients to overwrite our private xattrs.
67 ****************************************************************************/
69 static bool samba_private_attr_name(const char *unix_ea_name)
71 static const char * const prohibited_ea_names[] = {
72 SAMBA_POSIX_INHERITANCE_EA_NAME,
73 SAMBA_XATTR_DOS_ATTRIB,
74 SAMBA_XATTR_MARKER,
75 XATTR_NTACL_NAME,
76 NULL
79 int i;
81 for (i = 0; prohibited_ea_names[i]; i++) {
82 if (strequal( prohibited_ea_names[i], unix_ea_name))
83 return true;
85 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
86 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
87 return true;
89 return false;
92 /****************************************************************************
93 Get one EA value. Fill in a struct ea_struct.
94 ****************************************************************************/
96 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
97 files_struct *fsp, const char *fname,
98 const char *ea_name, struct ea_struct *pea)
100 /* Get the value of this xattr. Max size is 64k. */
101 size_t attr_size = 256;
102 char *val = NULL;
103 ssize_t sizeret;
105 again:
107 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
108 if (!val) {
109 return NT_STATUS_NO_MEMORY;
112 if (fsp && fsp->fh->fd != -1) {
113 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
114 } else {
115 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
118 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
119 attr_size = 65536;
120 goto again;
123 if (sizeret == -1) {
124 return map_nt_error_from_unix(errno);
127 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
128 dump_data(10, (uint8 *)val, sizeret);
130 pea->flags = 0;
131 if (strnequal(ea_name, "user.", 5)) {
132 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
133 } else {
134 pea->name = talloc_strdup(mem_ctx, ea_name);
136 if (pea->name == NULL) {
137 TALLOC_FREE(val);
138 return NT_STATUS_NO_MEMORY;
140 pea->value.data = (unsigned char *)val;
141 pea->value.length = (size_t)sizeret;
142 return NT_STATUS_OK;
145 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
146 files_struct *fsp, const char *fname,
147 char ***pnames, size_t *pnum_names)
149 /* Get a list of all xattrs. Max namesize is 64k. */
150 size_t ea_namelist_size = 1024;
151 char *ea_namelist = NULL;
153 char *p;
154 char **names, **tmp;
155 size_t num_names;
156 ssize_t sizeret = -1;
158 if (!lp_ea_support(SNUM(conn))) {
159 if (pnames) {
160 *pnames = NULL;
162 *pnum_names = 0;
163 return NT_STATUS_OK;
167 * TALLOC the result early to get the talloc hierarchy right.
170 names = TALLOC_ARRAY(mem_ctx, char *, 1);
171 if (names == NULL) {
172 DEBUG(0, ("talloc failed\n"));
173 return NT_STATUS_NO_MEMORY;
176 while (ea_namelist_size <= 65536) {
178 ea_namelist = TALLOC_REALLOC_ARRAY(
179 names, ea_namelist, char, ea_namelist_size);
180 if (ea_namelist == NULL) {
181 DEBUG(0, ("talloc failed\n"));
182 TALLOC_FREE(names);
183 return NT_STATUS_NO_MEMORY;
186 if (fsp && fsp->fh->fd != -1) {
187 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
188 ea_namelist_size);
189 } else {
190 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
191 ea_namelist_size);
194 if ((sizeret == -1) && (errno == ERANGE)) {
195 ea_namelist_size *= 2;
197 else {
198 break;
202 if (sizeret == -1) {
203 TALLOC_FREE(names);
204 return map_nt_error_from_unix(errno);
207 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
208 (unsigned int)sizeret));
210 if (sizeret == 0) {
211 TALLOC_FREE(names);
212 if (pnames) {
213 *pnames = NULL;
215 *pnum_names = 0;
216 return NT_STATUS_OK;
220 * Ensure the result is 0-terminated
223 if (ea_namelist[sizeret-1] != '\0') {
224 TALLOC_FREE(names);
225 return NT_STATUS_INTERNAL_ERROR;
229 * count the names
231 num_names = 0;
233 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
234 num_names += 1;
237 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
238 if (tmp == NULL) {
239 DEBUG(0, ("talloc failed\n"));
240 TALLOC_FREE(names);
241 return NT_STATUS_NO_MEMORY;
244 names = tmp;
245 num_names = 0;
247 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
248 names[num_names++] = p;
251 if (pnames) {
252 *pnames = names;
253 } else {
254 TALLOC_FREE(names);
256 *pnum_names = num_names;
257 return NT_STATUS_OK;
260 /****************************************************************************
261 Return a linked list of the total EA's. Plus the total size
262 ****************************************************************************/
264 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
265 const char *fname, size_t *pea_total_len)
267 /* Get a list of all xattrs. Max namesize is 64k. */
268 size_t i, num_names;
269 char **names;
270 struct ea_list *ea_list_head = NULL;
271 NTSTATUS status;
273 *pea_total_len = 0;
275 if (!lp_ea_support(SNUM(conn))) {
276 return NULL;
279 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
280 &names, &num_names);
282 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
283 return NULL;
286 for (i=0; i<num_names; i++) {
287 struct ea_list *listp;
288 fstring dos_ea_name;
290 if (strnequal(names[i], "system.", 7)
291 || samba_private_attr_name(names[i]))
292 continue;
294 listp = TALLOC_P(mem_ctx, struct ea_list);
295 if (listp == NULL) {
296 return NULL;
299 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
300 fname, names[i],
301 &listp->ea))) {
302 return NULL;
305 push_ascii_fstring(dos_ea_name, listp->ea.name);
307 *pea_total_len +=
308 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
310 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
311 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
312 (unsigned int)listp->ea.value.length));
314 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
318 /* Add on 4 for total length. */
319 if (*pea_total_len) {
320 *pea_total_len += 4;
323 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
324 (unsigned int)*pea_total_len));
326 return ea_list_head;
329 /****************************************************************************
330 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
331 that was filled.
332 ****************************************************************************/
334 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
335 connection_struct *conn, struct ea_list *ea_list)
337 unsigned int ret_data_size = 4;
338 char *p = pdata;
340 SMB_ASSERT(total_data_size >= 4);
342 if (!lp_ea_support(SNUM(conn))) {
343 SIVAL(pdata,4,0);
344 return 4;
347 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
348 size_t dos_namelen;
349 fstring dos_ea_name;
350 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
351 dos_namelen = strlen(dos_ea_name);
352 if (dos_namelen > 255 || dos_namelen == 0) {
353 break;
355 if (ea_list->ea.value.length > 65535) {
356 break;
358 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
359 break;
362 /* We know we have room. */
363 SCVAL(p,0,ea_list->ea.flags);
364 SCVAL(p,1,dos_namelen);
365 SSVAL(p,2,ea_list->ea.value.length);
366 fstrcpy(p+4, dos_ea_name);
367 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
369 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
370 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
373 ret_data_size = PTR_DIFF(p, pdata);
374 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
375 SIVAL(pdata,0,ret_data_size);
376 return ret_data_size;
379 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
380 char *pdata,
381 unsigned int total_data_size,
382 unsigned int *ret_data_size,
383 connection_struct *conn,
384 struct ea_list *ea_list)
386 uint8_t *p = (uint8_t *)pdata;
387 uint8_t *last_start = NULL;
389 *ret_data_size = 0;
391 if (!lp_ea_support(SNUM(conn))) {
392 return NT_STATUS_NO_EAS_ON_FILE;
395 for (; ea_list; ea_list = ea_list->next) {
396 size_t dos_namelen;
397 fstring dos_ea_name;
398 size_t this_size;
400 if (last_start) {
401 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
403 last_start = p;
405 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
406 dos_namelen = strlen(dos_ea_name);
407 if (dos_namelen > 255 || dos_namelen == 0) {
408 return NT_STATUS_INTERNAL_ERROR;
410 if (ea_list->ea.value.length > 65535) {
411 return NT_STATUS_INTERNAL_ERROR;
414 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
416 if (ea_list->next) {
417 size_t pad = 4 - (this_size % 4);
418 this_size += pad;
421 if (this_size > total_data_size) {
422 return NT_STATUS_INFO_LENGTH_MISMATCH;
425 /* We know we have room. */
426 SIVAL(p, 0x00, 0); /* next offset */
427 SCVAL(p, 0x04, ea_list->ea.flags);
428 SCVAL(p, 0x05, dos_namelen);
429 SSVAL(p, 0x06, ea_list->ea.value.length);
430 fstrcpy((char *)(p+0x08), dos_ea_name);
431 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
433 total_data_size -= this_size;
434 p += this_size;
437 *ret_data_size = PTR_DIFF(p, pdata);
438 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
439 return NT_STATUS_OK;
442 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
444 size_t total_ea_len = 0;
445 TALLOC_CTX *mem_ctx = NULL;
447 if (!lp_ea_support(SNUM(conn))) {
448 return 0;
450 mem_ctx = talloc_tos();
451 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
452 return total_ea_len;
455 /****************************************************************************
456 Ensure the EA name is case insensitive by matching any existing EA name.
457 ****************************************************************************/
459 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
461 size_t total_ea_len;
462 TALLOC_CTX *mem_ctx = talloc_tos();
463 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
465 for (; ea_list; ea_list = ea_list->next) {
466 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
467 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
468 &unix_ea_name[5], ea_list->ea.name));
469 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
470 break;
475 /****************************************************************************
476 Set or delete an extended attribute.
477 ****************************************************************************/
479 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
480 const struct smb_filename *smb_fname, struct ea_list *ea_list)
482 char *fname = NULL;
484 if (!lp_ea_support(SNUM(conn))) {
485 return NT_STATUS_EAS_NOT_SUPPORTED;
488 /* For now setting EAs on streams isn't supported. */
489 fname = smb_fname->base_name;
491 for (;ea_list; ea_list = ea_list->next) {
492 int ret;
493 fstring unix_ea_name;
495 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
496 fstrcat(unix_ea_name, ea_list->ea.name);
498 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
500 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
502 if (samba_private_attr_name(unix_ea_name)) {
503 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
504 return NT_STATUS_ACCESS_DENIED;
507 if (ea_list->ea.value.length == 0) {
508 /* Remove the attribute. */
509 if (fsp && (fsp->fh->fd != -1)) {
510 DEBUG(10,("set_ea: deleting ea name %s on "
511 "file %s by file descriptor.\n",
512 unix_ea_name, fsp_str_dbg(fsp)));
513 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
514 } else {
515 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
516 unix_ea_name, fname));
517 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
519 #ifdef ENOATTR
520 /* Removing a non existent attribute always succeeds. */
521 if (ret == -1 && errno == ENOATTR) {
522 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
523 unix_ea_name));
524 ret = 0;
526 #endif
527 } else {
528 if (fsp && (fsp->fh->fd != -1)) {
529 DEBUG(10,("set_ea: setting ea name %s on file "
530 "%s by file descriptor.\n",
531 unix_ea_name, fsp_str_dbg(fsp)));
532 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
533 ea_list->ea.value.data, ea_list->ea.value.length, 0);
534 } else {
535 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
536 unix_ea_name, fname));
537 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
538 ea_list->ea.value.data, ea_list->ea.value.length, 0);
542 if (ret == -1) {
543 #ifdef ENOTSUP
544 if (errno == ENOTSUP) {
545 return NT_STATUS_EAS_NOT_SUPPORTED;
547 #endif
548 return map_nt_error_from_unix(errno);
552 return NT_STATUS_OK;
554 /****************************************************************************
555 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
556 ****************************************************************************/
558 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
560 struct ea_list *ea_list_head = NULL;
561 size_t converted_size, offset = 0;
563 while (offset + 2 < data_size) {
564 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
565 unsigned int namelen = CVAL(pdata,offset);
567 offset++; /* Go past the namelen byte. */
569 /* integer wrap paranioa. */
570 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
571 (offset > data_size) || (namelen > data_size) ||
572 (offset + namelen >= data_size)) {
573 break;
575 /* Ensure the name is null terminated. */
576 if (pdata[offset + namelen] != '\0') {
577 return NULL;
579 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
580 &converted_size)) {
581 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
582 "failed: %s", strerror(errno)));
584 if (!eal->ea.name) {
585 return NULL;
588 offset += (namelen + 1); /* Go past the name + terminating zero. */
589 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
590 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
593 return ea_list_head;
596 /****************************************************************************
597 Read one EA list entry from the buffer.
598 ****************************************************************************/
600 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
602 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
603 uint16 val_len;
604 unsigned int namelen;
605 size_t converted_size;
607 if (!eal) {
608 return NULL;
611 if (data_size < 6) {
612 return NULL;
615 eal->ea.flags = CVAL(pdata,0);
616 namelen = CVAL(pdata,1);
617 val_len = SVAL(pdata,2);
619 if (4 + namelen + 1 + val_len > data_size) {
620 return NULL;
623 /* Ensure the name is null terminated. */
624 if (pdata[namelen + 4] != '\0') {
625 return NULL;
627 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
628 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
629 strerror(errno)));
631 if (!eal->ea.name) {
632 return NULL;
635 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
636 if (!eal->ea.value.data) {
637 return NULL;
640 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
642 /* Ensure we're null terminated just in case we print the value. */
643 eal->ea.value.data[val_len] = '\0';
644 /* But don't count the null. */
645 eal->ea.value.length--;
647 if (pbytes_used) {
648 *pbytes_used = 4 + namelen + 1 + val_len;
651 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
652 dump_data(10, eal->ea.value.data, eal->ea.value.length);
654 return eal;
657 /****************************************************************************
658 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
659 ****************************************************************************/
661 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
663 struct ea_list *ea_list_head = NULL;
664 size_t offset = 0;
665 size_t bytes_used = 0;
667 while (offset < data_size) {
668 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
670 if (!eal) {
671 return NULL;
674 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
675 offset += bytes_used;
678 return ea_list_head;
681 /****************************************************************************
682 Count the total EA size needed.
683 ****************************************************************************/
685 static size_t ea_list_size(struct ea_list *ealist)
687 fstring dos_ea_name;
688 struct ea_list *listp;
689 size_t ret = 0;
691 for (listp = ealist; listp; listp = listp->next) {
692 push_ascii_fstring(dos_ea_name, listp->ea.name);
693 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
695 /* Add on 4 for total length. */
696 if (ret) {
697 ret += 4;
700 return ret;
703 /****************************************************************************
704 Return a union of EA's from a file list and a list of names.
705 The TALLOC context for the two lists *MUST* be identical as we steal
706 memory from one list to add to another. JRA.
707 ****************************************************************************/
709 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
711 struct ea_list *nlistp, *flistp;
713 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
714 for (flistp = file_list; flistp; flistp = flistp->next) {
715 if (strequal(nlistp->ea.name, flistp->ea.name)) {
716 break;
720 if (flistp) {
721 /* Copy the data from this entry. */
722 nlistp->ea.flags = flistp->ea.flags;
723 nlistp->ea.value = flistp->ea.value;
724 } else {
725 /* Null entry. */
726 nlistp->ea.flags = 0;
727 ZERO_STRUCT(nlistp->ea.value);
731 *total_ea_len = ea_list_size(name_list);
732 return name_list;
735 /****************************************************************************
736 Send the required number of replies back.
737 We assume all fields other than the data fields are
738 set correctly for the type of call.
739 HACK ! Always assumes smb_setup field is zero.
740 ****************************************************************************/
742 void send_trans2_replies(connection_struct *conn,
743 struct smb_request *req,
744 const char *params,
745 int paramsize,
746 const char *pdata,
747 int datasize,
748 int max_data_bytes)
750 /* As we are using a protocol > LANMAN1 then the max_send
751 variable must have been set in the sessetupX call.
752 This takes precedence over the max_xmit field in the
753 global struct. These different max_xmit variables should
754 be merged as this is now too confusing */
756 int data_to_send = datasize;
757 int params_to_send = paramsize;
758 int useable_space;
759 const char *pp = params;
760 const char *pd = pdata;
761 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
762 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
763 int data_alignment_offset = 0;
764 bool overflow = False;
765 struct smbd_server_connection *sconn = smbd_server_conn;
766 int max_send = sconn->smb1.sessions.max_send;
768 /* Modify the data_to_send and datasize and set the error if
769 we're trying to send more than max_data_bytes. We still send
770 the part of the packet(s) that fit. Strange, but needed
771 for OS/2. */
773 if (max_data_bytes > 0 && datasize > max_data_bytes) {
774 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
775 max_data_bytes, datasize ));
776 datasize = data_to_send = max_data_bytes;
777 overflow = True;
780 /* If there genuinely are no parameters or data to send just send the empty packet */
782 if(params_to_send == 0 && data_to_send == 0) {
783 reply_outbuf(req, 10, 0);
784 show_msg((char *)req->outbuf);
785 if (!srv_send_smb(smbd_server_fd(),
786 (char *)req->outbuf,
787 true, req->seqnum+1,
788 IS_CONN_ENCRYPTED(conn),
789 &req->pcd)) {
790 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
792 TALLOC_FREE(req->outbuf);
793 return;
796 /* When sending params and data ensure that both are nicely aligned */
797 /* Only do this alignment when there is also data to send - else
798 can cause NT redirector problems. */
800 if (((params_to_send % 4) != 0) && (data_to_send != 0))
801 data_alignment_offset = 4 - (params_to_send % 4);
803 /* Space is bufsize minus Netbios over TCP header minus SMB header */
804 /* The alignment_offset is to align the param bytes on an even byte
805 boundary. NT 4.0 Beta needs this to work correctly. */
807 useable_space = max_send - (smb_size
808 + 2 * 10 /* wct */
809 + alignment_offset
810 + data_alignment_offset);
812 if (useable_space < 0) {
813 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
814 "= %d!!!", useable_space));
815 exit_server_cleanly("send_trans2_replies: Not enough space");
818 while (params_to_send || data_to_send) {
819 /* Calculate whether we will totally or partially fill this packet */
821 total_sent_thistime = params_to_send + data_to_send;
823 /* We can never send more than useable_space */
825 * Note that 'useable_space' does not include the alignment offsets,
826 * but we must include the alignment offsets in the calculation of
827 * the length of the data we send over the wire, as the alignment offsets
828 * are sent here. Fix from Marc_Jacobsen@hp.com.
831 total_sent_thistime = MIN(total_sent_thistime, useable_space);
833 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
834 + data_alignment_offset);
837 * We might have SMBtrans2s in req which was transferred to
838 * the outbuf, fix that.
840 SCVAL(req->outbuf, smb_com, SMBtrans2);
842 /* Set total params and data to be sent */
843 SSVAL(req->outbuf,smb_tprcnt,paramsize);
844 SSVAL(req->outbuf,smb_tdrcnt,datasize);
846 /* Calculate how many parameters and data we can fit into
847 * this packet. Parameters get precedence
850 params_sent_thistime = MIN(params_to_send,useable_space);
851 data_sent_thistime = useable_space - params_sent_thistime;
852 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
854 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
856 /* smb_proff is the offset from the start of the SMB header to the
857 parameter bytes, however the first 4 bytes of outbuf are
858 the Netbios over TCP header. Thus use smb_base() to subtract
859 them from the calculation */
861 SSVAL(req->outbuf,smb_proff,
862 ((smb_buf(req->outbuf)+alignment_offset)
863 - smb_base(req->outbuf)));
865 if(params_sent_thistime == 0)
866 SSVAL(req->outbuf,smb_prdisp,0);
867 else
868 /* Absolute displacement of param bytes sent in this packet */
869 SSVAL(req->outbuf,smb_prdisp,pp - params);
871 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
872 if(data_sent_thistime == 0) {
873 SSVAL(req->outbuf,smb_droff,0);
874 SSVAL(req->outbuf,smb_drdisp, 0);
875 } else {
876 /* The offset of the data bytes is the offset of the
877 parameter bytes plus the number of parameters being sent this time */
878 SSVAL(req->outbuf, smb_droff,
879 ((smb_buf(req->outbuf)+alignment_offset)
880 - smb_base(req->outbuf))
881 + params_sent_thistime + data_alignment_offset);
882 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
885 /* Initialize the padding for alignment */
887 if (alignment_offset != 0) {
888 memset(smb_buf(req->outbuf), 0, alignment_offset);
891 /* Copy the param bytes into the packet */
893 if(params_sent_thistime) {
894 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
895 params_sent_thistime);
898 /* Copy in the data bytes */
899 if(data_sent_thistime) {
900 if (data_alignment_offset != 0) {
901 memset((smb_buf(req->outbuf)+alignment_offset+
902 params_sent_thistime), 0,
903 data_alignment_offset);
905 memcpy(smb_buf(req->outbuf)+alignment_offset
906 +params_sent_thistime+data_alignment_offset,
907 pd,data_sent_thistime);
910 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
911 params_sent_thistime, data_sent_thistime, useable_space));
912 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
913 params_to_send, data_to_send, paramsize, datasize));
915 if (overflow) {
916 error_packet_set((char *)req->outbuf,
917 ERRDOS,ERRbufferoverflow,
918 STATUS_BUFFER_OVERFLOW,
919 __LINE__,__FILE__);
922 /* Send the packet */
923 show_msg((char *)req->outbuf);
924 if (!srv_send_smb(smbd_server_fd(),
925 (char *)req->outbuf,
926 true, req->seqnum+1,
927 IS_CONN_ENCRYPTED(conn),
928 &req->pcd))
929 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
931 TALLOC_FREE(req->outbuf);
933 pp += params_sent_thistime;
934 pd += data_sent_thistime;
936 params_to_send -= params_sent_thistime;
937 data_to_send -= data_sent_thistime;
939 /* Sanity check */
940 if(params_to_send < 0 || data_to_send < 0) {
941 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
942 params_to_send, data_to_send));
943 return;
947 return;
950 /****************************************************************************
951 Reply to a TRANSACT2_OPEN.
952 ****************************************************************************/
954 static void call_trans2open(connection_struct *conn,
955 struct smb_request *req,
956 char **pparams, int total_params,
957 char **ppdata, int total_data,
958 unsigned int max_data_bytes)
960 struct smb_filename *smb_fname = NULL;
961 char *params = *pparams;
962 char *pdata = *ppdata;
963 int deny_mode;
964 int32 open_attr;
965 bool oplock_request;
966 #if 0
967 bool return_additional_info;
968 int16 open_sattr;
969 time_t open_time;
970 #endif
971 int open_ofun;
972 uint32 open_size;
973 char *pname;
974 char *fname = NULL;
975 SMB_OFF_T size=0;
976 int fattr=0,mtime=0;
977 SMB_INO_T inode = 0;
978 int smb_action = 0;
979 files_struct *fsp;
980 struct ea_list *ea_list = NULL;
981 uint16 flags = 0;
982 NTSTATUS status;
983 uint32 access_mask;
984 uint32 share_mode;
985 uint32 create_disposition;
986 uint32 create_options = 0;
987 uint32_t private_flags = 0;
988 TALLOC_CTX *ctx = talloc_tos();
991 * Ensure we have enough parameters to perform the operation.
994 if (total_params < 29) {
995 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
996 goto out;
999 flags = SVAL(params, 0);
1000 deny_mode = SVAL(params, 2);
1001 open_attr = SVAL(params,6);
1002 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1003 if (oplock_request) {
1004 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1007 #if 0
1008 return_additional_info = BITSETW(params,0);
1009 open_sattr = SVAL(params, 4);
1010 open_time = make_unix_date3(params+8);
1011 #endif
1012 open_ofun = SVAL(params,12);
1013 open_size = IVAL(params,14);
1014 pname = &params[28];
1016 if (IS_IPC(conn)) {
1017 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1018 goto out;
1021 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1022 total_params - 28, STR_TERMINATE,
1023 &status);
1024 if (!NT_STATUS_IS_OK(status)) {
1025 reply_nterror(req, status);
1026 goto out;
1029 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1030 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1031 (unsigned int)open_ofun, open_size));
1033 status = filename_convert(ctx,
1034 conn,
1035 req->flags2 & FLAGS2_DFS_PATHNAMES,
1036 fname,
1038 NULL,
1039 &smb_fname);
1040 if (!NT_STATUS_IS_OK(status)) {
1041 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1042 reply_botherror(req,
1043 NT_STATUS_PATH_NOT_COVERED,
1044 ERRSRV, ERRbadpath);
1045 goto out;
1047 reply_nterror(req, status);
1048 goto out;
1051 if (open_ofun == 0) {
1052 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1053 goto out;
1056 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1057 &access_mask, &share_mode,
1058 &create_disposition,
1059 &create_options,
1060 &private_flags)) {
1061 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1062 goto out;
1065 /* Any data in this call is an EA list. */
1066 if (total_data && (total_data != 4)) {
1067 if (total_data < 10) {
1068 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1069 goto out;
1072 if (IVAL(pdata,0) > total_data) {
1073 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1074 IVAL(pdata,0), (unsigned int)total_data));
1075 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1076 goto out;
1079 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1080 total_data - 4);
1081 if (!ea_list) {
1082 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1083 goto out;
1086 if (!lp_ea_support(SNUM(conn))) {
1087 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1088 goto out;
1092 status = SMB_VFS_CREATE_FILE(
1093 conn, /* conn */
1094 req, /* req */
1095 0, /* root_dir_fid */
1096 smb_fname, /* fname */
1097 access_mask, /* access_mask */
1098 share_mode, /* share_access */
1099 create_disposition, /* create_disposition*/
1100 create_options, /* create_options */
1101 open_attr, /* file_attributes */
1102 oplock_request, /* oplock_request */
1103 open_size, /* allocation_size */
1104 private_flags,
1105 NULL, /* sd */
1106 ea_list, /* ea_list */
1107 &fsp, /* result */
1108 &smb_action); /* psbuf */
1110 if (!NT_STATUS_IS_OK(status)) {
1111 if (open_was_deferred(req->mid)) {
1112 /* We have re-scheduled this call. */
1113 goto out;
1115 reply_openerror(req, status);
1116 goto out;
1119 size = get_file_size_stat(&smb_fname->st);
1120 fattr = dos_mode(conn, smb_fname);
1121 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1122 inode = smb_fname->st.st_ex_ino;
1123 if (fattr & aDIR) {
1124 close_file(req, fsp, ERROR_CLOSE);
1125 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1126 goto out;
1129 /* Realloc the size of parameters and data we will return */
1130 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1131 if(*pparams == NULL ) {
1132 reply_nterror(req, NT_STATUS_NO_MEMORY);
1133 goto out;
1135 params = *pparams;
1137 SSVAL(params,0,fsp->fnum);
1138 SSVAL(params,2,fattr);
1139 srv_put_dos_date2(params,4, mtime);
1140 SIVAL(params,8, (uint32)size);
1141 SSVAL(params,12,deny_mode);
1142 SSVAL(params,14,0); /* open_type - file or directory. */
1143 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1145 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1146 smb_action |= EXTENDED_OPLOCK_GRANTED;
1149 SSVAL(params,18,smb_action);
1152 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1154 SIVAL(params,20,inode);
1155 SSVAL(params,24,0); /* Padding. */
1156 if (flags & 8) {
1157 uint32 ea_size = estimate_ea_size(conn, fsp,
1158 fsp->fsp_name->base_name);
1159 SIVAL(params, 26, ea_size);
1160 } else {
1161 SIVAL(params, 26, 0);
1164 /* Send the required number of replies */
1165 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1166 out:
1167 TALLOC_FREE(smb_fname);
1170 /*********************************************************
1171 Routine to check if a given string matches exactly.
1172 as a special case a mask of "." does NOT match. That
1173 is required for correct wildcard semantics
1174 Case can be significant or not.
1175 **********************************************************/
1177 static bool exact_match(bool has_wild,
1178 bool case_sensitive,
1179 const char *str,
1180 const char *mask)
1182 if (mask[0] == '.' && mask[1] == 0) {
1183 return false;
1186 if (has_wild) {
1187 return false;
1190 if (case_sensitive) {
1191 return strcmp(str,mask)==0;
1192 } else {
1193 return StrCaseCmp(str,mask) == 0;
1197 /****************************************************************************
1198 Return the filetype for UNIX extensions.
1199 ****************************************************************************/
1201 static uint32 unix_filetype(mode_t mode)
1203 if(S_ISREG(mode))
1204 return UNIX_TYPE_FILE;
1205 else if(S_ISDIR(mode))
1206 return UNIX_TYPE_DIR;
1207 #ifdef S_ISLNK
1208 else if(S_ISLNK(mode))
1209 return UNIX_TYPE_SYMLINK;
1210 #endif
1211 #ifdef S_ISCHR
1212 else if(S_ISCHR(mode))
1213 return UNIX_TYPE_CHARDEV;
1214 #endif
1215 #ifdef S_ISBLK
1216 else if(S_ISBLK(mode))
1217 return UNIX_TYPE_BLKDEV;
1218 #endif
1219 #ifdef S_ISFIFO
1220 else if(S_ISFIFO(mode))
1221 return UNIX_TYPE_FIFO;
1222 #endif
1223 #ifdef S_ISSOCK
1224 else if(S_ISSOCK(mode))
1225 return UNIX_TYPE_SOCKET;
1226 #endif
1228 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1229 return UNIX_TYPE_UNKNOWN;
1232 /****************************************************************************
1233 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1234 ****************************************************************************/
1236 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1238 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1239 const SMB_STRUCT_STAT *psbuf,
1240 uint32 perms,
1241 enum perm_type ptype,
1242 mode_t *ret_perms)
1244 mode_t ret = 0;
1246 if (perms == SMB_MODE_NO_CHANGE) {
1247 if (!VALID_STAT(*psbuf)) {
1248 return NT_STATUS_INVALID_PARAMETER;
1249 } else {
1250 *ret_perms = psbuf->st_ex_mode;
1251 return NT_STATUS_OK;
1255 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1256 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1257 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1258 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1259 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1260 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1261 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1262 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1263 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1264 #ifdef S_ISVTX
1265 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1266 #endif
1267 #ifdef S_ISGID
1268 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1269 #endif
1270 #ifdef S_ISUID
1271 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1272 #endif
1274 switch (ptype) {
1275 case PERM_NEW_FILE:
1276 /* Apply mode mask */
1277 ret &= lp_create_mask(SNUM(conn));
1278 /* Add in force bits */
1279 ret |= lp_force_create_mode(SNUM(conn));
1280 break;
1281 case PERM_NEW_DIR:
1282 ret &= lp_dir_mask(SNUM(conn));
1283 /* Add in force bits */
1284 ret |= lp_force_dir_mode(SNUM(conn));
1285 break;
1286 case PERM_EXISTING_FILE:
1287 /* Apply mode mask */
1288 ret &= lp_security_mask(SNUM(conn));
1289 /* Add in force bits */
1290 ret |= lp_force_security_mode(SNUM(conn));
1291 break;
1292 case PERM_EXISTING_DIR:
1293 /* Apply mode mask */
1294 ret &= lp_dir_security_mask(SNUM(conn));
1295 /* Add in force bits */
1296 ret |= lp_force_dir_security_mode(SNUM(conn));
1297 break;
1300 *ret_perms = ret;
1301 return NT_STATUS_OK;
1304 /****************************************************************************
1305 Needed to show the msdfs symlinks as directories. Modifies psbuf
1306 to be a directory if it's a msdfs link.
1307 ****************************************************************************/
1309 static bool check_msdfs_link(connection_struct *conn,
1310 const char *pathname,
1311 SMB_STRUCT_STAT *psbuf)
1313 int saved_errno = errno;
1314 if(lp_host_msdfs() &&
1315 lp_msdfs_root(SNUM(conn)) &&
1316 is_msdfs_link(conn, pathname, psbuf)) {
1318 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1319 "as a directory\n",
1320 pathname));
1321 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1322 errno = saved_errno;
1323 return true;
1325 errno = saved_errno;
1326 return false;
1330 /****************************************************************************
1331 Get a level dependent lanman2 dir entry.
1332 ****************************************************************************/
1334 struct smbd_dirptr_lanman2_state {
1335 connection_struct *conn;
1336 uint32_t info_level;
1337 bool check_mangled_names;
1338 bool has_wild;
1339 bool got_exact_match;
1342 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1343 void *private_data,
1344 const char *dname,
1345 const char *mask,
1346 char **_fname)
1348 struct smbd_dirptr_lanman2_state *state =
1349 (struct smbd_dirptr_lanman2_state *)private_data;
1350 bool ok;
1351 char mangled_name[13]; /* mangled 8.3 name. */
1352 bool got_match;
1353 const char *fname;
1355 /* Mangle fname if it's an illegal name. */
1356 if (mangle_must_mangle(dname, state->conn->params)) {
1357 ok = name_to_8_3(dname, mangled_name,
1358 true, state->conn->params);
1359 if (!ok) {
1360 return false;
1362 fname = mangled_name;
1363 } else {
1364 fname = dname;
1367 got_match = exact_match(state->has_wild,
1368 state->conn->case_sensitive,
1369 fname, mask);
1370 state->got_exact_match = got_match;
1371 if (!got_match) {
1372 got_match = mask_match(fname, mask,
1373 state->conn->case_sensitive);
1376 if(!got_match && state->check_mangled_names &&
1377 !mangle_is_8_3(fname, false, state->conn->params)) {
1379 * It turns out that NT matches wildcards against
1380 * both long *and* short names. This may explain some
1381 * of the wildcard wierdness from old DOS clients
1382 * that some people have been seeing.... JRA.
1384 /* Force the mangling into 8.3. */
1385 ok = name_to_8_3(fname, mangled_name,
1386 false, state->conn->params);
1387 if (!ok) {
1388 return false;
1391 got_match = exact_match(state->has_wild,
1392 state->conn->case_sensitive,
1393 mangled_name, mask);
1394 state->got_exact_match = got_match;
1395 if (!got_match) {
1396 got_match = mask_match(mangled_name, mask,
1397 state->conn->case_sensitive);
1401 if (!got_match) {
1402 return false;
1405 *_fname = talloc_strdup(ctx, fname);
1406 if (*_fname == NULL) {
1407 return false;
1410 return true;
1413 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1414 void *private_data,
1415 struct smb_filename *smb_fname,
1416 uint32_t *_mode)
1418 struct smbd_dirptr_lanman2_state *state =
1419 (struct smbd_dirptr_lanman2_state *)private_data;
1420 bool ms_dfs_link = false;
1421 uint32_t mode = 0;
1423 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1424 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1425 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1426 "Couldn't lstat [%s] (%s)\n",
1427 smb_fname_str_dbg(smb_fname),
1428 strerror(errno)));
1429 return false;
1431 } else if (!VALID_STAT(smb_fname->st) &&
1432 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1433 /* Needed to show the msdfs symlinks as
1434 * directories */
1436 ms_dfs_link = check_msdfs_link(state->conn,
1437 smb_fname->base_name,
1438 &smb_fname->st);
1439 if (!ms_dfs_link) {
1440 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1441 "Couldn't stat [%s] (%s)\n",
1442 smb_fname_str_dbg(smb_fname),
1443 strerror(errno)));
1444 return false;
1448 if (ms_dfs_link) {
1449 mode = dos_mode_msdfs(state->conn, smb_fname);
1450 } else {
1451 mode = dos_mode(state->conn, smb_fname);
1454 *_mode = mode;
1455 return true;
1458 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1459 connection_struct *conn,
1460 uint16_t flags2,
1461 uint32_t info_level,
1462 struct ea_list *name_list,
1463 bool check_mangled_names,
1464 bool requires_resume_key,
1465 uint32_t mode,
1466 const char *fname,
1467 const struct smb_filename *smb_fname,
1468 int space_remaining,
1469 uint8_t align,
1470 bool do_pad,
1471 char *base_data,
1472 char **ppdata,
1473 char *end_data,
1474 bool *out_of_space,
1475 uint64_t *last_entry_off)
1477 char *p, *q, *pdata = *ppdata;
1478 uint32_t reskey=0;
1479 uint64_t file_size = 0;
1480 uint64_t allocation_size = 0;
1481 uint32_t len;
1482 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1483 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1484 time_t c_date = (time_t)0;
1485 char *nameptr;
1486 char *last_entry_ptr;
1487 bool was_8_3;
1488 int off;
1489 int pad = 0;
1491 *out_of_space = false;
1493 ZERO_STRUCT(mdate_ts);
1494 ZERO_STRUCT(adate_ts);
1495 ZERO_STRUCT(create_date_ts);
1496 ZERO_STRUCT(cdate_ts);
1498 if (!(mode & aDIR)) {
1499 file_size = get_file_size_stat(&smb_fname->st);
1501 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1503 mdate_ts = smb_fname->st.st_ex_mtime;
1504 adate_ts = smb_fname->st.st_ex_atime;
1505 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1506 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1508 if (lp_dos_filetime_resolution(SNUM(conn))) {
1509 dos_filetime_timespec(&create_date_ts);
1510 dos_filetime_timespec(&mdate_ts);
1511 dos_filetime_timespec(&adate_ts);
1512 dos_filetime_timespec(&cdate_ts);
1515 create_date = convert_timespec_to_time_t(create_date_ts);
1516 mdate = convert_timespec_to_time_t(mdate_ts);
1517 adate = convert_timespec_to_time_t(adate_ts);
1518 c_date = convert_timespec_to_time_t(cdate_ts);
1520 /* align the record */
1521 SMB_ASSERT(align >= 1);
1523 off = (int)PTR_DIFF(pdata, base_data);
1524 pad = (off + (align-1)) & ~(align-1);
1525 pad -= off;
1527 if (pad && pad > space_remaining) {
1528 *out_of_space = true;
1529 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1530 "for padding (wanted %u, had %d)\n",
1531 (unsigned int)pad,
1532 space_remaining ));
1533 return false; /* Not finished - just out of space */
1536 off += pad;
1537 /* initialize padding to 0 */
1538 if (pad) {
1539 memset(pdata, 0, pad);
1541 space_remaining -= pad;
1543 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1544 space_remaining ));
1546 pdata += pad;
1547 p = pdata;
1548 last_entry_ptr = p;
1550 pad = 0;
1551 off = 0;
1553 switch (info_level) {
1554 case SMB_FIND_INFO_STANDARD:
1555 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1556 if(requires_resume_key) {
1557 SIVAL(p,0,reskey);
1558 p += 4;
1560 srv_put_dos_date2(p,0,create_date);
1561 srv_put_dos_date2(p,4,adate);
1562 srv_put_dos_date2(p,8,mdate);
1563 SIVAL(p,12,(uint32)file_size);
1564 SIVAL(p,16,(uint32)allocation_size);
1565 SSVAL(p,20,mode);
1566 p += 23;
1567 nameptr = p;
1568 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1569 p += ucs2_align(base_data, p, 0);
1571 len = srvstr_push(base_data, flags2, p,
1572 fname, PTR_DIFF(end_data, p),
1573 STR_TERMINATE);
1574 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1575 if (len > 2) {
1576 SCVAL(nameptr, -1, len - 2);
1577 } else {
1578 SCVAL(nameptr, -1, 0);
1580 } else {
1581 if (len > 1) {
1582 SCVAL(nameptr, -1, len - 1);
1583 } else {
1584 SCVAL(nameptr, -1, 0);
1587 p += len;
1588 break;
1590 case SMB_FIND_EA_SIZE:
1591 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1592 if (requires_resume_key) {
1593 SIVAL(p,0,reskey);
1594 p += 4;
1596 srv_put_dos_date2(p,0,create_date);
1597 srv_put_dos_date2(p,4,adate);
1598 srv_put_dos_date2(p,8,mdate);
1599 SIVAL(p,12,(uint32)file_size);
1600 SIVAL(p,16,(uint32)allocation_size);
1601 SSVAL(p,20,mode);
1603 unsigned int ea_size = estimate_ea_size(conn, NULL,
1604 smb_fname->base_name);
1605 SIVAL(p,22,ea_size); /* Extended attributes */
1607 p += 27;
1608 nameptr = p - 1;
1609 len = srvstr_push(base_data, flags2,
1610 p, fname, PTR_DIFF(end_data, p),
1611 STR_TERMINATE | STR_NOALIGN);
1612 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1613 if (len > 2) {
1614 len -= 2;
1615 } else {
1616 len = 0;
1618 } else {
1619 if (len > 1) {
1620 len -= 1;
1621 } else {
1622 len = 0;
1625 SCVAL(nameptr,0,len);
1626 p += len;
1627 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1628 break;
1630 case SMB_FIND_EA_LIST:
1632 struct ea_list *file_list = NULL;
1633 size_t ea_len = 0;
1635 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1636 if (!name_list) {
1637 return false;
1639 if (requires_resume_key) {
1640 SIVAL(p,0,reskey);
1641 p += 4;
1643 srv_put_dos_date2(p,0,create_date);
1644 srv_put_dos_date2(p,4,adate);
1645 srv_put_dos_date2(p,8,mdate);
1646 SIVAL(p,12,(uint32)file_size);
1647 SIVAL(p,16,(uint32)allocation_size);
1648 SSVAL(p,20,mode);
1649 p += 22; /* p now points to the EA area. */
1651 file_list = get_ea_list_from_file(ctx, conn, NULL,
1652 smb_fname->base_name,
1653 &ea_len);
1654 name_list = ea_list_union(name_list, file_list, &ea_len);
1656 /* We need to determine if this entry will fit in the space available. */
1657 /* Max string size is 255 bytes. */
1658 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1659 *out_of_space = true;
1660 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1661 "(wanted %u, had %d)\n",
1662 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1663 space_remaining ));
1664 return False; /* Not finished - just out of space */
1667 /* Push the ea_data followed by the name. */
1668 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1669 nameptr = p;
1670 len = srvstr_push(base_data, flags2,
1671 p + 1, fname, PTR_DIFF(end_data, p+1),
1672 STR_TERMINATE | STR_NOALIGN);
1673 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1674 if (len > 2) {
1675 len -= 2;
1676 } else {
1677 len = 0;
1679 } else {
1680 if (len > 1) {
1681 len -= 1;
1682 } else {
1683 len = 0;
1686 SCVAL(nameptr,0,len);
1687 p += len + 1;
1688 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1689 break;
1692 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1693 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1694 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1695 p += 4;
1696 SIVAL(p,0,reskey); p += 4;
1697 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1698 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1699 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1700 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1701 SOFF_T(p,0,file_size); p += 8;
1702 SOFF_T(p,0,allocation_size); p += 8;
1703 SIVAL(p,0,mode); p += 4;
1704 q = p; p += 4; /* q is placeholder for name length. */
1706 unsigned int ea_size = estimate_ea_size(conn, NULL,
1707 smb_fname->base_name);
1708 SIVAL(p,0,ea_size); /* Extended attributes */
1709 p += 4;
1711 /* Clear the short name buffer. This is
1712 * IMPORTANT as not doing so will trigger
1713 * a Win2k client bug. JRA.
1715 if (!was_8_3 && check_mangled_names) {
1716 char mangled_name[13]; /* mangled 8.3 name. */
1717 if (!name_to_8_3(fname,mangled_name,True,
1718 conn->params)) {
1719 /* Error - mangle failed ! */
1720 memset(mangled_name,'\0',12);
1722 mangled_name[12] = 0;
1723 len = srvstr_push(base_data, flags2,
1724 p+2, mangled_name, 24,
1725 STR_UPPER|STR_UNICODE);
1726 if (len < 24) {
1727 memset(p + 2 + len,'\0',24 - len);
1729 SSVAL(p, 0, len);
1730 } else {
1731 memset(p,'\0',26);
1733 p += 2 + 24;
1734 len = srvstr_push(base_data, flags2, p,
1735 fname, PTR_DIFF(end_data, p),
1736 STR_TERMINATE_ASCII);
1737 SIVAL(q,0,len);
1738 p += len;
1740 len = PTR_DIFF(p, pdata);
1741 pad = (len + (align-1)) & ~(align-1);
1743 * offset to the next entry, the caller
1744 * will overwrite it for the last entry
1745 * that's why we always include the padding
1747 SIVAL(pdata,0,pad);
1749 * set padding to zero
1751 if (do_pad) {
1752 memset(p, 0, pad - len);
1753 p = pdata + pad;
1754 } else {
1755 p = pdata + len;
1757 break;
1759 case SMB_FIND_FILE_DIRECTORY_INFO:
1760 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1761 p += 4;
1762 SIVAL(p,0,reskey); p += 4;
1763 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1764 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1765 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1766 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1767 SOFF_T(p,0,file_size); p += 8;
1768 SOFF_T(p,0,allocation_size); p += 8;
1769 SIVAL(p,0,mode); p += 4;
1770 len = srvstr_push(base_data, flags2,
1771 p + 4, fname, PTR_DIFF(end_data, p+4),
1772 STR_TERMINATE_ASCII);
1773 SIVAL(p,0,len);
1774 p += 4 + len;
1776 len = PTR_DIFF(p, pdata);
1777 pad = (len + (align-1)) & ~(align-1);
1779 * offset to the next entry, the caller
1780 * will overwrite it for the last entry
1781 * that's why we always include the padding
1783 SIVAL(pdata,0,pad);
1785 * set padding to zero
1787 if (do_pad) {
1788 memset(p, 0, pad - len);
1789 p = pdata + pad;
1790 } else {
1791 p = pdata + len;
1793 break;
1795 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1796 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1797 p += 4;
1798 SIVAL(p,0,reskey); p += 4;
1799 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1800 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1801 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1802 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1803 SOFF_T(p,0,file_size); p += 8;
1804 SOFF_T(p,0,allocation_size); p += 8;
1805 SIVAL(p,0,mode); p += 4;
1806 q = p; p += 4; /* q is placeholder for name length. */
1808 unsigned int ea_size = estimate_ea_size(conn, NULL,
1809 smb_fname->base_name);
1810 SIVAL(p,0,ea_size); /* Extended attributes */
1811 p +=4;
1813 len = srvstr_push(base_data, flags2, p,
1814 fname, PTR_DIFF(end_data, p),
1815 STR_TERMINATE_ASCII);
1816 SIVAL(q, 0, len);
1817 p += len;
1819 len = PTR_DIFF(p, pdata);
1820 pad = (len + (align-1)) & ~(align-1);
1822 * offset to the next entry, the caller
1823 * will overwrite it for the last entry
1824 * that's why we always include the padding
1826 SIVAL(pdata,0,pad);
1828 * set padding to zero
1830 if (do_pad) {
1831 memset(p, 0, pad - len);
1832 p = pdata + pad;
1833 } else {
1834 p = pdata + len;
1836 break;
1838 case SMB_FIND_FILE_NAMES_INFO:
1839 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1840 p += 4;
1841 SIVAL(p,0,reskey); p += 4;
1842 p += 4;
1843 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1844 acl on a dir (tridge) */
1845 len = srvstr_push(base_data, flags2, p,
1846 fname, PTR_DIFF(end_data, p),
1847 STR_TERMINATE_ASCII);
1848 SIVAL(p, -4, len);
1849 p += len;
1851 len = PTR_DIFF(p, pdata);
1852 pad = (len + (align-1)) & ~(align-1);
1854 * offset to the next entry, the caller
1855 * will overwrite it for the last entry
1856 * that's why we always include the padding
1858 SIVAL(pdata,0,pad);
1860 * set padding to zero
1862 if (do_pad) {
1863 memset(p, 0, pad - len);
1864 p = pdata + pad;
1865 } else {
1866 p = pdata + len;
1868 break;
1870 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1871 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1872 p += 4;
1873 SIVAL(p,0,reskey); p += 4;
1874 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1875 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1876 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1877 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1878 SOFF_T(p,0,file_size); p += 8;
1879 SOFF_T(p,0,allocation_size); p += 8;
1880 SIVAL(p,0,mode); p += 4;
1881 q = p; p += 4; /* q is placeholder for name length. */
1883 unsigned int ea_size = estimate_ea_size(conn, NULL,
1884 smb_fname->base_name);
1885 SIVAL(p,0,ea_size); /* Extended attributes */
1886 p +=4;
1888 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1889 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1890 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1891 len = srvstr_push(base_data, flags2, p,
1892 fname, PTR_DIFF(end_data, p),
1893 STR_TERMINATE_ASCII);
1894 SIVAL(q, 0, len);
1895 p += len;
1897 len = PTR_DIFF(p, pdata);
1898 pad = (len + (align-1)) & ~(align-1);
1900 * offset to the next entry, the caller
1901 * will overwrite it for the last entry
1902 * that's why we always include the padding
1904 SIVAL(pdata,0,pad);
1906 * set padding to zero
1908 if (do_pad) {
1909 memset(p, 0, pad - len);
1910 p = pdata + pad;
1911 } else {
1912 p = pdata + len;
1914 break;
1916 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1917 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1918 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1919 p += 4;
1920 SIVAL(p,0,reskey); p += 4;
1921 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1922 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1923 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1924 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1925 SOFF_T(p,0,file_size); p += 8;
1926 SOFF_T(p,0,allocation_size); p += 8;
1927 SIVAL(p,0,mode); p += 4;
1928 q = p; p += 4; /* q is placeholder for name length */
1930 unsigned int ea_size = estimate_ea_size(conn, NULL,
1931 smb_fname->base_name);
1932 SIVAL(p,0,ea_size); /* Extended attributes */
1933 p +=4;
1935 /* Clear the short name buffer. This is
1936 * IMPORTANT as not doing so will trigger
1937 * a Win2k client bug. JRA.
1939 if (!was_8_3 && check_mangled_names) {
1940 char mangled_name[13]; /* mangled 8.3 name. */
1941 if (!name_to_8_3(fname,mangled_name,True,
1942 conn->params)) {
1943 /* Error - mangle failed ! */
1944 memset(mangled_name,'\0',12);
1946 mangled_name[12] = 0;
1947 len = srvstr_push(base_data, flags2,
1948 p+2, mangled_name, 24,
1949 STR_UPPER|STR_UNICODE);
1950 SSVAL(p, 0, len);
1951 if (len < 24) {
1952 memset(p + 2 + len,'\0',24 - len);
1954 SSVAL(p, 0, len);
1955 } else {
1956 memset(p,'\0',26);
1958 p += 26;
1959 SSVAL(p,0,0); p += 2; /* Reserved ? */
1960 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1961 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1962 len = srvstr_push(base_data, flags2, p,
1963 fname, PTR_DIFF(end_data, p),
1964 STR_TERMINATE_ASCII);
1965 SIVAL(q,0,len);
1966 p += len;
1968 len = PTR_DIFF(p, pdata);
1969 pad = (len + (align-1)) & ~(align-1);
1971 * offset to the next entry, the caller
1972 * will overwrite it for the last entry
1973 * that's why we always include the padding
1975 SIVAL(pdata,0,pad);
1977 * set padding to zero
1979 if (do_pad) {
1980 memset(p, 0, pad - len);
1981 p = pdata + pad;
1982 } else {
1983 p = pdata + len;
1985 break;
1987 /* CIFS UNIX Extension. */
1989 case SMB_FIND_FILE_UNIX:
1990 case SMB_FIND_FILE_UNIX_INFO2:
1991 p+= 4;
1992 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1994 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1996 if (info_level == SMB_FIND_FILE_UNIX) {
1997 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1998 p = store_file_unix_basic(conn, p,
1999 NULL, &smb_fname->st);
2000 len = srvstr_push(base_data, flags2, p,
2001 fname, PTR_DIFF(end_data, p),
2002 STR_TERMINATE);
2003 } else {
2004 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2005 p = store_file_unix_basic_info2(conn, p,
2006 NULL, &smb_fname->st);
2007 nameptr = p;
2008 p += 4;
2009 len = srvstr_push(base_data, flags2, p, fname,
2010 PTR_DIFF(end_data, p), 0);
2011 SIVAL(nameptr, 0, len);
2014 p += len;
2016 len = PTR_DIFF(p, pdata);
2017 pad = (len + (align-1)) & ~(align-1);
2019 * offset to the next entry, the caller
2020 * will overwrite it for the last entry
2021 * that's why we always include the padding
2023 SIVAL(pdata,0,pad);
2025 * set padding to zero
2027 if (do_pad) {
2028 memset(p, 0, pad - len);
2029 p = pdata + pad;
2030 } else {
2031 p = pdata + len;
2033 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2035 break;
2037 default:
2038 return false;
2041 if (PTR_DIFF(p,pdata) > space_remaining) {
2042 *out_of_space = true;
2043 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2044 "(wanted %u, had %d)\n",
2045 (unsigned int)PTR_DIFF(p,pdata),
2046 space_remaining ));
2047 return false; /* Not finished - just out of space */
2050 /* Setup the last entry pointer, as an offset from base_data */
2051 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2052 /* Advance the data pointer to the next slot */
2053 *ppdata = p;
2055 return true;
2058 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2059 connection_struct *conn,
2060 struct dptr_struct *dirptr,
2061 uint16 flags2,
2062 const char *path_mask,
2063 uint32 dirtype,
2064 int info_level,
2065 int requires_resume_key,
2066 bool dont_descend,
2067 bool ask_sharemode,
2068 uint8_t align,
2069 bool do_pad,
2070 char **ppdata,
2071 char *base_data,
2072 char *end_data,
2073 int space_remaining,
2074 bool *out_of_space,
2075 bool *got_exact_match,
2076 int *_last_entry_off,
2077 struct ea_list *name_list)
2079 const char *p;
2080 const char *mask = NULL;
2081 long prev_dirpos = 0;
2082 uint32_t mode = 0;
2083 char *fname = NULL;
2084 struct smb_filename *smb_fname = NULL;
2085 struct smbd_dirptr_lanman2_state state;
2086 bool ok;
2087 uint64_t last_entry_off = 0;
2089 ZERO_STRUCT(state);
2090 state.conn = conn;
2091 state.info_level = info_level;
2092 state.check_mangled_names = lp_manglednames(conn->params);
2093 state.has_wild = dptr_has_wild(dirptr);
2094 state.got_exact_match = false;
2096 *out_of_space = false;
2097 *got_exact_match = false;
2099 p = strrchr_m(path_mask,'/');
2100 if(p != NULL) {
2101 if(p[1] == '\0') {
2102 mask = "*.*";
2103 } else {
2104 mask = p+1;
2106 } else {
2107 mask = path_mask;
2110 ok = smbd_dirptr_get_entry(ctx,
2111 dirptr,
2112 mask,
2113 dirtype,
2114 dont_descend,
2115 ask_sharemode,
2116 smbd_dirptr_lanman2_match_fn,
2117 smbd_dirptr_lanman2_mode_fn,
2118 &state,
2119 &fname,
2120 &smb_fname,
2121 &mode,
2122 &prev_dirpos);
2123 if (!ok) {
2124 return false;
2127 *got_exact_match = state.got_exact_match;
2129 ok = smbd_marshall_dir_entry(ctx,
2130 conn,
2131 flags2,
2132 info_level,
2133 name_list,
2134 state.check_mangled_names,
2135 requires_resume_key,
2136 mode,
2137 fname,
2138 smb_fname,
2139 space_remaining,
2140 align,
2141 do_pad,
2142 base_data,
2143 ppdata,
2144 end_data,
2145 out_of_space,
2146 &last_entry_off);
2147 TALLOC_FREE(fname);
2148 TALLOC_FREE(smb_fname);
2149 if (*out_of_space) {
2150 dptr_SeekDir(dirptr, prev_dirpos);
2151 return false;
2153 if (!ok) {
2154 return false;
2157 *_last_entry_off = last_entry_off;
2158 return true;
2161 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2162 connection_struct *conn,
2163 struct dptr_struct *dirptr,
2164 uint16 flags2,
2165 const char *path_mask,
2166 uint32 dirtype,
2167 int info_level,
2168 bool requires_resume_key,
2169 bool dont_descend,
2170 bool ask_sharemode,
2171 char **ppdata,
2172 char *base_data,
2173 char *end_data,
2174 int space_remaining,
2175 bool *out_of_space,
2176 bool *got_exact_match,
2177 int *last_entry_off,
2178 struct ea_list *name_list)
2180 uint8_t align = 4;
2181 const bool do_pad = true;
2183 if (info_level >= 1 && info_level <= 3) {
2184 /* No alignment on earlier info levels. */
2185 align = 1;
2188 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2189 path_mask, dirtype, info_level,
2190 requires_resume_key, dont_descend, ask_sharemode,
2191 align, do_pad,
2192 ppdata, base_data, end_data,
2193 space_remaining,
2194 out_of_space, got_exact_match,
2195 last_entry_off, name_list);
2198 /****************************************************************************
2199 Reply to a TRANS2_FINDFIRST.
2200 ****************************************************************************/
2202 static void call_trans2findfirst(connection_struct *conn,
2203 struct smb_request *req,
2204 char **pparams, int total_params,
2205 char **ppdata, int total_data,
2206 unsigned int max_data_bytes)
2208 /* We must be careful here that we don't return more than the
2209 allowed number of data bytes. If this means returning fewer than
2210 maxentries then so be it. We assume that the redirector has
2211 enough room for the fixed number of parameter bytes it has
2212 requested. */
2213 struct smb_filename *smb_dname = NULL;
2214 char *params = *pparams;
2215 char *pdata = *ppdata;
2216 char *data_end;
2217 uint32 dirtype;
2218 int maxentries;
2219 uint16 findfirst_flags;
2220 bool close_after_first;
2221 bool close_if_end;
2222 bool requires_resume_key;
2223 int info_level;
2224 char *directory = NULL;
2225 char *mask = NULL;
2226 char *p;
2227 int last_entry_off=0;
2228 int dptr_num = -1;
2229 int numentries = 0;
2230 int i;
2231 bool finished = False;
2232 bool dont_descend = False;
2233 bool out_of_space = False;
2234 int space_remaining;
2235 bool mask_contains_wcard = False;
2236 struct ea_list *ea_list = NULL;
2237 NTSTATUS ntstatus = NT_STATUS_OK;
2238 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2239 TALLOC_CTX *ctx = talloc_tos();
2240 struct dptr_struct *dirptr = NULL;
2241 struct smbd_server_connection *sconn = smbd_server_conn;
2243 if (total_params < 13) {
2244 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2245 goto out;
2248 dirtype = SVAL(params,0);
2249 maxentries = SVAL(params,2);
2250 findfirst_flags = SVAL(params,4);
2251 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2252 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2253 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2254 info_level = SVAL(params,6);
2256 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2257 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2258 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2259 info_level, max_data_bytes));
2261 if (!maxentries) {
2262 /* W2K3 seems to treat zero as 1. */
2263 maxentries = 1;
2266 switch (info_level) {
2267 case SMB_FIND_INFO_STANDARD:
2268 case SMB_FIND_EA_SIZE:
2269 case SMB_FIND_EA_LIST:
2270 case SMB_FIND_FILE_DIRECTORY_INFO:
2271 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2272 case SMB_FIND_FILE_NAMES_INFO:
2273 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2274 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2275 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2276 break;
2277 case SMB_FIND_FILE_UNIX:
2278 case SMB_FIND_FILE_UNIX_INFO2:
2279 /* Always use filesystem for UNIX mtime query. */
2280 ask_sharemode = false;
2281 if (!lp_unix_extensions()) {
2282 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2283 goto out;
2285 break;
2286 default:
2287 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2288 goto out;
2291 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2292 params+12, total_params - 12,
2293 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2294 if (!NT_STATUS_IS_OK(ntstatus)) {
2295 reply_nterror(req, ntstatus);
2296 goto out;
2299 ntstatus = filename_convert(ctx, conn,
2300 req->flags2 & FLAGS2_DFS_PATHNAMES,
2301 directory,
2302 (UCF_SAVE_LCOMP |
2303 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2304 &mask_contains_wcard,
2305 &smb_dname);
2306 if (!NT_STATUS_IS_OK(ntstatus)) {
2307 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2308 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2309 ERRSRV, ERRbadpath);
2310 goto out;
2312 reply_nterror(req, ntstatus);
2313 goto out;
2316 mask = smb_dname->original_lcomp;
2318 directory = smb_dname->base_name;
2320 p = strrchr_m(directory,'/');
2321 if(p == NULL) {
2322 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2323 if((directory[0] == '.') && (directory[1] == '\0')) {
2324 mask = talloc_strdup(ctx,"*");
2325 if (!mask) {
2326 reply_nterror(req, NT_STATUS_NO_MEMORY);
2327 goto out;
2329 mask_contains_wcard = True;
2331 directory = talloc_strdup(talloc_tos(), "./");
2332 if (!directory) {
2333 reply_nterror(req, NT_STATUS_NO_MEMORY);
2334 goto out;
2336 } else {
2337 *p = 0;
2340 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2342 if (info_level == SMB_FIND_EA_LIST) {
2343 uint32 ea_size;
2345 if (total_data < 4) {
2346 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2347 goto out;
2350 ea_size = IVAL(pdata,0);
2351 if (ea_size != total_data) {
2352 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2353 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2354 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2355 goto out;
2358 if (!lp_ea_support(SNUM(conn))) {
2359 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2360 goto out;
2363 /* Pull out the list of names. */
2364 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2365 if (!ea_list) {
2366 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2367 goto out;
2371 *ppdata = (char *)SMB_REALLOC(
2372 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2373 if(*ppdata == NULL ) {
2374 reply_nterror(req, NT_STATUS_NO_MEMORY);
2375 goto out;
2377 pdata = *ppdata;
2378 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2380 /* Realloc the params space */
2381 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2382 if (*pparams == NULL) {
2383 reply_nterror(req, NT_STATUS_NO_MEMORY);
2384 goto out;
2386 params = *pparams;
2388 /* Save the wildcard match and attribs we are using on this directory -
2389 needed as lanman2 assumes these are being saved between calls */
2391 ntstatus = dptr_create(conn,
2392 directory,
2393 False,
2394 True,
2395 req->smbpid,
2396 mask,
2397 mask_contains_wcard,
2398 dirtype,
2399 &dirptr);
2401 if (!NT_STATUS_IS_OK(ntstatus)) {
2402 reply_nterror(req, ntstatus);
2403 goto out;
2406 dptr_num = dptr_dnum(dirptr);
2407 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2409 /* Initialize per TRANS2_FIND_FIRST operation data */
2410 dptr_init_search_op(dirptr);
2412 /* We don't need to check for VOL here as this is returned by
2413 a different TRANS2 call. */
2415 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2416 directory,lp_dontdescend(SNUM(conn))));
2417 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2418 dont_descend = True;
2420 p = pdata;
2421 space_remaining = max_data_bytes;
2422 out_of_space = False;
2424 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2425 bool got_exact_match = False;
2427 /* this is a heuristic to avoid seeking the dirptr except when
2428 absolutely necessary. It allows for a filename of about 40 chars */
2429 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2430 out_of_space = True;
2431 finished = False;
2432 } else {
2433 finished = !get_lanman2_dir_entry(ctx,
2434 conn,
2435 dirptr,
2436 req->flags2,
2437 mask,dirtype,info_level,
2438 requires_resume_key,dont_descend,
2439 ask_sharemode,
2440 &p,pdata,data_end,
2441 space_remaining, &out_of_space,
2442 &got_exact_match,
2443 &last_entry_off, ea_list);
2446 if (finished && out_of_space)
2447 finished = False;
2449 if (!finished && !out_of_space)
2450 numentries++;
2453 * As an optimisation if we know we aren't looking
2454 * for a wildcard name (ie. the name matches the wildcard exactly)
2455 * then we can finish on any (first) match.
2456 * This speeds up large directory searches. JRA.
2459 if(got_exact_match)
2460 finished = True;
2462 /* Ensure space_remaining never goes -ve. */
2463 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2464 space_remaining = 0;
2465 out_of_space = true;
2466 } else {
2467 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2471 /* Check if we can close the dirptr */
2472 if(close_after_first || (finished && close_if_end)) {
2473 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2474 dptr_close(sconn, &dptr_num);
2478 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2479 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2480 * the protocol level is less than NT1. Tested with smbclient. JRA.
2481 * This should fix the OS/2 client bug #2335.
2484 if(numentries == 0) {
2485 dptr_close(sconn, &dptr_num);
2486 if (get_Protocol() < PROTOCOL_NT1) {
2487 reply_force_doserror(req, ERRDOS, ERRnofiles);
2488 goto out;
2489 } else {
2490 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2491 ERRDOS, ERRbadfile);
2492 goto out;
2496 /* At this point pdata points to numentries directory entries. */
2498 /* Set up the return parameter block */
2499 SSVAL(params,0,dptr_num);
2500 SSVAL(params,2,numentries);
2501 SSVAL(params,4,finished);
2502 SSVAL(params,6,0); /* Never an EA error */
2503 SSVAL(params,8,last_entry_off);
2505 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2506 max_data_bytes);
2508 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2509 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2510 if (!directory) {
2511 reply_nterror(req, NT_STATUS_NO_MEMORY);
2515 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2516 smb_fn_name(req->cmd),
2517 mask, directory, dirtype, numentries ) );
2520 * Force a name mangle here to ensure that the
2521 * mask as an 8.3 name is top of the mangled cache.
2522 * The reasons for this are subtle. Don't remove
2523 * this code unless you know what you are doing
2524 * (see PR#13758). JRA.
2527 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2528 char mangled_name[13];
2529 name_to_8_3(mask, mangled_name, True, conn->params);
2531 out:
2532 TALLOC_FREE(smb_dname);
2533 return;
2536 /****************************************************************************
2537 Reply to a TRANS2_FINDNEXT.
2538 ****************************************************************************/
2540 static void call_trans2findnext(connection_struct *conn,
2541 struct smb_request *req,
2542 char **pparams, int total_params,
2543 char **ppdata, int total_data,
2544 unsigned int max_data_bytes)
2546 /* We must be careful here that we don't return more than the
2547 allowed number of data bytes. If this means returning fewer than
2548 maxentries then so be it. We assume that the redirector has
2549 enough room for the fixed number of parameter bytes it has
2550 requested. */
2551 char *params = *pparams;
2552 char *pdata = *ppdata;
2553 char *data_end;
2554 int dptr_num;
2555 int maxentries;
2556 uint16 info_level;
2557 uint32 resume_key;
2558 uint16 findnext_flags;
2559 bool close_after_request;
2560 bool close_if_end;
2561 bool requires_resume_key;
2562 bool continue_bit;
2563 bool mask_contains_wcard = False;
2564 char *resume_name = NULL;
2565 const char *mask = NULL;
2566 const char *directory = NULL;
2567 char *p = NULL;
2568 uint16 dirtype;
2569 int numentries = 0;
2570 int i, last_entry_off=0;
2571 bool finished = False;
2572 bool dont_descend = False;
2573 bool out_of_space = False;
2574 int space_remaining;
2575 struct ea_list *ea_list = NULL;
2576 NTSTATUS ntstatus = NT_STATUS_OK;
2577 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2578 TALLOC_CTX *ctx = talloc_tos();
2579 struct dptr_struct *dirptr;
2580 struct smbd_server_connection *sconn = smbd_server_conn;
2582 if (total_params < 13) {
2583 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2584 return;
2587 dptr_num = SVAL(params,0);
2588 maxentries = SVAL(params,2);
2589 info_level = SVAL(params,4);
2590 resume_key = IVAL(params,6);
2591 findnext_flags = SVAL(params,10);
2592 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2593 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2594 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2595 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2597 if (!continue_bit) {
2598 /* We only need resume_name if continue_bit is zero. */
2599 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2600 params+12,
2601 total_params - 12, STR_TERMINATE, &ntstatus,
2602 &mask_contains_wcard);
2603 if (!NT_STATUS_IS_OK(ntstatus)) {
2604 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2605 complain (it thinks we're asking for the directory above the shared
2606 path or an invalid name). Catch this as the resume name is only compared, never used in
2607 a file access. JRA. */
2608 srvstr_pull_talloc(ctx, params, req->flags2,
2609 &resume_name, params+12,
2610 total_params - 12,
2611 STR_TERMINATE);
2613 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2614 reply_nterror(req, ntstatus);
2615 return;
2620 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2621 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2622 resume_key = %d resume name = %s continue=%d level = %d\n",
2623 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2624 requires_resume_key, resume_key,
2625 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2627 if (!maxentries) {
2628 /* W2K3 seems to treat zero as 1. */
2629 maxentries = 1;
2632 switch (info_level) {
2633 case SMB_FIND_INFO_STANDARD:
2634 case SMB_FIND_EA_SIZE:
2635 case SMB_FIND_EA_LIST:
2636 case SMB_FIND_FILE_DIRECTORY_INFO:
2637 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2638 case SMB_FIND_FILE_NAMES_INFO:
2639 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2640 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2641 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2642 break;
2643 case SMB_FIND_FILE_UNIX:
2644 case SMB_FIND_FILE_UNIX_INFO2:
2645 /* Always use filesystem for UNIX mtime query. */
2646 ask_sharemode = false;
2647 if (!lp_unix_extensions()) {
2648 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2649 return;
2651 break;
2652 default:
2653 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2654 return;
2657 if (info_level == SMB_FIND_EA_LIST) {
2658 uint32 ea_size;
2660 if (total_data < 4) {
2661 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2662 return;
2665 ea_size = IVAL(pdata,0);
2666 if (ea_size != total_data) {
2667 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2668 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2669 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2670 return;
2673 if (!lp_ea_support(SNUM(conn))) {
2674 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2675 return;
2678 /* Pull out the list of names. */
2679 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2680 if (!ea_list) {
2681 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2682 return;
2686 *ppdata = (char *)SMB_REALLOC(
2687 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2688 if(*ppdata == NULL) {
2689 reply_nterror(req, NT_STATUS_NO_MEMORY);
2690 return;
2693 pdata = *ppdata;
2694 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2696 /* Realloc the params space */
2697 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2698 if(*pparams == NULL ) {
2699 reply_nterror(req, NT_STATUS_NO_MEMORY);
2700 return;
2703 params = *pparams;
2705 /* Check that the dptr is valid */
2706 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2707 reply_nterror(req, STATUS_NO_MORE_FILES);
2708 return;
2711 directory = dptr_path(sconn, dptr_num);
2713 /* Get the wildcard mask from the dptr */
2714 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2715 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2716 reply_nterror(req, STATUS_NO_MORE_FILES);
2717 return;
2720 mask = p;
2722 /* Get the attr mask from the dptr */
2723 dirtype = dptr_attr(sconn, dptr_num);
2725 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2726 dptr_num, mask, dirtype,
2727 (long)dirptr,
2728 dptr_TellDir(dirptr)));
2730 /* Initialize per TRANS2_FIND_NEXT operation data */
2731 dptr_init_search_op(dirptr);
2733 /* We don't need to check for VOL here as this is returned by
2734 a different TRANS2 call. */
2736 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2737 directory,lp_dontdescend(SNUM(conn))));
2738 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2739 dont_descend = True;
2741 p = pdata;
2742 space_remaining = max_data_bytes;
2743 out_of_space = False;
2746 * Seek to the correct position. We no longer use the resume key but
2747 * depend on the last file name instead.
2750 if(!continue_bit && resume_name && *resume_name) {
2751 SMB_STRUCT_STAT st;
2753 long current_pos = 0;
2755 * Remember, name_to_8_3 is called by
2756 * get_lanman2_dir_entry(), so the resume name
2757 * could be mangled. Ensure we check the unmangled name.
2760 if (mangle_is_mangled(resume_name, conn->params)) {
2761 char *new_resume_name = NULL;
2762 mangle_lookup_name_from_8_3(ctx,
2763 resume_name,
2764 &new_resume_name,
2765 conn->params);
2766 if (new_resume_name) {
2767 resume_name = new_resume_name;
2772 * Fix for NT redirector problem triggered by resume key indexes
2773 * changing between directory scans. We now return a resume key of 0
2774 * and instead look for the filename to continue from (also given
2775 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2776 * findfirst/findnext (as is usual) then the directory pointer
2777 * should already be at the correct place.
2780 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2781 } /* end if resume_name && !continue_bit */
2783 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2784 bool got_exact_match = False;
2786 /* this is a heuristic to avoid seeking the dirptr except when
2787 absolutely necessary. It allows for a filename of about 40 chars */
2788 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2789 out_of_space = True;
2790 finished = False;
2791 } else {
2792 finished = !get_lanman2_dir_entry(ctx,
2793 conn,
2794 dirptr,
2795 req->flags2,
2796 mask,dirtype,info_level,
2797 requires_resume_key,dont_descend,
2798 ask_sharemode,
2799 &p,pdata,data_end,
2800 space_remaining, &out_of_space,
2801 &got_exact_match,
2802 &last_entry_off, ea_list);
2805 if (finished && out_of_space)
2806 finished = False;
2808 if (!finished && !out_of_space)
2809 numentries++;
2812 * As an optimisation if we know we aren't looking
2813 * for a wildcard name (ie. the name matches the wildcard exactly)
2814 * then we can finish on any (first) match.
2815 * This speeds up large directory searches. JRA.
2818 if(got_exact_match)
2819 finished = True;
2821 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2824 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2825 smb_fn_name(req->cmd),
2826 mask, directory, dirtype, numentries ) );
2828 /* Check if we can close the dirptr */
2829 if(close_after_request || (finished && close_if_end)) {
2830 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2831 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2834 /* Set up the return parameter block */
2835 SSVAL(params,0,numentries);
2836 SSVAL(params,2,finished);
2837 SSVAL(params,4,0); /* Never an EA error */
2838 SSVAL(params,6,last_entry_off);
2840 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2841 max_data_bytes);
2843 return;
2846 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2848 E_md4hash(lp_servicename(SNUM(conn)),objid);
2849 return objid;
2852 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2854 SMB_ASSERT(extended_info != NULL);
2856 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2857 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2858 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2859 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2860 #ifdef SAMBA_VERSION_REVISION
2861 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2862 #endif
2863 extended_info->samba_subversion = 0;
2864 #ifdef SAMBA_VERSION_RC_RELEASE
2865 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2866 #else
2867 #ifdef SAMBA_VERSION_PRE_RELEASE
2868 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2869 #endif
2870 #endif
2871 #ifdef SAMBA_VERSION_VENDOR_PATCH
2872 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2873 #endif
2874 extended_info->samba_gitcommitdate = 0;
2875 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2876 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2877 #endif
2879 memset(extended_info->samba_version_string, 0,
2880 sizeof(extended_info->samba_version_string));
2882 snprintf (extended_info->samba_version_string,
2883 sizeof(extended_info->samba_version_string),
2884 "%s", samba_version_string());
2887 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2888 TALLOC_CTX *mem_ctx,
2889 uint16_t info_level,
2890 uint16_t flags2,
2891 unsigned int max_data_bytes,
2892 char **ppdata,
2893 int *ret_data_len)
2895 char *pdata, *end_data;
2896 int data_len = 0, len;
2897 const char *vname = volume_label(SNUM(conn));
2898 int snum = SNUM(conn);
2899 char *fstype = lp_fstype(SNUM(conn));
2900 uint32 additional_flags = 0;
2901 struct smb_filename smb_fname_dot;
2902 SMB_STRUCT_STAT st;
2904 if (IS_IPC(conn)) {
2905 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2906 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2907 "info level (0x%x) on IPC$.\n",
2908 (unsigned int)info_level));
2909 return NT_STATUS_ACCESS_DENIED;
2913 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2915 ZERO_STRUCT(smb_fname_dot);
2916 smb_fname_dot.base_name = discard_const_p(char, ".");
2918 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2919 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2920 return map_nt_error_from_unix(errno);
2923 st = smb_fname_dot.st;
2925 *ppdata = (char *)SMB_REALLOC(
2926 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2927 if (*ppdata == NULL) {
2928 return NT_STATUS_NO_MEMORY;
2931 pdata = *ppdata;
2932 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2933 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2935 switch (info_level) {
2936 case SMB_INFO_ALLOCATION:
2938 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2939 data_len = 18;
2940 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2941 return map_nt_error_from_unix(errno);
2944 block_size = lp_block_size(snum);
2945 if (bsize < block_size) {
2946 uint64_t factor = block_size/bsize;
2947 bsize = block_size;
2948 dsize /= factor;
2949 dfree /= factor;
2951 if (bsize > block_size) {
2952 uint64_t factor = bsize/block_size;
2953 bsize = block_size;
2954 dsize *= factor;
2955 dfree *= factor;
2957 bytes_per_sector = 512;
2958 sectors_per_unit = bsize/bytes_per_sector;
2960 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2961 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2962 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2964 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2965 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2966 SIVAL(pdata,l1_cUnit,dsize);
2967 SIVAL(pdata,l1_cUnitAvail,dfree);
2968 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2969 break;
2972 case SMB_INFO_VOLUME:
2973 /* Return volume name */
2975 * Add volume serial number - hash of a combination of
2976 * the called hostname and the service name.
2978 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2980 * Win2k3 and previous mess this up by sending a name length
2981 * one byte short. I believe only older clients (OS/2 Win9x) use
2982 * this call so try fixing this by adding a terminating null to
2983 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2985 len = srvstr_push(
2986 pdata, flags2,
2987 pdata+l2_vol_szVolLabel, vname,
2988 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2989 STR_NOALIGN|STR_TERMINATE);
2990 SCVAL(pdata,l2_vol_cch,len);
2991 data_len = l2_vol_szVolLabel + len;
2992 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2993 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2994 len, vname));
2995 break;
2997 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2998 case SMB_FS_ATTRIBUTE_INFORMATION:
3000 additional_flags = 0;
3001 #if defined(HAVE_SYS_QUOTAS)
3002 additional_flags |= FILE_VOLUME_QUOTAS;
3003 #endif
3005 if(lp_nt_acl_support(SNUM(conn))) {
3006 additional_flags |= FILE_PERSISTENT_ACLS;
3009 /* Capabilities are filled in at connection time through STATVFS call */
3010 additional_flags |= conn->fs_capabilities;
3011 additional_flags |= lp_parm_int(conn->params->service,
3012 "share", "fake_fscaps",
3015 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3016 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3017 additional_flags); /* FS ATTRIBUTES */
3019 SIVAL(pdata,4,255); /* Max filename component length */
3020 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3021 and will think we can't do long filenames */
3022 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3023 PTR_DIFF(end_data, pdata+12),
3024 STR_UNICODE);
3025 SIVAL(pdata,8,len);
3026 data_len = 12 + len;
3027 break;
3029 case SMB_QUERY_FS_LABEL_INFO:
3030 case SMB_FS_LABEL_INFORMATION:
3031 len = srvstr_push(pdata, flags2, pdata+4, vname,
3032 PTR_DIFF(end_data, pdata+4), 0);
3033 data_len = 4 + len;
3034 SIVAL(pdata,0,len);
3035 break;
3037 case SMB_QUERY_FS_VOLUME_INFO:
3038 case SMB_FS_VOLUME_INFORMATION:
3041 * Add volume serial number - hash of a combination of
3042 * the called hostname and the service name.
3044 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3045 (str_checksum(get_local_machine_name())<<16));
3047 /* Max label len is 32 characters. */
3048 len = srvstr_push(pdata, flags2, pdata+18, vname,
3049 PTR_DIFF(end_data, pdata+18),
3050 STR_UNICODE);
3051 SIVAL(pdata,12,len);
3052 data_len = 18+len;
3054 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3055 (int)strlen(vname),vname, lp_servicename(snum)));
3056 break;
3058 case SMB_QUERY_FS_SIZE_INFO:
3059 case SMB_FS_SIZE_INFORMATION:
3061 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3062 data_len = 24;
3063 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3064 return map_nt_error_from_unix(errno);
3066 block_size = lp_block_size(snum);
3067 if (bsize < block_size) {
3068 uint64_t factor = block_size/bsize;
3069 bsize = block_size;
3070 dsize /= factor;
3071 dfree /= factor;
3073 if (bsize > block_size) {
3074 uint64_t factor = bsize/block_size;
3075 bsize = block_size;
3076 dsize *= factor;
3077 dfree *= factor;
3079 bytes_per_sector = 512;
3080 sectors_per_unit = bsize/bytes_per_sector;
3081 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3082 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3083 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3084 SBIG_UINT(pdata,0,dsize);
3085 SBIG_UINT(pdata,8,dfree);
3086 SIVAL(pdata,16,sectors_per_unit);
3087 SIVAL(pdata,20,bytes_per_sector);
3088 break;
3091 case SMB_FS_FULL_SIZE_INFORMATION:
3093 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3094 data_len = 32;
3095 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3096 return map_nt_error_from_unix(errno);
3098 block_size = lp_block_size(snum);
3099 if (bsize < block_size) {
3100 uint64_t factor = block_size/bsize;
3101 bsize = block_size;
3102 dsize /= factor;
3103 dfree /= factor;
3105 if (bsize > block_size) {
3106 uint64_t factor = bsize/block_size;
3107 bsize = block_size;
3108 dsize *= factor;
3109 dfree *= factor;
3111 bytes_per_sector = 512;
3112 sectors_per_unit = bsize/bytes_per_sector;
3113 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3114 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3115 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3116 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3117 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3118 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3119 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3120 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3121 break;
3124 case SMB_QUERY_FS_DEVICE_INFO:
3125 case SMB_FS_DEVICE_INFORMATION:
3126 data_len = 8;
3127 SIVAL(pdata,0,0); /* dev type */
3128 SIVAL(pdata,4,0); /* characteristics */
3129 break;
3131 #ifdef HAVE_SYS_QUOTAS
3132 case SMB_FS_QUOTA_INFORMATION:
3134 * what we have to send --metze:
3136 * Unknown1: 24 NULL bytes
3137 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3138 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3139 * Quota Flags: 2 byte :
3140 * Unknown3: 6 NULL bytes
3142 * 48 bytes total
3144 * details for Quota Flags:
3146 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3147 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3148 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3149 * 0x0001 Enable Quotas: enable quota for this fs
3153 /* we need to fake up a fsp here,
3154 * because its not send in this call
3156 files_struct fsp;
3157 SMB_NTQUOTA_STRUCT quotas;
3159 ZERO_STRUCT(fsp);
3160 ZERO_STRUCT(quotas);
3162 fsp.conn = conn;
3163 fsp.fnum = -1;
3165 /* access check */
3166 if (conn->server_info->utok.uid != sec_initial_uid()) {
3167 DEBUG(0,("set_user_quota: access_denied "
3168 "service [%s] user [%s]\n",
3169 lp_servicename(SNUM(conn)),
3170 conn->server_info->unix_name));
3171 return NT_STATUS_ACCESS_DENIED;
3174 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3175 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3176 return map_nt_error_from_unix(errno);
3179 data_len = 48;
3181 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3182 lp_servicename(SNUM(conn))));
3184 /* Unknown1 24 NULL bytes*/
3185 SBIG_UINT(pdata,0,(uint64_t)0);
3186 SBIG_UINT(pdata,8,(uint64_t)0);
3187 SBIG_UINT(pdata,16,(uint64_t)0);
3189 /* Default Soft Quota 8 bytes */
3190 SBIG_UINT(pdata,24,quotas.softlim);
3192 /* Default Hard Quota 8 bytes */
3193 SBIG_UINT(pdata,32,quotas.hardlim);
3195 /* Quota flag 2 bytes */
3196 SSVAL(pdata,40,quotas.qflags);
3198 /* Unknown3 6 NULL bytes */
3199 SSVAL(pdata,42,0);
3200 SIVAL(pdata,44,0);
3202 break;
3204 #endif /* HAVE_SYS_QUOTAS */
3205 case SMB_FS_OBJECTID_INFORMATION:
3207 unsigned char objid[16];
3208 struct smb_extended_info extended_info;
3209 memcpy(pdata,create_volume_objectid(conn, objid),16);
3210 samba_extended_info_version (&extended_info);
3211 SIVAL(pdata,16,extended_info.samba_magic);
3212 SIVAL(pdata,20,extended_info.samba_version);
3213 SIVAL(pdata,24,extended_info.samba_subversion);
3214 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3215 memcpy(pdata+36,extended_info.samba_version_string,28);
3216 data_len = 64;
3217 break;
3221 * Query the version and capabilities of the CIFS UNIX extensions
3222 * in use.
3225 case SMB_QUERY_CIFS_UNIX_INFO:
3227 bool large_write = lp_min_receive_file_size() &&
3228 !srv_is_signing_active(smbd_server_conn);
3229 bool large_read = !srv_is_signing_active(smbd_server_conn);
3230 int encrypt_caps = 0;
3232 if (!lp_unix_extensions()) {
3233 return NT_STATUS_INVALID_LEVEL;
3236 switch (conn->encrypt_level) {
3237 case 0:
3238 encrypt_caps = 0;
3239 break;
3240 case 1:
3241 case Auto:
3242 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3243 break;
3244 case Required:
3245 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3246 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3247 large_write = false;
3248 large_read = false;
3249 break;
3252 data_len = 12;
3253 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3254 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3256 /* We have POSIX ACLs, pathname, encryption,
3257 * large read/write, and locking capability. */
3259 SBIG_UINT(pdata,4,((uint64_t)(
3260 CIFS_UNIX_POSIX_ACLS_CAP|
3261 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3262 CIFS_UNIX_FCNTL_LOCKS_CAP|
3263 CIFS_UNIX_EXTATTR_CAP|
3264 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3265 encrypt_caps|
3266 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3267 (large_write ?
3268 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3269 break;
3272 case SMB_QUERY_POSIX_FS_INFO:
3274 int rc;
3275 vfs_statvfs_struct svfs;
3277 if (!lp_unix_extensions()) {
3278 return NT_STATUS_INVALID_LEVEL;
3281 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3283 if (!rc) {
3284 data_len = 56;
3285 SIVAL(pdata,0,svfs.OptimalTransferSize);
3286 SIVAL(pdata,4,svfs.BlockSize);
3287 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3288 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3289 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3290 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3291 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3292 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3293 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3294 #ifdef EOPNOTSUPP
3295 } else if (rc == EOPNOTSUPP) {
3296 return NT_STATUS_INVALID_LEVEL;
3297 #endif /* EOPNOTSUPP */
3298 } else {
3299 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3300 return NT_STATUS_DOS(ERRSRV, ERRerror);
3302 break;
3305 case SMB_QUERY_POSIX_WHOAMI:
3307 uint32_t flags = 0;
3308 uint32_t sid_bytes;
3309 int i;
3311 if (!lp_unix_extensions()) {
3312 return NT_STATUS_INVALID_LEVEL;
3315 if (max_data_bytes < 40) {
3316 return NT_STATUS_BUFFER_TOO_SMALL;
3319 /* We ARE guest if global_sid_Builtin_Guests is
3320 * in our list of SIDs.
3322 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3323 conn->server_info->ptok)) {
3324 flags |= SMB_WHOAMI_GUEST;
3327 /* We are NOT guest if global_sid_Authenticated_Users
3328 * is in our list of SIDs.
3330 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3331 conn->server_info->ptok)) {
3332 flags &= ~SMB_WHOAMI_GUEST;
3335 /* NOTE: 8 bytes for UID/GID, irrespective of native
3336 * platform size. This matches
3337 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3339 data_len = 4 /* flags */
3340 + 4 /* flag mask */
3341 + 8 /* uid */
3342 + 8 /* gid */
3343 + 4 /* ngroups */
3344 + 4 /* num_sids */
3345 + 4 /* SID bytes */
3346 + 4 /* pad/reserved */
3347 + (conn->server_info->utok.ngroups * 8)
3348 /* groups list */
3349 + (conn->server_info->ptok->num_sids *
3350 SID_MAX_SIZE)
3351 /* SID list */;
3353 SIVAL(pdata, 0, flags);
3354 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3355 SBIG_UINT(pdata, 8,
3356 (uint64_t)conn->server_info->utok.uid);
3357 SBIG_UINT(pdata, 16,
3358 (uint64_t)conn->server_info->utok.gid);
3361 if (data_len >= max_data_bytes) {
3362 /* Potential overflow, skip the GIDs and SIDs. */
3364 SIVAL(pdata, 24, 0); /* num_groups */
3365 SIVAL(pdata, 28, 0); /* num_sids */
3366 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3367 SIVAL(pdata, 36, 0); /* reserved */
3369 data_len = 40;
3370 break;
3373 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3374 SIVAL(pdata, 28, conn->server_info->num_sids);
3376 /* We walk the SID list twice, but this call is fairly
3377 * infrequent, and I don't expect that it's performance
3378 * sensitive -- jpeach
3380 for (i = 0, sid_bytes = 0;
3381 i < conn->server_info->ptok->num_sids; ++i) {
3382 sid_bytes += ndr_size_dom_sid(
3383 &conn->server_info->ptok->user_sids[i],
3387 /* SID list byte count */
3388 SIVAL(pdata, 32, sid_bytes);
3390 /* 4 bytes pad/reserved - must be zero */
3391 SIVAL(pdata, 36, 0);
3392 data_len = 40;
3394 /* GID list */
3395 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3396 SBIG_UINT(pdata, data_len,
3397 (uint64_t)conn->server_info->utok.groups[i]);
3398 data_len += 8;
3401 /* SID list */
3402 for (i = 0;
3403 i < conn->server_info->ptok->num_sids; ++i) {
3404 int sid_len = ndr_size_dom_sid(
3405 &conn->server_info->ptok->user_sids[i],
3408 sid_linearize(pdata + data_len, sid_len,
3409 &conn->server_info->ptok->user_sids[i]);
3410 data_len += sid_len;
3413 break;
3416 case SMB_MAC_QUERY_FS_INFO:
3418 * Thursby MAC extension... ONLY on NTFS filesystems
3419 * once we do streams then we don't need this
3421 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3422 data_len = 88;
3423 SIVAL(pdata,84,0x100); /* Don't support mac... */
3424 break;
3426 /* drop through */
3427 default:
3428 return NT_STATUS_INVALID_LEVEL;
3431 *ret_data_len = data_len;
3432 return NT_STATUS_OK;
3435 /****************************************************************************
3436 Reply to a TRANS2_QFSINFO (query filesystem info).
3437 ****************************************************************************/
3439 static void call_trans2qfsinfo(connection_struct *conn,
3440 struct smb_request *req,
3441 char **pparams, int total_params,
3442 char **ppdata, int total_data,
3443 unsigned int max_data_bytes)
3445 char *params = *pparams;
3446 uint16_t info_level;
3447 int data_len = 0;
3448 NTSTATUS status;
3450 if (total_params < 2) {
3451 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3452 return;
3455 info_level = SVAL(params,0);
3457 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3458 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3459 DEBUG(0,("call_trans2qfsinfo: encryption required "
3460 "and info level 0x%x sent.\n",
3461 (unsigned int)info_level));
3462 exit_server_cleanly("encryption required "
3463 "on connection");
3464 return;
3468 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3470 status = smbd_do_qfsinfo(conn, req,
3471 info_level,
3472 req->flags2,
3473 max_data_bytes,
3474 ppdata, &data_len);
3475 if (!NT_STATUS_IS_OK(status)) {
3476 reply_nterror(req, status);
3477 return;
3480 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3481 max_data_bytes);
3483 DEBUG( 4, ( "%s info_level = %d\n",
3484 smb_fn_name(req->cmd), info_level) );
3486 return;
3489 /****************************************************************************
3490 Reply to a TRANS2_SETFSINFO (set filesystem info).
3491 ****************************************************************************/
3493 static void call_trans2setfsinfo(connection_struct *conn,
3494 struct smb_request *req,
3495 char **pparams, int total_params,
3496 char **ppdata, int total_data,
3497 unsigned int max_data_bytes)
3499 char *pdata = *ppdata;
3500 char *params = *pparams;
3501 uint16 info_level;
3503 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3505 /* */
3506 if (total_params < 4) {
3507 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3508 total_params));
3509 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3510 return;
3513 info_level = SVAL(params,2);
3515 if (IS_IPC(conn)) {
3516 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3517 info_level != SMB_SET_CIFS_UNIX_INFO) {
3518 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3519 "info level (0x%x) on IPC$.\n",
3520 (unsigned int)info_level));
3521 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3522 return;
3526 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3527 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3528 DEBUG(0,("call_trans2setfsinfo: encryption required "
3529 "and info level 0x%x sent.\n",
3530 (unsigned int)info_level));
3531 exit_server_cleanly("encryption required "
3532 "on connection");
3533 return;
3537 switch(info_level) {
3538 case SMB_SET_CIFS_UNIX_INFO:
3540 uint16 client_unix_major;
3541 uint16 client_unix_minor;
3542 uint32 client_unix_cap_low;
3543 uint32 client_unix_cap_high;
3545 if (!lp_unix_extensions()) {
3546 reply_nterror(req,
3547 NT_STATUS_INVALID_LEVEL);
3548 return;
3551 /* There should be 12 bytes of capabilities set. */
3552 if (total_data < 8) {
3553 reply_nterror(
3554 req,
3555 NT_STATUS_INVALID_PARAMETER);
3556 return;
3558 client_unix_major = SVAL(pdata,0);
3559 client_unix_minor = SVAL(pdata,2);
3560 client_unix_cap_low = IVAL(pdata,4);
3561 client_unix_cap_high = IVAL(pdata,8);
3562 /* Just print these values for now. */
3563 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3564 cap_low = 0x%x, cap_high = 0x%x\n",
3565 (unsigned int)client_unix_major,
3566 (unsigned int)client_unix_minor,
3567 (unsigned int)client_unix_cap_low,
3568 (unsigned int)client_unix_cap_high ));
3570 /* Here is where we must switch to posix pathname processing... */
3571 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3572 lp_set_posix_pathnames();
3573 mangle_change_to_posix();
3576 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3577 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3578 /* Client that knows how to do posix locks,
3579 * but not posix open/mkdir operations. Set a
3580 * default type for read/write checks. */
3582 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3585 break;
3588 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3590 NTSTATUS status;
3591 size_t param_len = 0;
3592 size_t data_len = total_data;
3594 if (!lp_unix_extensions()) {
3595 reply_nterror(
3596 req,
3597 NT_STATUS_INVALID_LEVEL);
3598 return;
3601 if (lp_smb_encrypt(SNUM(conn)) == false) {
3602 reply_nterror(
3603 req,
3604 NT_STATUS_NOT_SUPPORTED);
3605 return;
3608 if (smbd_server_conn->smb1.echo_handler.trusted_fde) {
3609 DEBUG( 2,("call_trans2setfsinfo: "
3610 "request transport encryption disabled"
3611 "with 'fork echo handler = yes'\n"));
3612 reply_nterror(
3613 req,
3614 NT_STATUS_NOT_SUPPORTED);
3615 return;
3618 DEBUG( 4,("call_trans2setfsinfo: "
3619 "request transport encryption.\n"));
3621 status = srv_request_encryption_setup(conn,
3622 (unsigned char **)ppdata,
3623 &data_len,
3624 (unsigned char **)pparams,
3625 &param_len);
3627 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3628 !NT_STATUS_IS_OK(status)) {
3629 reply_nterror(req, status);
3630 return;
3633 send_trans2_replies(conn, req,
3634 *pparams,
3635 param_len,
3636 *ppdata,
3637 data_len,
3638 max_data_bytes);
3640 if (NT_STATUS_IS_OK(status)) {
3641 /* Server-side transport
3642 * encryption is now *on*. */
3643 status = srv_encryption_start(conn);
3644 if (!NT_STATUS_IS_OK(status)) {
3645 exit_server_cleanly(
3646 "Failure in setting "
3647 "up encrypted transport");
3650 return;
3653 case SMB_FS_QUOTA_INFORMATION:
3655 files_struct *fsp = NULL;
3656 SMB_NTQUOTA_STRUCT quotas;
3658 ZERO_STRUCT(quotas);
3660 /* access check */
3661 if ((conn->server_info->utok.uid != sec_initial_uid())
3662 ||!CAN_WRITE(conn)) {
3663 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3664 lp_servicename(SNUM(conn)),
3665 conn->server_info->unix_name));
3666 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3667 return;
3670 /* note: normaly there're 48 bytes,
3671 * but we didn't use the last 6 bytes for now
3672 * --metze
3674 fsp = file_fsp(req, SVAL(params,0));
3676 if (!check_fsp_ntquota_handle(conn, req,
3677 fsp)) {
3678 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3679 reply_nterror(
3680 req, NT_STATUS_INVALID_HANDLE);
3681 return;
3684 if (total_data < 42) {
3685 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3686 total_data));
3687 reply_nterror(
3688 req,
3689 NT_STATUS_INVALID_PARAMETER);
3690 return;
3693 /* unknown_1 24 NULL bytes in pdata*/
3695 /* the soft quotas 8 bytes (uint64_t)*/
3696 quotas.softlim = (uint64_t)IVAL(pdata,24);
3697 #ifdef LARGE_SMB_OFF_T
3698 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3699 #else /* LARGE_SMB_OFF_T */
3700 if ((IVAL(pdata,28) != 0)&&
3701 ((quotas.softlim != 0xFFFFFFFF)||
3702 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3703 /* more than 32 bits? */
3704 reply_nterror(
3705 req,
3706 NT_STATUS_INVALID_PARAMETER);
3707 return;
3709 #endif /* LARGE_SMB_OFF_T */
3711 /* the hard quotas 8 bytes (uint64_t)*/
3712 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3713 #ifdef LARGE_SMB_OFF_T
3714 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3715 #else /* LARGE_SMB_OFF_T */
3716 if ((IVAL(pdata,36) != 0)&&
3717 ((quotas.hardlim != 0xFFFFFFFF)||
3718 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3719 /* more than 32 bits? */
3720 reply_nterror(
3721 req,
3722 NT_STATUS_INVALID_PARAMETER);
3723 return;
3725 #endif /* LARGE_SMB_OFF_T */
3727 /* quota_flags 2 bytes **/
3728 quotas.qflags = SVAL(pdata,40);
3730 /* unknown_2 6 NULL bytes follow*/
3732 /* now set the quotas */
3733 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3734 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3735 reply_nterror(req, map_nt_error_from_unix(errno));
3736 return;
3739 break;
3741 default:
3742 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3743 info_level));
3744 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3745 return;
3746 break;
3750 * sending this reply works fine,
3751 * but I'm not sure it's the same
3752 * like windows do...
3753 * --metze
3755 reply_outbuf(req, 10, 0);
3758 #if defined(HAVE_POSIX_ACLS)
3759 /****************************************************************************
3760 Utility function to count the number of entries in a POSIX acl.
3761 ****************************************************************************/
3763 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3765 unsigned int ace_count = 0;
3766 int entry_id = SMB_ACL_FIRST_ENTRY;
3767 SMB_ACL_ENTRY_T entry;
3769 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3770 /* get_next... */
3771 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3772 entry_id = SMB_ACL_NEXT_ENTRY;
3774 ace_count++;
3776 return ace_count;
3779 /****************************************************************************
3780 Utility function to marshall a POSIX acl into wire format.
3781 ****************************************************************************/
3783 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3785 int entry_id = SMB_ACL_FIRST_ENTRY;
3786 SMB_ACL_ENTRY_T entry;
3788 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3789 SMB_ACL_TAG_T tagtype;
3790 SMB_ACL_PERMSET_T permset;
3791 unsigned char perms = 0;
3792 unsigned int own_grp;
3794 /* get_next... */
3795 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3796 entry_id = SMB_ACL_NEXT_ENTRY;
3799 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3800 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3801 return False;
3804 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3805 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3806 return False;
3809 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3810 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3811 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3813 SCVAL(pdata,1,perms);
3815 switch (tagtype) {
3816 case SMB_ACL_USER_OBJ:
3817 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3818 own_grp = (unsigned int)pst->st_ex_uid;
3819 SIVAL(pdata,2,own_grp);
3820 SIVAL(pdata,6,0);
3821 break;
3822 case SMB_ACL_USER:
3824 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3825 if (!puid) {
3826 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3827 return False;
3829 own_grp = (unsigned int)*puid;
3830 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3831 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3832 SIVAL(pdata,2,own_grp);
3833 SIVAL(pdata,6,0);
3834 break;
3836 case SMB_ACL_GROUP_OBJ:
3837 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3838 own_grp = (unsigned int)pst->st_ex_gid;
3839 SIVAL(pdata,2,own_grp);
3840 SIVAL(pdata,6,0);
3841 break;
3842 case SMB_ACL_GROUP:
3844 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3845 if (!pgid) {
3846 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3847 return False;
3849 own_grp = (unsigned int)*pgid;
3850 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3851 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3852 SIVAL(pdata,2,own_grp);
3853 SIVAL(pdata,6,0);
3854 break;
3856 case SMB_ACL_MASK:
3857 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3858 SIVAL(pdata,2,0xFFFFFFFF);
3859 SIVAL(pdata,6,0xFFFFFFFF);
3860 break;
3861 case SMB_ACL_OTHER:
3862 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3863 SIVAL(pdata,2,0xFFFFFFFF);
3864 SIVAL(pdata,6,0xFFFFFFFF);
3865 break;
3866 default:
3867 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3868 return False;
3870 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3873 return True;
3875 #endif
3877 /****************************************************************************
3878 Store the FILE_UNIX_BASIC info.
3879 ****************************************************************************/
3881 static char *store_file_unix_basic(connection_struct *conn,
3882 char *pdata,
3883 files_struct *fsp,
3884 const SMB_STRUCT_STAT *psbuf)
3886 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3887 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3889 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3890 pdata += 8;
3892 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3893 pdata += 8;
3895 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3896 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3897 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3898 pdata += 24;
3900 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3901 SIVAL(pdata,4,0);
3902 pdata += 8;
3904 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3905 SIVAL(pdata,4,0);
3906 pdata += 8;
3908 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3909 pdata += 4;
3911 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3912 SIVAL(pdata,4,0);
3913 pdata += 8;
3915 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3916 SIVAL(pdata,4,0);
3917 pdata += 8;
3919 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3920 pdata += 8;
3922 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3923 SIVAL(pdata,4,0);
3924 pdata += 8;
3926 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3927 SIVAL(pdata,4,0);
3928 pdata += 8;
3930 return pdata;
3933 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3934 * the chflags(2) (or equivalent) flags.
3936 * XXX: this really should be behind the VFS interface. To do this, we would
3937 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3938 * Each VFS module could then implement its own mapping as appropriate for the
3939 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3941 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3942 info2_flags_map[] =
3944 #ifdef UF_NODUMP
3945 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3946 #endif
3948 #ifdef UF_IMMUTABLE
3949 { UF_IMMUTABLE, EXT_IMMUTABLE },
3950 #endif
3952 #ifdef UF_APPEND
3953 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3954 #endif
3956 #ifdef UF_HIDDEN
3957 { UF_HIDDEN, EXT_HIDDEN },
3958 #endif
3960 /* Do not remove. We need to guarantee that this array has at least one
3961 * entry to build on HP-UX.
3963 { 0, 0 }
3967 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3968 uint32 *smb_fflags, uint32 *smb_fmask)
3970 int i;
3972 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3973 *smb_fmask |= info2_flags_map[i].smb_fflag;
3974 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3975 *smb_fflags |= info2_flags_map[i].smb_fflag;
3980 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3981 const uint32 smb_fflags,
3982 const uint32 smb_fmask,
3983 int *stat_fflags)
3985 uint32 max_fmask = 0;
3986 int i;
3988 *stat_fflags = psbuf->st_ex_flags;
3990 /* For each flags requested in smb_fmask, check the state of the
3991 * corresponding flag in smb_fflags and set or clear the matching
3992 * stat flag.
3995 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3996 max_fmask |= info2_flags_map[i].smb_fflag;
3997 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3998 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3999 *stat_fflags |= info2_flags_map[i].stat_fflag;
4000 } else {
4001 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4006 /* If smb_fmask is asking to set any bits that are not supported by
4007 * our flag mappings, we should fail.
4009 if ((smb_fmask & max_fmask) != smb_fmask) {
4010 return False;
4013 return True;
4017 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4018 * of file flags and birth (create) time.
4020 static char *store_file_unix_basic_info2(connection_struct *conn,
4021 char *pdata,
4022 files_struct *fsp,
4023 const SMB_STRUCT_STAT *psbuf)
4025 uint32 file_flags = 0;
4026 uint32 flags_mask = 0;
4028 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4030 /* Create (birth) time 64 bit */
4031 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4032 pdata += 8;
4034 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4035 SIVAL(pdata, 0, file_flags); /* flags */
4036 SIVAL(pdata, 4, flags_mask); /* mask */
4037 pdata += 8;
4039 return pdata;
4042 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4043 const struct stream_struct *streams,
4044 char *data,
4045 unsigned int max_data_bytes,
4046 unsigned int *data_size)
4048 unsigned int i;
4049 unsigned int ofs = 0;
4051 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4052 unsigned int next_offset;
4053 size_t namelen;
4054 smb_ucs2_t *namebuf;
4056 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4057 streams[i].name, &namelen) ||
4058 namelen <= 2)
4060 return NT_STATUS_INVALID_PARAMETER;
4064 * name_buf is now null-terminated, we need to marshall as not
4065 * terminated
4068 namelen -= 2;
4070 SIVAL(data, ofs+4, namelen);
4071 SOFF_T(data, ofs+8, streams[i].size);
4072 SOFF_T(data, ofs+16, streams[i].alloc_size);
4073 memcpy(data+ofs+24, namebuf, namelen);
4074 TALLOC_FREE(namebuf);
4076 next_offset = ofs + 24 + namelen;
4078 if (i == num_streams-1) {
4079 SIVAL(data, ofs, 0);
4081 else {
4082 unsigned int align = ndr_align_size(next_offset, 8);
4084 memset(data+next_offset, 0, align);
4085 next_offset += align;
4087 SIVAL(data, ofs, next_offset - ofs);
4088 ofs = next_offset;
4091 ofs = next_offset;
4094 *data_size = ofs;
4096 return NT_STATUS_OK;
4099 /****************************************************************************
4100 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4101 ****************************************************************************/
4103 static void call_trans2qpipeinfo(connection_struct *conn,
4104 struct smb_request *req,
4105 unsigned int tran_call,
4106 char **pparams, int total_params,
4107 char **ppdata, int total_data,
4108 unsigned int max_data_bytes)
4110 char *params = *pparams;
4111 char *pdata = *ppdata;
4112 unsigned int data_size = 0;
4113 unsigned int param_size = 2;
4114 uint16 info_level;
4115 files_struct *fsp;
4117 if (!params) {
4118 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4119 return;
4122 if (total_params < 4) {
4123 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4124 return;
4127 fsp = file_fsp(req, SVAL(params,0));
4128 if (!fsp_is_np(fsp)) {
4129 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4130 return;
4133 info_level = SVAL(params,2);
4135 *pparams = (char *)SMB_REALLOC(*pparams,2);
4136 if (*pparams == NULL) {
4137 reply_nterror(req, NT_STATUS_NO_MEMORY);
4138 return;
4140 params = *pparams;
4141 SSVAL(params,0,0);
4142 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4143 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4144 if (*ppdata == NULL ) {
4145 reply_nterror(req, NT_STATUS_NO_MEMORY);
4146 return;
4148 pdata = *ppdata;
4150 switch (info_level) {
4151 case SMB_FILE_STANDARD_INFORMATION:
4152 memset(pdata,0,24);
4153 SOFF_T(pdata,0,4096LL);
4154 SIVAL(pdata,16,1);
4155 SIVAL(pdata,20,1);
4156 data_size = 24;
4157 break;
4159 default:
4160 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4161 return;
4164 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4165 max_data_bytes);
4167 return;
4170 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4171 TALLOC_CTX *mem_ctx,
4172 uint16_t info_level,
4173 files_struct *fsp,
4174 struct smb_filename *smb_fname,
4175 bool delete_pending,
4176 struct timespec write_time_ts,
4177 struct ea_list *ea_list,
4178 int lock_data_count,
4179 char *lock_data,
4180 uint16_t flags2,
4181 unsigned int max_data_bytes,
4182 char **ppdata,
4183 unsigned int *pdata_size)
4185 char *pdata = *ppdata;
4186 char *dstart, *dend;
4187 unsigned int data_size;
4188 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4189 time_t create_time, mtime, atime, c_time;
4190 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4191 char *p;
4192 char *base_name;
4193 char *dos_fname;
4194 int mode;
4195 int nlink;
4196 NTSTATUS status;
4197 uint64_t file_size = 0;
4198 uint64_t pos = 0;
4199 uint64_t allocation_size = 0;
4200 uint64_t file_index = 0;
4201 uint32_t access_mask = 0;
4203 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4204 return NT_STATUS_INVALID_LEVEL;
4207 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4208 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4209 info_level, max_data_bytes));
4211 mode = dos_mode(conn, smb_fname);
4212 nlink = psbuf->st_ex_nlink;
4214 if (nlink && (mode&aDIR)) {
4215 nlink = 1;
4218 if ((nlink > 0) && delete_pending) {
4219 nlink -= 1;
4222 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4223 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4224 if (*ppdata == NULL) {
4225 return NT_STATUS_NO_MEMORY;
4227 pdata = *ppdata;
4228 dstart = pdata;
4229 dend = dstart + data_size - 1;
4231 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4232 update_stat_ex_mtime(psbuf, write_time_ts);
4235 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4236 mtime_ts = psbuf->st_ex_mtime;
4237 atime_ts = psbuf->st_ex_atime;
4238 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4240 if (lp_dos_filetime_resolution(SNUM(conn))) {
4241 dos_filetime_timespec(&create_time_ts);
4242 dos_filetime_timespec(&mtime_ts);
4243 dos_filetime_timespec(&atime_ts);
4244 dos_filetime_timespec(&ctime_ts);
4247 create_time = convert_timespec_to_time_t(create_time_ts);
4248 mtime = convert_timespec_to_time_t(mtime_ts);
4249 atime = convert_timespec_to_time_t(atime_ts);
4250 c_time = convert_timespec_to_time_t(ctime_ts);
4252 p = strrchr_m(smb_fname->base_name,'/');
4253 if (!p)
4254 base_name = smb_fname->base_name;
4255 else
4256 base_name = p+1;
4258 /* NT expects the name to be in an exact form of the *full*
4259 filename. See the trans2 torture test */
4260 if (ISDOT(base_name)) {
4261 dos_fname = talloc_strdup(mem_ctx, "\\");
4262 if (!dos_fname) {
4263 return NT_STATUS_NO_MEMORY;
4265 } else {
4266 dos_fname = talloc_asprintf(mem_ctx,
4267 "\\%s",
4268 smb_fname->base_name);
4269 if (!dos_fname) {
4270 return NT_STATUS_NO_MEMORY;
4272 if (is_ntfs_stream_smb_fname(smb_fname)) {
4273 dos_fname = talloc_asprintf(dos_fname, "%s",
4274 smb_fname->stream_name);
4275 if (!dos_fname) {
4276 return NT_STATUS_NO_MEMORY;
4280 string_replace(dos_fname, '/', '\\');
4283 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4285 if (!fsp) {
4286 /* Do we have this path open ? */
4287 files_struct *fsp1;
4288 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4289 fsp1 = file_find_di_first(fileid);
4290 if (fsp1 && fsp1->initial_allocation_size) {
4291 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4295 if (!(mode & aDIR)) {
4296 file_size = get_file_size_stat(psbuf);
4299 if (fsp) {
4300 pos = fsp->fh->position_information;
4303 if (fsp) {
4304 access_mask = fsp->access_mask;
4305 } else {
4306 /* GENERIC_EXECUTE mapping from Windows */
4307 access_mask = 0x12019F;
4310 /* This should be an index number - looks like
4311 dev/ino to me :-)
4313 I think this causes us to fail the IFSKIT
4314 BasicFileInformationTest. -tpot */
4315 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4316 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4318 switch (info_level) {
4319 case SMB_INFO_STANDARD:
4320 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4321 data_size = 22;
4322 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4323 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4324 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4325 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4326 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4327 SSVAL(pdata,l1_attrFile,mode);
4328 break;
4330 case SMB_INFO_QUERY_EA_SIZE:
4332 unsigned int ea_size =
4333 estimate_ea_size(conn, fsp,
4334 smb_fname->base_name);
4335 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4336 data_size = 26;
4337 srv_put_dos_date2(pdata,0,create_time);
4338 srv_put_dos_date2(pdata,4,atime);
4339 srv_put_dos_date2(pdata,8,mtime); /* write time */
4340 SIVAL(pdata,12,(uint32)file_size);
4341 SIVAL(pdata,16,(uint32)allocation_size);
4342 SSVAL(pdata,20,mode);
4343 SIVAL(pdata,22,ea_size);
4344 break;
4347 case SMB_INFO_IS_NAME_VALID:
4348 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4349 if (fsp) {
4350 /* os/2 needs this ? really ?*/
4351 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4353 /* This is only reached for qpathinfo */
4354 data_size = 0;
4355 break;
4357 case SMB_INFO_QUERY_EAS_FROM_LIST:
4359 size_t total_ea_len = 0;
4360 struct ea_list *ea_file_list = NULL;
4362 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4364 ea_file_list =
4365 get_ea_list_from_file(mem_ctx, conn, fsp,
4366 smb_fname->base_name,
4367 &total_ea_len);
4368 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4370 if (!ea_list || (total_ea_len > data_size)) {
4371 data_size = 4;
4372 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4373 break;
4376 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4377 break;
4380 case SMB_INFO_QUERY_ALL_EAS:
4382 /* We have data_size bytes to put EA's into. */
4383 size_t total_ea_len = 0;
4385 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4387 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4388 smb_fname->base_name,
4389 &total_ea_len);
4390 if (!ea_list || (total_ea_len > data_size)) {
4391 data_size = 4;
4392 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4393 break;
4396 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4397 break;
4400 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4402 /* This is FileFullEaInformation - 0xF which maps to
4403 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4405 /* We have data_size bytes to put EA's into. */
4406 size_t total_ea_len = 0;
4407 struct ea_list *ea_file_list = NULL;
4409 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4411 /*TODO: add filtering and index handling */
4413 ea_file_list =
4414 get_ea_list_from_file(mem_ctx, conn, fsp,
4415 smb_fname->base_name,
4416 &total_ea_len);
4417 if (!ea_file_list) {
4418 return NT_STATUS_NO_EAS_ON_FILE;
4421 status = fill_ea_chained_buffer(mem_ctx,
4422 pdata,
4423 data_size,
4424 &data_size,
4425 conn, ea_file_list);
4426 if (!NT_STATUS_IS_OK(status)) {
4427 return status;
4429 break;
4432 case SMB_FILE_BASIC_INFORMATION:
4433 case SMB_QUERY_FILE_BASIC_INFO:
4435 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4436 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4437 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4438 } else {
4439 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4440 data_size = 40;
4441 SIVAL(pdata,36,0);
4443 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4444 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4445 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4446 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4447 SIVAL(pdata,32,mode);
4449 DEBUG(5,("SMB_QFBI - "));
4450 DEBUG(5,("create: %s ", ctime(&create_time)));
4451 DEBUG(5,("access: %s ", ctime(&atime)));
4452 DEBUG(5,("write: %s ", ctime(&mtime)));
4453 DEBUG(5,("change: %s ", ctime(&c_time)));
4454 DEBUG(5,("mode: %x\n", mode));
4455 break;
4457 case SMB_FILE_STANDARD_INFORMATION:
4458 case SMB_QUERY_FILE_STANDARD_INFO:
4460 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4461 data_size = 24;
4462 SOFF_T(pdata,0,allocation_size);
4463 SOFF_T(pdata,8,file_size);
4464 SIVAL(pdata,16,nlink);
4465 SCVAL(pdata,20,delete_pending?1:0);
4466 SCVAL(pdata,21,(mode&aDIR)?1:0);
4467 SSVAL(pdata,22,0); /* Padding. */
4468 break;
4470 case SMB_FILE_EA_INFORMATION:
4471 case SMB_QUERY_FILE_EA_INFO:
4473 unsigned int ea_size =
4474 estimate_ea_size(conn, fsp, smb_fname->base_name);
4475 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4476 data_size = 4;
4477 SIVAL(pdata,0,ea_size);
4478 break;
4481 /* Get the 8.3 name - used if NT SMB was negotiated. */
4482 case SMB_QUERY_FILE_ALT_NAME_INFO:
4483 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4485 int len;
4486 char mangled_name[13];
4487 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4488 if (!name_to_8_3(base_name,mangled_name,
4489 True,conn->params)) {
4490 return NT_STATUS_NO_MEMORY;
4492 len = srvstr_push(dstart, flags2,
4493 pdata+4, mangled_name,
4494 PTR_DIFF(dend, pdata+4),
4495 STR_UNICODE);
4496 data_size = 4 + len;
4497 SIVAL(pdata,0,len);
4498 break;
4501 case SMB_QUERY_FILE_NAME_INFO:
4503 int len;
4505 this must be *exactly* right for ACLs on mapped drives to work
4507 len = srvstr_push(dstart, flags2,
4508 pdata+4, dos_fname,
4509 PTR_DIFF(dend, pdata+4),
4510 STR_UNICODE);
4511 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4512 data_size = 4 + len;
4513 SIVAL(pdata,0,len);
4514 break;
4517 case SMB_FILE_ALLOCATION_INFORMATION:
4518 case SMB_QUERY_FILE_ALLOCATION_INFO:
4519 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4520 data_size = 8;
4521 SOFF_T(pdata,0,allocation_size);
4522 break;
4524 case SMB_FILE_END_OF_FILE_INFORMATION:
4525 case SMB_QUERY_FILE_END_OF_FILEINFO:
4526 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4527 data_size = 8;
4528 SOFF_T(pdata,0,file_size);
4529 break;
4531 case SMB_QUERY_FILE_ALL_INFO:
4532 case SMB_FILE_ALL_INFORMATION:
4534 int len;
4535 unsigned int ea_size =
4536 estimate_ea_size(conn, fsp, smb_fname->base_name);
4537 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4538 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4539 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4540 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4541 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4542 SIVAL(pdata,32,mode);
4543 SIVAL(pdata,36,0); /* padding. */
4544 pdata += 40;
4545 SOFF_T(pdata,0,allocation_size);
4546 SOFF_T(pdata,8,file_size);
4547 SIVAL(pdata,16,nlink);
4548 SCVAL(pdata,20,delete_pending);
4549 SCVAL(pdata,21,(mode&aDIR)?1:0);
4550 SSVAL(pdata,22,0);
4551 pdata += 24;
4552 SIVAL(pdata,0,ea_size);
4553 pdata += 4; /* EA info */
4554 len = srvstr_push(dstart, flags2,
4555 pdata+4, dos_fname,
4556 PTR_DIFF(dend, pdata+4),
4557 STR_UNICODE);
4558 SIVAL(pdata,0,len);
4559 pdata += 4 + len;
4560 data_size = PTR_DIFF(pdata,(*ppdata));
4561 break;
4564 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4566 int len;
4567 unsigned int ea_size =
4568 estimate_ea_size(conn, fsp, smb_fname->base_name);
4569 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4570 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4571 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4572 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4573 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4574 SIVAL(pdata, 0x20, mode);
4575 SIVAL(pdata, 0x24, 0); /* padding. */
4576 SBVAL(pdata, 0x28, allocation_size);
4577 SBVAL(pdata, 0x30, file_size);
4578 SIVAL(pdata, 0x38, nlink);
4579 SCVAL(pdata, 0x3C, delete_pending);
4580 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4581 SSVAL(pdata, 0x3E, 0); /* padding */
4582 SBVAL(pdata, 0x40, file_index);
4583 SIVAL(pdata, 0x48, ea_size);
4584 SIVAL(pdata, 0x4C, access_mask);
4585 SBVAL(pdata, 0x50, pos);
4586 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4587 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4589 pdata += 0x60;
4591 len = srvstr_push(dstart, flags2,
4592 pdata+4, dos_fname,
4593 PTR_DIFF(dend, pdata+4),
4594 STR_UNICODE);
4595 SIVAL(pdata,0,len);
4596 pdata += 4 + len;
4597 data_size = PTR_DIFF(pdata,(*ppdata));
4598 break;
4600 case SMB_FILE_INTERNAL_INFORMATION:
4602 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4603 SBVAL(pdata, 0, file_index);
4604 data_size = 8;
4605 break;
4607 case SMB_FILE_ACCESS_INFORMATION:
4608 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4609 SIVAL(pdata, 0, access_mask);
4610 data_size = 4;
4611 break;
4613 case SMB_FILE_NAME_INFORMATION:
4614 /* Pathname with leading '\'. */
4616 size_t byte_len;
4617 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4618 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4619 SIVAL(pdata,0,byte_len);
4620 data_size = 4 + byte_len;
4621 break;
4624 case SMB_FILE_DISPOSITION_INFORMATION:
4625 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4626 data_size = 1;
4627 SCVAL(pdata,0,delete_pending);
4628 break;
4630 case SMB_FILE_POSITION_INFORMATION:
4631 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4632 data_size = 8;
4633 SOFF_T(pdata,0,pos);
4634 break;
4636 case SMB_FILE_MODE_INFORMATION:
4637 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4638 SIVAL(pdata,0,mode);
4639 data_size = 4;
4640 break;
4642 case SMB_FILE_ALIGNMENT_INFORMATION:
4643 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4644 SIVAL(pdata,0,0); /* No alignment needed. */
4645 data_size = 4;
4646 break;
4649 * NT4 server just returns "invalid query" to this - if we try
4650 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4651 * want this. JRA.
4653 /* The first statement above is false - verified using Thursby
4654 * client against NT4 -- gcolley.
4656 case SMB_QUERY_FILE_STREAM_INFO:
4657 case SMB_FILE_STREAM_INFORMATION: {
4658 unsigned int num_streams;
4659 struct stream_struct *streams;
4661 DEBUG(10,("smbd_do_qfilepathinfo: "
4662 "SMB_FILE_STREAM_INFORMATION\n"));
4664 if (is_ntfs_stream_smb_fname(smb_fname)) {
4665 return NT_STATUS_INVALID_PARAMETER;
4668 status = SMB_VFS_STREAMINFO(
4669 conn, fsp, smb_fname->base_name, talloc_tos(),
4670 &num_streams, &streams);
4672 if (!NT_STATUS_IS_OK(status)) {
4673 DEBUG(10, ("could not get stream info: %s\n",
4674 nt_errstr(status)));
4675 return status;
4678 status = marshall_stream_info(num_streams, streams,
4679 pdata, max_data_bytes,
4680 &data_size);
4682 if (!NT_STATUS_IS_OK(status)) {
4683 DEBUG(10, ("marshall_stream_info failed: %s\n",
4684 nt_errstr(status)));
4685 return status;
4688 TALLOC_FREE(streams);
4690 break;
4692 case SMB_QUERY_COMPRESSION_INFO:
4693 case SMB_FILE_COMPRESSION_INFORMATION:
4694 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4695 SOFF_T(pdata,0,file_size);
4696 SIVAL(pdata,8,0); /* ??? */
4697 SIVAL(pdata,12,0); /* ??? */
4698 data_size = 16;
4699 break;
4701 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4702 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4703 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4704 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4705 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4706 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4707 SOFF_T(pdata,32,allocation_size);
4708 SOFF_T(pdata,40,file_size);
4709 SIVAL(pdata,48,mode);
4710 SIVAL(pdata,52,0); /* ??? */
4711 data_size = 56;
4712 break;
4714 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4715 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4716 SIVAL(pdata,0,mode);
4717 SIVAL(pdata,4,0);
4718 data_size = 8;
4719 break;
4722 * CIFS UNIX Extensions.
4725 case SMB_QUERY_FILE_UNIX_BASIC:
4727 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4728 data_size = PTR_DIFF(pdata,(*ppdata));
4731 int i;
4732 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4734 for (i=0; i<100; i++)
4735 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4736 DEBUG(4,("\n"));
4739 break;
4741 case SMB_QUERY_FILE_UNIX_INFO2:
4743 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4744 data_size = PTR_DIFF(pdata,(*ppdata));
4747 int i;
4748 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4750 for (i=0; i<100; i++)
4751 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4752 DEBUG(4,("\n"));
4755 break;
4757 case SMB_QUERY_FILE_UNIX_LINK:
4759 int len;
4760 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4762 if (!buffer) {
4763 return NT_STATUS_NO_MEMORY;
4766 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4767 #ifdef S_ISLNK
4768 if(!S_ISLNK(psbuf->st_ex_mode)) {
4769 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4771 #else
4772 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4773 #endif
4774 len = SMB_VFS_READLINK(conn,
4775 smb_fname->base_name,
4776 buffer, PATH_MAX);
4777 if (len == -1) {
4778 return map_nt_error_from_unix(errno);
4780 buffer[len] = 0;
4781 len = srvstr_push(dstart, flags2,
4782 pdata, buffer,
4783 PTR_DIFF(dend, pdata),
4784 STR_TERMINATE);
4785 pdata += len;
4786 data_size = PTR_DIFF(pdata,(*ppdata));
4788 break;
4791 #if defined(HAVE_POSIX_ACLS)
4792 case SMB_QUERY_POSIX_ACL:
4794 SMB_ACL_T file_acl = NULL;
4795 SMB_ACL_T def_acl = NULL;
4796 uint16 num_file_acls = 0;
4797 uint16 num_def_acls = 0;
4799 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4800 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4801 } else {
4802 file_acl =
4803 SMB_VFS_SYS_ACL_GET_FILE(conn,
4804 smb_fname->base_name,
4805 SMB_ACL_TYPE_ACCESS);
4808 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4809 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4810 "not implemented on "
4811 "filesystem containing %s\n",
4812 smb_fname->base_name));
4813 return NT_STATUS_NOT_IMPLEMENTED;
4816 if (S_ISDIR(psbuf->st_ex_mode)) {
4817 if (fsp && fsp->is_directory) {
4818 def_acl =
4819 SMB_VFS_SYS_ACL_GET_FILE(
4820 conn,
4821 fsp->fsp_name->base_name,
4822 SMB_ACL_TYPE_DEFAULT);
4823 } else {
4824 def_acl =
4825 SMB_VFS_SYS_ACL_GET_FILE(
4826 conn,
4827 smb_fname->base_name,
4828 SMB_ACL_TYPE_DEFAULT);
4830 def_acl = free_empty_sys_acl(conn, def_acl);
4833 num_file_acls = count_acl_entries(conn, file_acl);
4834 num_def_acls = count_acl_entries(conn, def_acl);
4836 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4837 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4838 data_size,
4839 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4840 SMB_POSIX_ACL_HEADER_SIZE) ));
4841 if (file_acl) {
4842 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4844 if (def_acl) {
4845 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4847 return NT_STATUS_BUFFER_TOO_SMALL;
4850 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4851 SSVAL(pdata,2,num_file_acls);
4852 SSVAL(pdata,4,num_def_acls);
4853 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4854 if (file_acl) {
4855 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4857 if (def_acl) {
4858 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4860 return NT_STATUS_INTERNAL_ERROR;
4862 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4863 if (file_acl) {
4864 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4866 if (def_acl) {
4867 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4869 return NT_STATUS_INTERNAL_ERROR;
4872 if (file_acl) {
4873 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4875 if (def_acl) {
4876 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4878 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4879 break;
4881 #endif
4884 case SMB_QUERY_POSIX_LOCK:
4886 uint64_t count;
4887 uint64_t offset;
4888 uint64_t smblctx;
4889 enum brl_type lock_type;
4891 /* We need an open file with a real fd for this. */
4892 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4893 return NT_STATUS_INVALID_LEVEL;
4896 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4897 return NT_STATUS_INVALID_PARAMETER;
4900 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4901 case POSIX_LOCK_TYPE_READ:
4902 lock_type = READ_LOCK;
4903 break;
4904 case POSIX_LOCK_TYPE_WRITE:
4905 lock_type = WRITE_LOCK;
4906 break;
4907 case POSIX_LOCK_TYPE_UNLOCK:
4908 default:
4909 /* There's no point in asking for an unlock... */
4910 return NT_STATUS_INVALID_PARAMETER;
4913 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4914 #if defined(HAVE_LONGLONG)
4915 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4916 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4917 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4918 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4919 #else /* HAVE_LONGLONG */
4920 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4921 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4922 #endif /* HAVE_LONGLONG */
4924 status = query_lock(fsp,
4925 &smblctx,
4926 &count,
4927 &offset,
4928 &lock_type,
4929 POSIX_LOCK);
4931 if (ERROR_WAS_LOCK_DENIED(status)) {
4932 /* Here we need to report who has it locked... */
4933 data_size = POSIX_LOCK_DATA_SIZE;
4935 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4936 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4937 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4938 #if defined(HAVE_LONGLONG)
4939 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4940 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4941 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4942 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4943 #else /* HAVE_LONGLONG */
4944 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4945 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4946 #endif /* HAVE_LONGLONG */
4948 } else if (NT_STATUS_IS_OK(status)) {
4949 /* For success we just return a copy of what we sent
4950 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4951 data_size = POSIX_LOCK_DATA_SIZE;
4952 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4953 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4954 } else {
4955 return status;
4957 break;
4960 default:
4961 return NT_STATUS_INVALID_LEVEL;
4964 *pdata_size = data_size;
4965 return NT_STATUS_OK;
4968 /****************************************************************************
4969 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4970 file name or file id).
4971 ****************************************************************************/
4973 static void call_trans2qfilepathinfo(connection_struct *conn,
4974 struct smb_request *req,
4975 unsigned int tran_call,
4976 char **pparams, int total_params,
4977 char **ppdata, int total_data,
4978 unsigned int max_data_bytes)
4980 char *params = *pparams;
4981 char *pdata = *ppdata;
4982 uint16 info_level;
4983 unsigned int data_size = 0;
4984 unsigned int param_size = 2;
4985 struct smb_filename *smb_fname = NULL;
4986 bool delete_pending = False;
4987 struct timespec write_time_ts;
4988 files_struct *fsp = NULL;
4989 struct file_id fileid;
4990 struct ea_list *ea_list = NULL;
4991 int lock_data_count = 0;
4992 char *lock_data = NULL;
4993 NTSTATUS status = NT_STATUS_OK;
4995 if (!params) {
4996 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4997 return;
5000 ZERO_STRUCT(write_time_ts);
5002 if (tran_call == TRANSACT2_QFILEINFO) {
5003 if (total_params < 4) {
5004 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5005 return;
5008 if (IS_IPC(conn)) {
5009 call_trans2qpipeinfo(conn, req, tran_call,
5010 pparams, total_params,
5011 ppdata, total_data,
5012 max_data_bytes);
5013 return;
5016 fsp = file_fsp(req, SVAL(params,0));
5017 info_level = SVAL(params,2);
5019 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5021 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5022 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5023 return;
5026 /* Initial check for valid fsp ptr. */
5027 if (!check_fsp_open(conn, req, fsp)) {
5028 return;
5031 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5032 &smb_fname);
5033 if (!NT_STATUS_IS_OK(status)) {
5034 reply_nterror(req, status);
5035 return;
5038 if(fsp->fake_file_handle) {
5040 * This is actually for the QUOTA_FAKE_FILE --metze
5043 /* We know this name is ok, it's already passed the checks. */
5045 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5047 * This is actually a QFILEINFO on a directory
5048 * handle (returned from an NT SMB). NT5.0 seems
5049 * to do this call. JRA.
5052 if (INFO_LEVEL_IS_UNIX(info_level)) {
5053 /* Always do lstat for UNIX calls. */
5054 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5055 DEBUG(3,("call_trans2qfilepathinfo: "
5056 "SMB_VFS_LSTAT of %s failed "
5057 "(%s)\n",
5058 smb_fname_str_dbg(smb_fname),
5059 strerror(errno)));
5060 reply_nterror(req,
5061 map_nt_error_from_unix(errno));
5062 return;
5064 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5065 DEBUG(3,("call_trans2qfilepathinfo: "
5066 "SMB_VFS_STAT of %s failed (%s)\n",
5067 smb_fname_str_dbg(smb_fname),
5068 strerror(errno)));
5069 reply_nterror(req,
5070 map_nt_error_from_unix(errno));
5071 return;
5074 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5075 get_file_infos(fileid, &delete_pending, &write_time_ts);
5076 } else {
5078 * Original code - this is an open file.
5080 if (!check_fsp(conn, req, fsp)) {
5081 return;
5084 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5085 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5086 fsp->fnum, strerror(errno)));
5087 reply_nterror(req,
5088 map_nt_error_from_unix(errno));
5089 return;
5091 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5092 get_file_infos(fileid, &delete_pending, &write_time_ts);
5095 } else {
5096 char *fname = NULL;
5098 /* qpathinfo */
5099 if (total_params < 7) {
5100 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5101 return;
5104 info_level = SVAL(params,0);
5106 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5108 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5109 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5110 return;
5113 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5114 total_params - 6,
5115 STR_TERMINATE, &status);
5116 if (!NT_STATUS_IS_OK(status)) {
5117 reply_nterror(req, status);
5118 return;
5121 status = filename_convert(req,
5122 conn,
5123 req->flags2 & FLAGS2_DFS_PATHNAMES,
5124 fname,
5126 NULL,
5127 &smb_fname);
5128 if (!NT_STATUS_IS_OK(status)) {
5129 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5130 reply_botherror(req,
5131 NT_STATUS_PATH_NOT_COVERED,
5132 ERRSRV, ERRbadpath);
5133 return;
5135 reply_nterror(req, status);
5136 return;
5139 /* If this is a stream, check if there is a delete_pending. */
5140 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5141 && is_ntfs_stream_smb_fname(smb_fname)) {
5142 struct smb_filename *smb_fname_base = NULL;
5144 /* Create an smb_filename with stream_name == NULL. */
5145 status =
5146 create_synthetic_smb_fname(talloc_tos(),
5147 smb_fname->base_name,
5148 NULL, NULL,
5149 &smb_fname_base);
5150 if (!NT_STATUS_IS_OK(status)) {
5151 reply_nterror(req, status);
5152 return;
5155 if (INFO_LEVEL_IS_UNIX(info_level)) {
5156 /* Always do lstat for UNIX calls. */
5157 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5158 DEBUG(3,("call_trans2qfilepathinfo: "
5159 "SMB_VFS_LSTAT of %s failed "
5160 "(%s)\n",
5161 smb_fname_str_dbg(smb_fname_base),
5162 strerror(errno)));
5163 TALLOC_FREE(smb_fname_base);
5164 reply_nterror(req,
5165 map_nt_error_from_unix(errno));
5166 return;
5168 } else {
5169 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5170 DEBUG(3,("call_trans2qfilepathinfo: "
5171 "fileinfo of %s failed "
5172 "(%s)\n",
5173 smb_fname_str_dbg(smb_fname_base),
5174 strerror(errno)));
5175 TALLOC_FREE(smb_fname_base);
5176 reply_nterror(req,
5177 map_nt_error_from_unix(errno));
5178 return;
5182 fileid = vfs_file_id_from_sbuf(conn,
5183 &smb_fname_base->st);
5184 TALLOC_FREE(smb_fname_base);
5185 get_file_infos(fileid, &delete_pending, NULL);
5186 if (delete_pending) {
5187 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5188 return;
5192 if (INFO_LEVEL_IS_UNIX(info_level)) {
5193 /* Always do lstat for UNIX calls. */
5194 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5195 DEBUG(3,("call_trans2qfilepathinfo: "
5196 "SMB_VFS_LSTAT of %s failed (%s)\n",
5197 smb_fname_str_dbg(smb_fname),
5198 strerror(errno)));
5199 reply_nterror(req,
5200 map_nt_error_from_unix(errno));
5201 return;
5204 } else {
5205 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5206 DEBUG(3,("call_trans2qfilepathinfo: "
5207 "SMB_VFS_STAT of %s failed (%s)\n",
5208 smb_fname_str_dbg(smb_fname),
5209 strerror(errno)));
5210 reply_nterror(req,
5211 map_nt_error_from_unix(errno));
5212 return;
5216 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5217 get_file_infos(fileid, &delete_pending, &write_time_ts);
5218 if (delete_pending) {
5219 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5220 return;
5224 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5225 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5226 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5228 /* Pull out any data sent here before we realloc. */
5229 switch (info_level) {
5230 case SMB_INFO_QUERY_EAS_FROM_LIST:
5232 /* Pull any EA list from the data portion. */
5233 uint32 ea_size;
5235 if (total_data < 4) {
5236 reply_nterror(
5237 req, NT_STATUS_INVALID_PARAMETER);
5238 return;
5240 ea_size = IVAL(pdata,0);
5242 if (total_data > 0 && ea_size != total_data) {
5243 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5244 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5245 reply_nterror(
5246 req, NT_STATUS_INVALID_PARAMETER);
5247 return;
5250 if (!lp_ea_support(SNUM(conn))) {
5251 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5252 return;
5255 /* Pull out the list of names. */
5256 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5257 if (!ea_list) {
5258 reply_nterror(
5259 req, NT_STATUS_INVALID_PARAMETER);
5260 return;
5262 break;
5265 case SMB_QUERY_POSIX_LOCK:
5267 if (fsp == NULL || fsp->fh->fd == -1) {
5268 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5269 return;
5272 if (total_data != POSIX_LOCK_DATA_SIZE) {
5273 reply_nterror(
5274 req, NT_STATUS_INVALID_PARAMETER);
5275 return;
5278 /* Copy the lock range data. */
5279 lock_data = (char *)TALLOC_MEMDUP(
5280 req, pdata, total_data);
5281 if (!lock_data) {
5282 reply_nterror(req, NT_STATUS_NO_MEMORY);
5283 return;
5285 lock_data_count = total_data;
5287 default:
5288 break;
5291 *pparams = (char *)SMB_REALLOC(*pparams,2);
5292 if (*pparams == NULL) {
5293 reply_nterror(req, NT_STATUS_NO_MEMORY);
5294 return;
5296 params = *pparams;
5297 SSVAL(params,0,0);
5300 * draft-leach-cifs-v1-spec-02.txt
5301 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5302 * says:
5304 * The requested information is placed in the Data portion of the
5305 * transaction response. For the information levels greater than 0x100,
5306 * the transaction response has 1 parameter word which should be
5307 * ignored by the client.
5309 * However Windows only follows this rule for the IS_NAME_VALID call.
5311 switch (info_level) {
5312 case SMB_INFO_IS_NAME_VALID:
5313 param_size = 0;
5314 break;
5317 if ((info_level & 0xFF00) == 0xFF00) {
5319 * We use levels that start with 0xFF00
5320 * internally to represent SMB2 specific levels
5322 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5323 return;
5326 status = smbd_do_qfilepathinfo(conn, req, info_level,
5327 fsp, smb_fname,
5328 delete_pending, write_time_ts,
5329 ea_list,
5330 lock_data_count, lock_data,
5331 req->flags2, max_data_bytes,
5332 ppdata, &data_size);
5333 if (!NT_STATUS_IS_OK(status)) {
5334 reply_nterror(req, status);
5335 return;
5338 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5339 max_data_bytes);
5341 return;
5344 /****************************************************************************
5345 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5346 code.
5347 ****************************************************************************/
5349 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5350 connection_struct *conn,
5351 struct smb_request *req,
5352 bool overwrite_if_exists,
5353 const struct smb_filename *smb_fname_old,
5354 struct smb_filename *smb_fname_new)
5356 NTSTATUS status = NT_STATUS_OK;
5358 /* source must already exist. */
5359 if (!VALID_STAT(smb_fname_old->st)) {
5360 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5363 if (VALID_STAT(smb_fname_new->st)) {
5364 if (overwrite_if_exists) {
5365 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5366 return NT_STATUS_FILE_IS_A_DIRECTORY;
5368 status = unlink_internals(conn,
5369 req,
5370 FILE_ATTRIBUTE_NORMAL,
5371 smb_fname_new,
5372 false);
5373 if (!NT_STATUS_IS_OK(status)) {
5374 return status;
5376 } else {
5377 /* Disallow if newname already exists. */
5378 return NT_STATUS_OBJECT_NAME_COLLISION;
5382 /* No links from a directory. */
5383 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5384 return NT_STATUS_FILE_IS_A_DIRECTORY;
5387 /* Setting a hardlink to/from a stream isn't currently supported. */
5388 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5389 is_ntfs_stream_smb_fname(smb_fname_new)) {
5390 return NT_STATUS_INVALID_PARAMETER;
5393 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5394 smb_fname_old->base_name, smb_fname_new->base_name));
5396 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5397 smb_fname_new->base_name) != 0) {
5398 status = map_nt_error_from_unix(errno);
5399 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5400 nt_errstr(status), smb_fname_old->base_name,
5401 smb_fname_new->base_name));
5403 return status;
5406 /****************************************************************************
5407 Deal with setting the time from any of the setfilepathinfo functions.
5408 ****************************************************************************/
5410 NTSTATUS smb_set_file_time(connection_struct *conn,
5411 files_struct *fsp,
5412 const struct smb_filename *smb_fname,
5413 struct smb_file_time *ft,
5414 bool setting_write_time)
5416 struct smb_filename smb_fname_base;
5417 uint32 action =
5418 FILE_NOTIFY_CHANGE_LAST_ACCESS
5419 |FILE_NOTIFY_CHANGE_LAST_WRITE
5420 |FILE_NOTIFY_CHANGE_CREATION;
5422 if (!VALID_STAT(smb_fname->st)) {
5423 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5426 /* get some defaults (no modifications) if any info is zero or -1. */
5427 if (null_timespec(ft->create_time)) {
5428 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5431 if (null_timespec(ft->atime)) {
5432 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5435 if (null_timespec(ft->mtime)) {
5436 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5439 if (!setting_write_time) {
5440 /* ft->mtime comes from change time, not write time. */
5441 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5444 /* Ensure the resolution is the correct for
5445 * what we can store on this filesystem. */
5447 round_timespec(conn->ts_res, &ft->create_time);
5448 round_timespec(conn->ts_res, &ft->ctime);
5449 round_timespec(conn->ts_res, &ft->atime);
5450 round_timespec(conn->ts_res, &ft->mtime);
5452 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5453 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5454 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5455 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5456 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5457 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5458 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5459 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5461 if (setting_write_time) {
5463 * This was a Windows setfileinfo on an open file.
5464 * NT does this a lot. We also need to
5465 * set the time here, as it can be read by
5466 * FindFirst/FindNext and with the patch for bug #2045
5467 * in smbd/fileio.c it ensures that this timestamp is
5468 * kept sticky even after a write. We save the request
5469 * away and will set it on file close and after a write. JRA.
5472 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5473 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5475 if (fsp != NULL) {
5476 if (fsp->base_fsp) {
5477 set_sticky_write_time_fsp(fsp->base_fsp,
5478 ft->mtime);
5479 } else {
5480 set_sticky_write_time_fsp(fsp, ft->mtime);
5482 } else {
5483 set_sticky_write_time_path(
5484 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5485 ft->mtime);
5489 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5491 /* Always call ntimes on the base, even if a stream was passed in. */
5492 smb_fname_base = *smb_fname;
5493 smb_fname_base.stream_name = NULL;
5495 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5496 return map_nt_error_from_unix(errno);
5499 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5500 smb_fname->base_name);
5501 return NT_STATUS_OK;
5504 /****************************************************************************
5505 Deal with setting the dosmode from any of the setfilepathinfo functions.
5506 ****************************************************************************/
5508 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5509 const struct smb_filename *smb_fname,
5510 uint32 dosmode)
5512 struct smb_filename *smb_fname_base = NULL;
5513 NTSTATUS status;
5515 if (!VALID_STAT(smb_fname->st)) {
5516 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5519 /* Always operate on the base_name, even if a stream was passed in. */
5520 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5521 NULL, &smb_fname->st,
5522 &smb_fname_base);
5523 if (!NT_STATUS_IS_OK(status)) {
5524 return status;
5527 if (dosmode) {
5528 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5529 dosmode |= aDIR;
5530 } else {
5531 dosmode &= ~aDIR;
5535 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5537 /* check the mode isn't different, before changing it */
5538 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5539 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5540 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5541 (unsigned int)dosmode));
5543 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5544 false)) {
5545 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5546 "%s failed (%s)\n",
5547 smb_fname_str_dbg(smb_fname_base),
5548 strerror(errno)));
5549 status = map_nt_error_from_unix(errno);
5550 goto out;
5553 status = NT_STATUS_OK;
5554 out:
5555 TALLOC_FREE(smb_fname_base);
5556 return status;
5559 /****************************************************************************
5560 Deal with setting the size from any of the setfilepathinfo functions.
5561 ****************************************************************************/
5563 static NTSTATUS smb_set_file_size(connection_struct *conn,
5564 struct smb_request *req,
5565 files_struct *fsp,
5566 const struct smb_filename *smb_fname,
5567 const SMB_STRUCT_STAT *psbuf,
5568 SMB_OFF_T size,
5569 bool fail_after_createfile)
5571 NTSTATUS status = NT_STATUS_OK;
5572 struct smb_filename *smb_fname_tmp = NULL;
5573 files_struct *new_fsp = NULL;
5575 if (!VALID_STAT(*psbuf)) {
5576 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5579 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5581 if (size == get_file_size_stat(psbuf)) {
5582 return NT_STATUS_OK;
5585 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5586 smb_fname_str_dbg(smb_fname), (double)size));
5588 if (fsp && fsp->fh->fd != -1) {
5589 /* Handle based call. */
5590 if (vfs_set_filelen(fsp, size) == -1) {
5591 return map_nt_error_from_unix(errno);
5593 trigger_write_time_update_immediate(fsp);
5594 return NT_STATUS_OK;
5597 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5598 if (!NT_STATUS_IS_OK(status)) {
5599 return status;
5602 smb_fname_tmp->st = *psbuf;
5604 status = SMB_VFS_CREATE_FILE(
5605 conn, /* conn */
5606 req, /* req */
5607 0, /* root_dir_fid */
5608 smb_fname_tmp, /* fname */
5609 FILE_WRITE_DATA, /* access_mask */
5610 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5611 FILE_SHARE_DELETE),
5612 FILE_OPEN, /* create_disposition*/
5613 0, /* create_options */
5614 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5615 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5616 0, /* allocation_size */
5617 0, /* private_flags */
5618 NULL, /* sd */
5619 NULL, /* ea_list */
5620 &new_fsp, /* result */
5621 NULL); /* pinfo */
5623 TALLOC_FREE(smb_fname_tmp);
5625 if (!NT_STATUS_IS_OK(status)) {
5626 /* NB. We check for open_was_deferred in the caller. */
5627 return status;
5630 /* See RAW-SFILEINFO-END-OF-FILE */
5631 if (fail_after_createfile) {
5632 close_file(req, new_fsp,NORMAL_CLOSE);
5633 return NT_STATUS_INVALID_LEVEL;
5636 if (vfs_set_filelen(new_fsp, size) == -1) {
5637 status = map_nt_error_from_unix(errno);
5638 close_file(req, new_fsp,NORMAL_CLOSE);
5639 return status;
5642 trigger_write_time_update_immediate(new_fsp);
5643 close_file(req, new_fsp,NORMAL_CLOSE);
5644 return NT_STATUS_OK;
5647 /****************************************************************************
5648 Deal with SMB_INFO_SET_EA.
5649 ****************************************************************************/
5651 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5652 const char *pdata,
5653 int total_data,
5654 files_struct *fsp,
5655 const struct smb_filename *smb_fname)
5657 struct ea_list *ea_list = NULL;
5658 TALLOC_CTX *ctx = NULL;
5659 NTSTATUS status = NT_STATUS_OK;
5661 if (total_data < 10) {
5663 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5664 length. They seem to have no effect. Bug #3212. JRA */
5666 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5667 /* We're done. We only get EA info in this call. */
5668 return NT_STATUS_OK;
5671 return NT_STATUS_INVALID_PARAMETER;
5674 if (IVAL(pdata,0) > total_data) {
5675 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5676 IVAL(pdata,0), (unsigned int)total_data));
5677 return NT_STATUS_INVALID_PARAMETER;
5680 ctx = talloc_tos();
5681 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5682 if (!ea_list) {
5683 return NT_STATUS_INVALID_PARAMETER;
5685 status = set_ea(conn, fsp, smb_fname, ea_list);
5687 return status;
5690 /****************************************************************************
5691 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5692 ****************************************************************************/
5694 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5695 const char *pdata,
5696 int total_data,
5697 files_struct *fsp)
5699 struct ea_list *ea_list = NULL;
5700 NTSTATUS status;
5702 if (!fsp) {
5703 return NT_STATUS_INVALID_HANDLE;
5706 if (!lp_ea_support(SNUM(conn))) {
5707 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5708 "EA's not supported.\n",
5709 (unsigned int)total_data));
5710 return NT_STATUS_EAS_NOT_SUPPORTED;
5713 if (total_data < 10) {
5714 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5715 "too small.\n",
5716 (unsigned int)total_data));
5717 return NT_STATUS_INVALID_PARAMETER;
5720 ea_list = read_nttrans_ea_list(talloc_tos(),
5721 pdata,
5722 total_data);
5724 if (!ea_list) {
5725 return NT_STATUS_INVALID_PARAMETER;
5727 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5729 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5730 smb_fname_str_dbg(fsp->fsp_name),
5731 nt_errstr(status) ));
5733 return status;
5737 /****************************************************************************
5738 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5739 ****************************************************************************/
5741 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5742 const char *pdata,
5743 int total_data,
5744 files_struct *fsp,
5745 struct smb_filename *smb_fname)
5747 NTSTATUS status = NT_STATUS_OK;
5748 bool delete_on_close;
5749 uint32 dosmode = 0;
5751 if (total_data < 1) {
5752 return NT_STATUS_INVALID_PARAMETER;
5755 if (fsp == NULL) {
5756 return NT_STATUS_INVALID_HANDLE;
5759 delete_on_close = (CVAL(pdata,0) ? True : False);
5760 dosmode = dos_mode(conn, smb_fname);
5762 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5763 "delete_on_close = %u\n",
5764 smb_fname_str_dbg(smb_fname),
5765 (unsigned int)dosmode,
5766 (unsigned int)delete_on_close ));
5768 if (delete_on_close) {
5769 status = can_set_delete_on_close(fsp, dosmode);
5770 if (!NT_STATUS_IS_OK(status)) {
5771 return status;
5775 /* The set is across all open files on this dev/inode pair. */
5776 if (!set_delete_on_close(fsp, delete_on_close,
5777 &conn->server_info->utok)) {
5778 return NT_STATUS_ACCESS_DENIED;
5780 return NT_STATUS_OK;
5783 /****************************************************************************
5784 Deal with SMB_FILE_POSITION_INFORMATION.
5785 ****************************************************************************/
5787 static NTSTATUS smb_file_position_information(connection_struct *conn,
5788 const char *pdata,
5789 int total_data,
5790 files_struct *fsp)
5792 uint64_t position_information;
5794 if (total_data < 8) {
5795 return NT_STATUS_INVALID_PARAMETER;
5798 if (fsp == NULL) {
5799 /* Ignore on pathname based set. */
5800 return NT_STATUS_OK;
5803 position_information = (uint64_t)IVAL(pdata,0);
5804 #ifdef LARGE_SMB_OFF_T
5805 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5806 #else /* LARGE_SMB_OFF_T */
5807 if (IVAL(pdata,4) != 0) {
5808 /* more than 32 bits? */
5809 return NT_STATUS_INVALID_PARAMETER;
5811 #endif /* LARGE_SMB_OFF_T */
5813 DEBUG(10,("smb_file_position_information: Set file position "
5814 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5815 (double)position_information));
5816 fsp->fh->position_information = position_information;
5817 return NT_STATUS_OK;
5820 /****************************************************************************
5821 Deal with SMB_FILE_MODE_INFORMATION.
5822 ****************************************************************************/
5824 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5825 const char *pdata,
5826 int total_data)
5828 uint32 mode;
5830 if (total_data < 4) {
5831 return NT_STATUS_INVALID_PARAMETER;
5833 mode = IVAL(pdata,0);
5834 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5835 return NT_STATUS_INVALID_PARAMETER;
5837 return NT_STATUS_OK;
5840 /****************************************************************************
5841 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5842 ****************************************************************************/
5844 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5845 struct smb_request *req,
5846 const char *pdata,
5847 int total_data,
5848 const struct smb_filename *smb_fname)
5850 char *link_target = NULL;
5851 const char *newname = smb_fname->base_name;
5852 TALLOC_CTX *ctx = talloc_tos();
5854 /* Set a symbolic link. */
5855 /* Don't allow this if follow links is false. */
5857 if (total_data == 0) {
5858 return NT_STATUS_INVALID_PARAMETER;
5861 if (!lp_symlinks(SNUM(conn))) {
5862 return NT_STATUS_ACCESS_DENIED;
5865 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5866 total_data, STR_TERMINATE);
5868 if (!link_target) {
5869 return NT_STATUS_INVALID_PARAMETER;
5872 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5873 newname, link_target ));
5875 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5876 return map_nt_error_from_unix(errno);
5879 return NT_STATUS_OK;
5882 /****************************************************************************
5883 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5884 ****************************************************************************/
5886 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5887 struct smb_request *req,
5888 const char *pdata, int total_data,
5889 struct smb_filename *smb_fname_new)
5891 char *oldname = NULL;
5892 struct smb_filename *smb_fname_old = NULL;
5893 TALLOC_CTX *ctx = talloc_tos();
5894 NTSTATUS status = NT_STATUS_OK;
5896 /* Set a hard link. */
5897 if (total_data == 0) {
5898 return NT_STATUS_INVALID_PARAMETER;
5901 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5902 total_data, STR_TERMINATE, &status);
5903 if (!NT_STATUS_IS_OK(status)) {
5904 return status;
5907 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5908 smb_fname_str_dbg(smb_fname_new), oldname));
5910 status = filename_convert(ctx,
5911 conn,
5912 req->flags2 & FLAGS2_DFS_PATHNAMES,
5913 oldname,
5915 NULL,
5916 &smb_fname_old);
5917 if (!NT_STATUS_IS_OK(status)) {
5918 return status;
5921 return hardlink_internals(ctx, conn, req, false,
5922 smb_fname_old, smb_fname_new);
5925 /****************************************************************************
5926 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5927 ****************************************************************************/
5929 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5930 struct smb_request *req,
5931 const char *pdata,
5932 int total_data,
5933 files_struct *fsp,
5934 struct smb_filename *smb_fname_src)
5936 bool overwrite;
5937 uint32_t len;
5938 char *newname = NULL;
5939 struct smb_filename *smb_fname_dst = NULL;
5940 NTSTATUS status = NT_STATUS_OK;
5941 TALLOC_CTX *ctx = talloc_tos();
5943 if (!fsp) {
5944 return NT_STATUS_INVALID_HANDLE;
5947 if (total_data < 20) {
5948 return NT_STATUS_INVALID_PARAMETER;
5951 overwrite = (CVAL(pdata,0) ? True : False);
5952 len = IVAL(pdata,16);
5954 if (len > (total_data - 20) || (len == 0)) {
5955 return NT_STATUS_INVALID_PARAMETER;
5958 srvstr_get_path(ctx, pdata, req->flags2, &newname,
5959 &pdata[20], len, STR_TERMINATE,
5960 &status);
5961 if (!NT_STATUS_IS_OK(status)) {
5962 return status;
5965 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
5966 newname));
5968 status = filename_convert(ctx,
5969 conn,
5970 req->flags2 & FLAGS2_DFS_PATHNAMES,
5971 newname,
5973 NULL,
5974 &smb_fname_dst);
5975 if (!NT_STATUS_IS_OK(status)) {
5976 return status;
5979 /* Ok, this looks wrong to me, but appears to
5980 * be how SMB2 renames work. CHECK WITH Microsoft !
5981 * jra.
5983 if (fsp->oplock_type != NO_OPLOCK) {
5984 return NT_STATUS_SHARING_VIOLATION;
5987 if (fsp->base_fsp) {
5988 /* newname must be a stream name. */
5989 if (newname[0] != ':') {
5990 return NT_STATUS_NOT_SUPPORTED;
5993 /* Create an smb_fname to call rename_internals_fsp() with. */
5994 status = create_synthetic_smb_fname(talloc_tos(),
5995 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5996 &smb_fname_dst);
5997 if (!NT_STATUS_IS_OK(status)) {
5998 goto out;
6002 * Set the original last component, since
6003 * rename_internals_fsp() requires it.
6005 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6006 newname);
6007 if (smb_fname_dst->original_lcomp == NULL) {
6008 status = NT_STATUS_NO_MEMORY;
6009 goto out;
6014 DEBUG(10,("smb2_file_rename_information: "
6015 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6016 fsp->fnum, fsp_str_dbg(fsp),
6017 smb_fname_str_dbg(smb_fname_dst)));
6018 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6019 overwrite);
6021 out:
6022 TALLOC_FREE(smb_fname_dst);
6023 return status;
6026 static NTSTATUS smb_file_link_information(connection_struct *conn,
6027 struct smb_request *req,
6028 const char *pdata,
6029 int total_data,
6030 files_struct *fsp,
6031 struct smb_filename *smb_fname_src)
6033 bool overwrite;
6034 uint32_t len;
6035 char *newname = NULL;
6036 struct smb_filename *smb_fname_dst = NULL;
6037 NTSTATUS status = NT_STATUS_OK;
6038 TALLOC_CTX *ctx = talloc_tos();
6040 if (!fsp) {
6041 return NT_STATUS_INVALID_HANDLE;
6044 if (total_data < 20) {
6045 return NT_STATUS_INVALID_PARAMETER;
6048 overwrite = (CVAL(pdata,0) ? true : false);
6049 len = IVAL(pdata,16);
6051 if (len > (total_data - 20) || (len == 0)) {
6052 return NT_STATUS_INVALID_PARAMETER;
6055 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6056 &pdata[20], len, STR_TERMINATE,
6057 &status);
6058 if (!NT_STATUS_IS_OK(status)) {
6059 return status;
6062 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6063 newname));
6065 status = filename_convert(ctx,
6066 conn,
6067 req->flags2 & FLAGS2_DFS_PATHNAMES,
6068 newname,
6070 NULL,
6071 &smb_fname_dst);
6072 if (!NT_STATUS_IS_OK(status)) {
6073 return status;
6076 if (fsp->base_fsp) {
6077 /* No stream names. */
6078 return NT_STATUS_NOT_SUPPORTED;
6081 DEBUG(10,("smb_file_link_information: "
6082 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6083 fsp->fnum, fsp_str_dbg(fsp),
6084 smb_fname_str_dbg(smb_fname_dst)));
6085 status = hardlink_internals(ctx,
6086 conn,
6087 req,
6088 overwrite,
6089 fsp->fsp_name,
6090 smb_fname_dst);
6092 TALLOC_FREE(smb_fname_dst);
6093 return status;
6096 /****************************************************************************
6097 Deal with SMB_FILE_RENAME_INFORMATION.
6098 ****************************************************************************/
6100 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6101 struct smb_request *req,
6102 const char *pdata,
6103 int total_data,
6104 files_struct *fsp,
6105 struct smb_filename *smb_fname_src)
6107 bool overwrite;
6108 uint32 root_fid;
6109 uint32 len;
6110 char *newname = NULL;
6111 struct smb_filename *smb_fname_dst = NULL;
6112 bool dest_has_wcard = False;
6113 NTSTATUS status = NT_STATUS_OK;
6114 char *p;
6115 TALLOC_CTX *ctx = talloc_tos();
6117 if (total_data < 13) {
6118 return NT_STATUS_INVALID_PARAMETER;
6121 overwrite = (CVAL(pdata,0) ? True : False);
6122 root_fid = IVAL(pdata,4);
6123 len = IVAL(pdata,8);
6125 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6126 return NT_STATUS_INVALID_PARAMETER;
6129 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6130 len, 0, &status,
6131 &dest_has_wcard);
6132 if (!NT_STATUS_IS_OK(status)) {
6133 return status;
6136 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6137 newname));
6139 status = resolve_dfspath_wcard(ctx, conn,
6140 req->flags2 & FLAGS2_DFS_PATHNAMES,
6141 newname,
6142 true,
6143 &newname,
6144 &dest_has_wcard);
6145 if (!NT_STATUS_IS_OK(status)) {
6146 return status;
6149 /* Check the new name has no '/' characters. */
6150 if (strchr_m(newname, '/')) {
6151 return NT_STATUS_NOT_SUPPORTED;
6154 if (fsp && fsp->base_fsp) {
6155 /* newname must be a stream name. */
6156 if (newname[0] != ':') {
6157 return NT_STATUS_NOT_SUPPORTED;
6160 /* Create an smb_fname to call rename_internals_fsp() with. */
6161 status = create_synthetic_smb_fname(talloc_tos(),
6162 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6163 &smb_fname_dst);
6164 if (!NT_STATUS_IS_OK(status)) {
6165 goto out;
6169 * Set the original last component, since
6170 * rename_internals_fsp() requires it.
6172 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6173 newname);
6174 if (smb_fname_dst->original_lcomp == NULL) {
6175 status = NT_STATUS_NO_MEMORY;
6176 goto out;
6179 } else {
6181 * Build up an smb_fname_dst based on the filename passed in.
6182 * We basically just strip off the last component, and put on
6183 * the newname instead.
6185 char *base_name = NULL;
6187 /* newname must *not* be a stream name. */
6188 if (newname[0] == ':') {
6189 return NT_STATUS_NOT_SUPPORTED;
6193 * Strip off the last component (filename) of the path passed
6194 * in.
6196 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6197 if (!base_name) {
6198 return NT_STATUS_NO_MEMORY;
6200 p = strrchr_m(base_name, '/');
6201 if (p) {
6202 p[1] = '\0';
6203 } else {
6204 base_name = talloc_strdup(ctx, "./");
6205 if (!base_name) {
6206 return NT_STATUS_NO_MEMORY;
6209 /* Append the new name. */
6210 base_name = talloc_asprintf_append(base_name,
6211 "%s",
6212 newname);
6213 if (!base_name) {
6214 return NT_STATUS_NO_MEMORY;
6217 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6218 (UCF_SAVE_LCOMP |
6219 (dest_has_wcard ?
6220 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6221 0)));
6223 /* If an error we expect this to be
6224 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6226 if (!NT_STATUS_IS_OK(status)) {
6227 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6228 status)) {
6229 goto out;
6231 /* Create an smb_fname to call rename_internals_fsp() */
6232 status = create_synthetic_smb_fname(ctx,
6233 base_name, NULL,
6234 NULL,
6235 &smb_fname_dst);
6236 if (!NT_STATUS_IS_OK(status)) {
6237 goto out;
6242 if (fsp) {
6243 DEBUG(10,("smb_file_rename_information: "
6244 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6245 fsp->fnum, fsp_str_dbg(fsp),
6246 smb_fname_str_dbg(smb_fname_dst)));
6247 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6248 overwrite);
6249 } else {
6250 DEBUG(10,("smb_file_rename_information: "
6251 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6252 smb_fname_str_dbg(smb_fname_src),
6253 smb_fname_str_dbg(smb_fname_dst)));
6254 status = rename_internals(ctx, conn, req, smb_fname_src,
6255 smb_fname_dst, 0, overwrite, false,
6256 dest_has_wcard,
6257 FILE_WRITE_ATTRIBUTES);
6259 out:
6260 TALLOC_FREE(smb_fname_dst);
6261 return status;
6264 /****************************************************************************
6265 Deal with SMB_SET_POSIX_ACL.
6266 ****************************************************************************/
6268 #if defined(HAVE_POSIX_ACLS)
6269 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6270 const char *pdata,
6271 int total_data,
6272 files_struct *fsp,
6273 const struct smb_filename *smb_fname)
6275 uint16 posix_acl_version;
6276 uint16 num_file_acls;
6277 uint16 num_def_acls;
6278 bool valid_file_acls = True;
6279 bool valid_def_acls = True;
6281 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6282 return NT_STATUS_INVALID_PARAMETER;
6284 posix_acl_version = SVAL(pdata,0);
6285 num_file_acls = SVAL(pdata,2);
6286 num_def_acls = SVAL(pdata,4);
6288 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6289 valid_file_acls = False;
6290 num_file_acls = 0;
6293 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6294 valid_def_acls = False;
6295 num_def_acls = 0;
6298 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6299 return NT_STATUS_INVALID_PARAMETER;
6302 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6303 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6304 return NT_STATUS_INVALID_PARAMETER;
6307 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6308 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6309 (unsigned int)num_file_acls,
6310 (unsigned int)num_def_acls));
6312 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6313 smb_fname->base_name, num_file_acls,
6314 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6315 return map_nt_error_from_unix(errno);
6318 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6319 smb_fname->base_name, &smb_fname->st, num_def_acls,
6320 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6321 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6322 return map_nt_error_from_unix(errno);
6324 return NT_STATUS_OK;
6326 #endif
6328 /****************************************************************************
6329 Deal with SMB_SET_POSIX_LOCK.
6330 ****************************************************************************/
6332 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6333 struct smb_request *req,
6334 const char *pdata,
6335 int total_data,
6336 files_struct *fsp)
6338 uint64_t count;
6339 uint64_t offset;
6340 uint64_t smblctx;
6341 bool blocking_lock = False;
6342 enum brl_type lock_type;
6344 NTSTATUS status = NT_STATUS_OK;
6346 if (fsp == NULL || fsp->fh->fd == -1) {
6347 return NT_STATUS_INVALID_HANDLE;
6350 if (total_data != POSIX_LOCK_DATA_SIZE) {
6351 return NT_STATUS_INVALID_PARAMETER;
6354 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6355 case POSIX_LOCK_TYPE_READ:
6356 lock_type = READ_LOCK;
6357 break;
6358 case POSIX_LOCK_TYPE_WRITE:
6359 /* Return the right POSIX-mappable error code for files opened read-only. */
6360 if (!fsp->can_write) {
6361 return NT_STATUS_INVALID_HANDLE;
6363 lock_type = WRITE_LOCK;
6364 break;
6365 case POSIX_LOCK_TYPE_UNLOCK:
6366 lock_type = UNLOCK_LOCK;
6367 break;
6368 default:
6369 return NT_STATUS_INVALID_PARAMETER;
6372 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6373 blocking_lock = False;
6374 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6375 blocking_lock = True;
6376 } else {
6377 return NT_STATUS_INVALID_PARAMETER;
6380 if (!lp_blocking_locks(SNUM(conn))) {
6381 blocking_lock = False;
6384 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6385 #if defined(HAVE_LONGLONG)
6386 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6387 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6388 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6389 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6390 #else /* HAVE_LONGLONG */
6391 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6392 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6393 #endif /* HAVE_LONGLONG */
6395 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6396 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6397 fsp_str_dbg(fsp),
6398 (unsigned int)lock_type,
6399 (unsigned long long)smblctx,
6400 (double)count,
6401 (double)offset ));
6403 if (lock_type == UNLOCK_LOCK) {
6404 status = do_unlock(smbd_messaging_context(),
6405 fsp,
6406 smblctx,
6407 count,
6408 offset,
6409 POSIX_LOCK);
6410 } else {
6411 uint64_t block_smblctx;
6413 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6414 fsp,
6415 smblctx,
6416 count,
6417 offset,
6418 lock_type,
6419 POSIX_LOCK,
6420 blocking_lock,
6421 &status,
6422 &block_smblctx,
6423 NULL);
6425 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6427 * A blocking lock was requested. Package up
6428 * this smb into a queued request and push it
6429 * onto the blocking lock queue.
6431 if(push_blocking_lock_request(br_lck,
6432 req,
6433 fsp,
6434 -1, /* infinite timeout. */
6436 smblctx,
6437 lock_type,
6438 POSIX_LOCK,
6439 offset,
6440 count,
6441 block_smblctx)) {
6442 TALLOC_FREE(br_lck);
6443 return status;
6446 TALLOC_FREE(br_lck);
6449 return status;
6452 /****************************************************************************
6453 Deal with SMB_SET_FILE_BASIC_INFO.
6454 ****************************************************************************/
6456 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6457 const char *pdata,
6458 int total_data,
6459 files_struct *fsp,
6460 const struct smb_filename *smb_fname)
6462 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6463 struct smb_file_time ft;
6464 uint32 dosmode = 0;
6465 NTSTATUS status = NT_STATUS_OK;
6467 ZERO_STRUCT(ft);
6469 if (total_data < 36) {
6470 return NT_STATUS_INVALID_PARAMETER;
6473 /* Set the attributes */
6474 dosmode = IVAL(pdata,32);
6475 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6476 if (!NT_STATUS_IS_OK(status)) {
6477 return status;
6480 /* create time */
6481 ft.create_time = interpret_long_date(pdata);
6483 /* access time */
6484 ft.atime = interpret_long_date(pdata+8);
6486 /* write time. */
6487 ft.mtime = interpret_long_date(pdata+16);
6489 /* change time. */
6490 ft.ctime = interpret_long_date(pdata+24);
6492 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6493 smb_fname_str_dbg(smb_fname)));
6495 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6496 true);
6499 /****************************************************************************
6500 Deal with SMB_INFO_STANDARD.
6501 ****************************************************************************/
6503 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6504 const char *pdata,
6505 int total_data,
6506 files_struct *fsp,
6507 const struct smb_filename *smb_fname)
6509 struct smb_file_time ft;
6511 ZERO_STRUCT(ft);
6513 if (total_data < 12) {
6514 return NT_STATUS_INVALID_PARAMETER;
6517 /* create time */
6518 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6519 /* access time */
6520 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6521 /* write time */
6522 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6524 DEBUG(10,("smb_set_info_standard: file %s\n",
6525 smb_fname_str_dbg(smb_fname)));
6527 return smb_set_file_time(conn,
6528 fsp,
6529 smb_fname,
6530 &ft,
6531 true);
6534 /****************************************************************************
6535 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6536 ****************************************************************************/
6538 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6539 struct smb_request *req,
6540 const char *pdata,
6541 int total_data,
6542 files_struct *fsp,
6543 struct smb_filename *smb_fname)
6545 uint64_t allocation_size = 0;
6546 NTSTATUS status = NT_STATUS_OK;
6547 files_struct *new_fsp = NULL;
6549 if (!VALID_STAT(smb_fname->st)) {
6550 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6553 if (total_data < 8) {
6554 return NT_STATUS_INVALID_PARAMETER;
6557 allocation_size = (uint64_t)IVAL(pdata,0);
6558 #ifdef LARGE_SMB_OFF_T
6559 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6560 #else /* LARGE_SMB_OFF_T */
6561 if (IVAL(pdata,4) != 0) {
6562 /* more than 32 bits? */
6563 return NT_STATUS_INVALID_PARAMETER;
6565 #endif /* LARGE_SMB_OFF_T */
6567 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6568 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6569 (double)allocation_size));
6571 if (allocation_size) {
6572 allocation_size = smb_roundup(conn, allocation_size);
6575 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6576 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6577 (double)allocation_size));
6579 if (fsp && fsp->fh->fd != -1) {
6580 /* Open file handle. */
6581 /* Only change if needed. */
6582 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6583 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6584 return map_nt_error_from_unix(errno);
6587 /* But always update the time. */
6589 * This is equivalent to a write. Ensure it's seen immediately
6590 * if there are no pending writes.
6592 trigger_write_time_update_immediate(fsp);
6593 return NT_STATUS_OK;
6596 /* Pathname or stat or directory file. */
6597 status = SMB_VFS_CREATE_FILE(
6598 conn, /* conn */
6599 req, /* req */
6600 0, /* root_dir_fid */
6601 smb_fname, /* fname */
6602 FILE_WRITE_DATA, /* access_mask */
6603 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6604 FILE_SHARE_DELETE),
6605 FILE_OPEN, /* create_disposition*/
6606 0, /* create_options */
6607 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6608 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6609 0, /* allocation_size */
6610 0, /* private_flags */
6611 NULL, /* sd */
6612 NULL, /* ea_list */
6613 &new_fsp, /* result */
6614 NULL); /* pinfo */
6616 if (!NT_STATUS_IS_OK(status)) {
6617 /* NB. We check for open_was_deferred in the caller. */
6618 return status;
6621 /* Only change if needed. */
6622 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6623 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6624 status = map_nt_error_from_unix(errno);
6625 close_file(req, new_fsp, NORMAL_CLOSE);
6626 return status;
6630 /* Changing the allocation size should set the last mod time. */
6632 * This is equivalent to a write. Ensure it's seen immediately
6633 * if there are no pending writes.
6635 trigger_write_time_update_immediate(new_fsp);
6637 close_file(req, new_fsp, NORMAL_CLOSE);
6638 return NT_STATUS_OK;
6641 /****************************************************************************
6642 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6643 ****************************************************************************/
6645 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6646 struct smb_request *req,
6647 const char *pdata,
6648 int total_data,
6649 files_struct *fsp,
6650 const struct smb_filename *smb_fname,
6651 bool fail_after_createfile)
6653 SMB_OFF_T size;
6655 if (total_data < 8) {
6656 return NT_STATUS_INVALID_PARAMETER;
6659 size = IVAL(pdata,0);
6660 #ifdef LARGE_SMB_OFF_T
6661 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6662 #else /* LARGE_SMB_OFF_T */
6663 if (IVAL(pdata,4) != 0) {
6664 /* more than 32 bits? */
6665 return NT_STATUS_INVALID_PARAMETER;
6667 #endif /* LARGE_SMB_OFF_T */
6668 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6669 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6670 (double)size));
6672 return smb_set_file_size(conn, req,
6673 fsp,
6674 smb_fname,
6675 &smb_fname->st,
6676 size,
6677 fail_after_createfile);
6680 /****************************************************************************
6681 Allow a UNIX info mknod.
6682 ****************************************************************************/
6684 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6685 const char *pdata,
6686 int total_data,
6687 const struct smb_filename *smb_fname)
6689 uint32 file_type = IVAL(pdata,56);
6690 #if defined(HAVE_MAKEDEV)
6691 uint32 dev_major = IVAL(pdata,60);
6692 uint32 dev_minor = IVAL(pdata,68);
6693 #endif
6694 SMB_DEV_T dev = (SMB_DEV_T)0;
6695 uint32 raw_unixmode = IVAL(pdata,84);
6696 NTSTATUS status;
6697 mode_t unixmode;
6699 if (total_data < 100) {
6700 return NT_STATUS_INVALID_PARAMETER;
6703 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6704 PERM_NEW_FILE, &unixmode);
6705 if (!NT_STATUS_IS_OK(status)) {
6706 return status;
6709 #if defined(HAVE_MAKEDEV)
6710 dev = makedev(dev_major, dev_minor);
6711 #endif
6713 switch (file_type) {
6714 #if defined(S_IFIFO)
6715 case UNIX_TYPE_FIFO:
6716 unixmode |= S_IFIFO;
6717 break;
6718 #endif
6719 #if defined(S_IFSOCK)
6720 case UNIX_TYPE_SOCKET:
6721 unixmode |= S_IFSOCK;
6722 break;
6723 #endif
6724 #if defined(S_IFCHR)
6725 case UNIX_TYPE_CHARDEV:
6726 unixmode |= S_IFCHR;
6727 break;
6728 #endif
6729 #if defined(S_IFBLK)
6730 case UNIX_TYPE_BLKDEV:
6731 unixmode |= S_IFBLK;
6732 break;
6733 #endif
6734 default:
6735 return NT_STATUS_INVALID_PARAMETER;
6738 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6739 "%.0f mode 0%o for file %s\n", (double)dev,
6740 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6742 /* Ok - do the mknod. */
6743 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6744 return map_nt_error_from_unix(errno);
6747 /* If any of the other "set" calls fail we
6748 * don't want to end up with a half-constructed mknod.
6751 if (lp_inherit_perms(SNUM(conn))) {
6752 char *parent;
6753 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6754 &parent, NULL)) {
6755 return NT_STATUS_NO_MEMORY;
6757 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6758 unixmode);
6759 TALLOC_FREE(parent);
6762 return NT_STATUS_OK;
6765 /****************************************************************************
6766 Deal with SMB_SET_FILE_UNIX_BASIC.
6767 ****************************************************************************/
6769 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6770 struct smb_request *req,
6771 const char *pdata,
6772 int total_data,
6773 files_struct *fsp,
6774 const struct smb_filename *smb_fname)
6776 struct smb_file_time ft;
6777 uint32 raw_unixmode;
6778 mode_t unixmode;
6779 SMB_OFF_T size = 0;
6780 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6781 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6782 NTSTATUS status = NT_STATUS_OK;
6783 bool delete_on_fail = False;
6784 enum perm_type ptype;
6785 files_struct *all_fsps = NULL;
6786 bool modify_mtime = true;
6787 struct file_id id;
6788 SMB_STRUCT_STAT sbuf;
6790 ZERO_STRUCT(ft);
6792 if (total_data < 100) {
6793 return NT_STATUS_INVALID_PARAMETER;
6796 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6797 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6798 size=IVAL(pdata,0); /* first 8 Bytes are size */
6799 #ifdef LARGE_SMB_OFF_T
6800 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6801 #else /* LARGE_SMB_OFF_T */
6802 if (IVAL(pdata,4) != 0) {
6803 /* more than 32 bits? */
6804 return NT_STATUS_INVALID_PARAMETER;
6806 #endif /* LARGE_SMB_OFF_T */
6809 ft.atime = interpret_long_date(pdata+24); /* access_time */
6810 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6811 set_owner = (uid_t)IVAL(pdata,40);
6812 set_grp = (gid_t)IVAL(pdata,48);
6813 raw_unixmode = IVAL(pdata,84);
6815 if (VALID_STAT(smb_fname->st)) {
6816 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6817 ptype = PERM_EXISTING_DIR;
6818 } else {
6819 ptype = PERM_EXISTING_FILE;
6821 } else {
6822 ptype = PERM_NEW_FILE;
6825 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6826 ptype, &unixmode);
6827 if (!NT_STATUS_IS_OK(status)) {
6828 return status;
6831 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6832 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6833 smb_fname_str_dbg(smb_fname), (double)size,
6834 (unsigned int)set_owner, (unsigned int)set_grp,
6835 (int)raw_unixmode));
6837 sbuf = smb_fname->st;
6839 if (!VALID_STAT(sbuf)) {
6840 struct smb_filename *smb_fname_tmp = NULL;
6842 * The only valid use of this is to create character and block
6843 * devices, and named pipes. This is deprecated (IMHO) and
6844 * a new info level should be used for mknod. JRA.
6847 status = smb_unix_mknod(conn,
6848 pdata,
6849 total_data,
6850 smb_fname);
6851 if (!NT_STATUS_IS_OK(status)) {
6852 return status;
6855 status = copy_smb_filename(talloc_tos(), smb_fname,
6856 &smb_fname_tmp);
6857 if (!NT_STATUS_IS_OK(status)) {
6858 return status;
6861 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6862 status = map_nt_error_from_unix(errno);
6863 TALLOC_FREE(smb_fname_tmp);
6864 SMB_VFS_UNLINK(conn, smb_fname);
6865 return status;
6868 sbuf = smb_fname_tmp->st;
6869 TALLOC_FREE(smb_fname_tmp);
6871 /* Ensure we don't try and change anything else. */
6872 raw_unixmode = SMB_MODE_NO_CHANGE;
6873 size = get_file_size_stat(&sbuf);
6874 ft.atime = sbuf.st_ex_atime;
6875 ft.mtime = sbuf.st_ex_mtime;
6877 * We continue here as we might want to change the
6878 * owner uid/gid.
6880 delete_on_fail = True;
6883 #if 1
6884 /* Horrible backwards compatibility hack as an old server bug
6885 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6886 * */
6888 if (!size) {
6889 size = get_file_size_stat(&sbuf);
6891 #endif
6894 * Deal with the UNIX specific mode set.
6897 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6898 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6899 "setting mode 0%o for file %s\n",
6900 (unsigned int)unixmode,
6901 smb_fname_str_dbg(smb_fname)));
6902 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6903 return map_nt_error_from_unix(errno);
6908 * Deal with the UNIX specific uid set.
6911 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6912 (sbuf.st_ex_uid != set_owner)) {
6913 int ret;
6915 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6916 "changing owner %u for path %s\n",
6917 (unsigned int)set_owner,
6918 smb_fname_str_dbg(smb_fname)));
6920 if (S_ISLNK(sbuf.st_ex_mode)) {
6921 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6922 set_owner, (gid_t)-1);
6923 } else {
6924 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6925 set_owner, (gid_t)-1);
6928 if (ret != 0) {
6929 status = map_nt_error_from_unix(errno);
6930 if (delete_on_fail) {
6931 SMB_VFS_UNLINK(conn, smb_fname);
6933 return status;
6938 * Deal with the UNIX specific gid set.
6941 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6942 (sbuf.st_ex_gid != set_grp)) {
6943 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6944 "changing group %u for file %s\n",
6945 (unsigned int)set_owner,
6946 smb_fname_str_dbg(smb_fname)));
6947 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6948 set_grp) != 0) {
6949 status = map_nt_error_from_unix(errno);
6950 if (delete_on_fail) {
6951 SMB_VFS_UNLINK(conn, smb_fname);
6953 return status;
6957 /* Deal with any size changes. */
6959 status = smb_set_file_size(conn, req,
6960 fsp,
6961 smb_fname,
6962 &sbuf,
6963 size,
6964 false);
6965 if (!NT_STATUS_IS_OK(status)) {
6966 return status;
6969 /* Deal with any time changes. */
6970 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6971 /* No change, don't cancel anything. */
6972 return status;
6975 id = vfs_file_id_from_sbuf(conn, &sbuf);
6976 for(all_fsps = file_find_di_first(id); all_fsps;
6977 all_fsps = file_find_di_next(all_fsps)) {
6979 * We're setting the time explicitly for UNIX.
6980 * Cancel any pending changes over all handles.
6982 all_fsps->update_write_time_on_close = false;
6983 TALLOC_FREE(all_fsps->update_write_time_event);
6987 * Override the "setting_write_time"
6988 * parameter here as it almost does what
6989 * we need. Just remember if we modified
6990 * mtime and send the notify ourselves.
6992 if (null_timespec(ft.mtime)) {
6993 modify_mtime = false;
6996 status = smb_set_file_time(conn,
6997 fsp,
6998 smb_fname,
6999 &ft,
7000 false);
7001 if (modify_mtime) {
7002 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7003 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7005 return status;
7008 /****************************************************************************
7009 Deal with SMB_SET_FILE_UNIX_INFO2.
7010 ****************************************************************************/
7012 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7013 struct smb_request *req,
7014 const char *pdata,
7015 int total_data,
7016 files_struct *fsp,
7017 const struct smb_filename *smb_fname)
7019 NTSTATUS status;
7020 uint32 smb_fflags;
7021 uint32 smb_fmask;
7023 if (total_data < 116) {
7024 return NT_STATUS_INVALID_PARAMETER;
7027 /* Start by setting all the fields that are common between UNIX_BASIC
7028 * and UNIX_INFO2.
7030 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7031 fsp, smb_fname);
7032 if (!NT_STATUS_IS_OK(status)) {
7033 return status;
7036 smb_fflags = IVAL(pdata, 108);
7037 smb_fmask = IVAL(pdata, 112);
7039 /* NB: We should only attempt to alter the file flags if the client
7040 * sends a non-zero mask.
7042 if (smb_fmask != 0) {
7043 int stat_fflags = 0;
7045 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7046 smb_fmask, &stat_fflags)) {
7047 /* Client asked to alter a flag we don't understand. */
7048 return NT_STATUS_INVALID_PARAMETER;
7051 if (fsp && fsp->fh->fd != -1) {
7052 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7053 return NT_STATUS_NOT_SUPPORTED;
7054 } else {
7055 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7056 stat_fflags) != 0) {
7057 return map_nt_error_from_unix(errno);
7062 /* XXX: need to add support for changing the create_time here. You
7063 * can do this for paths on Darwin with setattrlist(2). The right way
7064 * to hook this up is probably by extending the VFS utimes interface.
7067 return NT_STATUS_OK;
7070 /****************************************************************************
7071 Create a directory with POSIX semantics.
7072 ****************************************************************************/
7074 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7075 struct smb_request *req,
7076 char **ppdata,
7077 int total_data,
7078 struct smb_filename *smb_fname,
7079 int *pdata_return_size)
7081 NTSTATUS status = NT_STATUS_OK;
7082 uint32 raw_unixmode = 0;
7083 uint32 mod_unixmode = 0;
7084 mode_t unixmode = (mode_t)0;
7085 files_struct *fsp = NULL;
7086 uint16 info_level_return = 0;
7087 int info;
7088 char *pdata = *ppdata;
7090 if (total_data < 18) {
7091 return NT_STATUS_INVALID_PARAMETER;
7094 raw_unixmode = IVAL(pdata,8);
7095 /* Next 4 bytes are not yet defined. */
7097 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7098 PERM_NEW_DIR, &unixmode);
7099 if (!NT_STATUS_IS_OK(status)) {
7100 return status;
7103 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7105 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7106 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7108 status = SMB_VFS_CREATE_FILE(
7109 conn, /* conn */
7110 req, /* req */
7111 0, /* root_dir_fid */
7112 smb_fname, /* fname */
7113 FILE_READ_ATTRIBUTES, /* access_mask */
7114 FILE_SHARE_NONE, /* share_access */
7115 FILE_CREATE, /* create_disposition*/
7116 FILE_DIRECTORY_FILE, /* create_options */
7117 mod_unixmode, /* file_attributes */
7118 0, /* oplock_request */
7119 0, /* allocation_size */
7120 0, /* private_flags */
7121 NULL, /* sd */
7122 NULL, /* ea_list */
7123 &fsp, /* result */
7124 &info); /* pinfo */
7126 if (NT_STATUS_IS_OK(status)) {
7127 close_file(req, fsp, NORMAL_CLOSE);
7130 info_level_return = SVAL(pdata,16);
7132 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7133 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7134 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7135 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7136 } else {
7137 *pdata_return_size = 12;
7140 /* Realloc the data size */
7141 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7142 if (*ppdata == NULL) {
7143 *pdata_return_size = 0;
7144 return NT_STATUS_NO_MEMORY;
7146 pdata = *ppdata;
7148 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7149 SSVAL(pdata,2,0); /* No fnum. */
7150 SIVAL(pdata,4,info); /* Was directory created. */
7152 switch (info_level_return) {
7153 case SMB_QUERY_FILE_UNIX_BASIC:
7154 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7155 SSVAL(pdata,10,0); /* Padding. */
7156 store_file_unix_basic(conn, pdata + 12, fsp,
7157 &smb_fname->st);
7158 break;
7159 case SMB_QUERY_FILE_UNIX_INFO2:
7160 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7161 SSVAL(pdata,10,0); /* Padding. */
7162 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7163 &smb_fname->st);
7164 break;
7165 default:
7166 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7167 SSVAL(pdata,10,0); /* Padding. */
7168 break;
7171 return status;
7174 /****************************************************************************
7175 Open/Create a file with POSIX semantics.
7176 ****************************************************************************/
7178 static NTSTATUS smb_posix_open(connection_struct *conn,
7179 struct smb_request *req,
7180 char **ppdata,
7181 int total_data,
7182 struct smb_filename *smb_fname,
7183 int *pdata_return_size)
7185 bool extended_oplock_granted = False;
7186 char *pdata = *ppdata;
7187 uint32 flags = 0;
7188 uint32 wire_open_mode = 0;
7189 uint32 raw_unixmode = 0;
7190 uint32 mod_unixmode = 0;
7191 uint32 create_disp = 0;
7192 uint32 access_mask = 0;
7193 uint32 create_options = 0;
7194 NTSTATUS status = NT_STATUS_OK;
7195 mode_t unixmode = (mode_t)0;
7196 files_struct *fsp = NULL;
7197 int oplock_request = 0;
7198 int info = 0;
7199 uint16 info_level_return = 0;
7201 if (total_data < 18) {
7202 return NT_STATUS_INVALID_PARAMETER;
7205 flags = IVAL(pdata,0);
7206 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7207 if (oplock_request) {
7208 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7211 wire_open_mode = IVAL(pdata,4);
7213 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7214 return smb_posix_mkdir(conn, req,
7215 ppdata,
7216 total_data,
7217 smb_fname,
7218 pdata_return_size);
7221 switch (wire_open_mode & SMB_ACCMODE) {
7222 case SMB_O_RDONLY:
7223 access_mask = FILE_READ_DATA;
7224 break;
7225 case SMB_O_WRONLY:
7226 access_mask = FILE_WRITE_DATA;
7227 break;
7228 case SMB_O_RDWR:
7229 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7230 break;
7231 default:
7232 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7233 (unsigned int)wire_open_mode ));
7234 return NT_STATUS_INVALID_PARAMETER;
7237 wire_open_mode &= ~SMB_ACCMODE;
7239 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7240 create_disp = FILE_CREATE;
7241 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7242 create_disp = FILE_OVERWRITE_IF;
7243 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7244 create_disp = FILE_OPEN_IF;
7245 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7246 create_disp = FILE_OPEN;
7247 } else {
7248 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7249 (unsigned int)wire_open_mode ));
7250 return NT_STATUS_INVALID_PARAMETER;
7253 raw_unixmode = IVAL(pdata,8);
7254 /* Next 4 bytes are not yet defined. */
7256 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7257 (VALID_STAT(smb_fname->st) ?
7258 PERM_EXISTING_FILE : PERM_NEW_FILE),
7259 &unixmode);
7261 if (!NT_STATUS_IS_OK(status)) {
7262 return status;
7265 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7267 if (wire_open_mode & SMB_O_SYNC) {
7268 create_options |= FILE_WRITE_THROUGH;
7270 if (wire_open_mode & SMB_O_APPEND) {
7271 access_mask |= FILE_APPEND_DATA;
7273 if (wire_open_mode & SMB_O_DIRECT) {
7274 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7277 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7278 smb_fname_str_dbg(smb_fname),
7279 (unsigned int)wire_open_mode,
7280 (unsigned int)unixmode ));
7282 status = SMB_VFS_CREATE_FILE(
7283 conn, /* conn */
7284 req, /* req */
7285 0, /* root_dir_fid */
7286 smb_fname, /* fname */
7287 access_mask, /* access_mask */
7288 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7289 FILE_SHARE_DELETE),
7290 create_disp, /* create_disposition*/
7291 FILE_NON_DIRECTORY_FILE, /* create_options */
7292 mod_unixmode, /* file_attributes */
7293 oplock_request, /* oplock_request */
7294 0, /* allocation_size */
7295 0, /* private_flags */
7296 NULL, /* sd */
7297 NULL, /* ea_list */
7298 &fsp, /* result */
7299 &info); /* pinfo */
7301 if (!NT_STATUS_IS_OK(status)) {
7302 return status;
7305 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7306 extended_oplock_granted = True;
7309 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7310 extended_oplock_granted = True;
7313 info_level_return = SVAL(pdata,16);
7315 /* Allocate the correct return size. */
7317 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7318 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7319 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7320 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7321 } else {
7322 *pdata_return_size = 12;
7325 /* Realloc the data size */
7326 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7327 if (*ppdata == NULL) {
7328 close_file(req, fsp, ERROR_CLOSE);
7329 *pdata_return_size = 0;
7330 return NT_STATUS_NO_MEMORY;
7332 pdata = *ppdata;
7334 if (extended_oplock_granted) {
7335 if (flags & REQUEST_BATCH_OPLOCK) {
7336 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7337 } else {
7338 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7340 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7341 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7342 } else {
7343 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7346 SSVAL(pdata,2,fsp->fnum);
7347 SIVAL(pdata,4,info); /* Was file created etc. */
7349 switch (info_level_return) {
7350 case SMB_QUERY_FILE_UNIX_BASIC:
7351 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7352 SSVAL(pdata,10,0); /* padding. */
7353 store_file_unix_basic(conn, pdata + 12, fsp,
7354 &smb_fname->st);
7355 break;
7356 case SMB_QUERY_FILE_UNIX_INFO2:
7357 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7358 SSVAL(pdata,10,0); /* padding. */
7359 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7360 &smb_fname->st);
7361 break;
7362 default:
7363 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7364 SSVAL(pdata,10,0); /* padding. */
7365 break;
7367 return NT_STATUS_OK;
7370 /****************************************************************************
7371 Delete a file with POSIX semantics.
7372 ****************************************************************************/
7374 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7375 struct smb_request *req,
7376 const char *pdata,
7377 int total_data,
7378 struct smb_filename *smb_fname)
7380 NTSTATUS status = NT_STATUS_OK;
7381 files_struct *fsp = NULL;
7382 uint16 flags = 0;
7383 char del = 1;
7384 int info = 0;
7385 int create_options = 0;
7386 int i;
7387 struct share_mode_lock *lck = NULL;
7389 if (total_data < 2) {
7390 return NT_STATUS_INVALID_PARAMETER;
7393 flags = SVAL(pdata,0);
7395 if (!VALID_STAT(smb_fname->st)) {
7396 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7399 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7400 !VALID_STAT_OF_DIR(smb_fname->st)) {
7401 return NT_STATUS_NOT_A_DIRECTORY;
7404 DEBUG(10,("smb_posix_unlink: %s %s\n",
7405 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7406 smb_fname_str_dbg(smb_fname)));
7408 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7409 create_options |= FILE_DIRECTORY_FILE;
7412 status = SMB_VFS_CREATE_FILE(
7413 conn, /* conn */
7414 req, /* req */
7415 0, /* root_dir_fid */
7416 smb_fname, /* fname */
7417 DELETE_ACCESS, /* access_mask */
7418 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7419 FILE_SHARE_DELETE),
7420 FILE_OPEN, /* create_disposition*/
7421 create_options, /* create_options */
7422 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7423 0, /* oplock_request */
7424 0, /* allocation_size */
7425 0, /* private_flags */
7426 NULL, /* sd */
7427 NULL, /* ea_list */
7428 &fsp, /* result */
7429 &info); /* pinfo */
7431 if (!NT_STATUS_IS_OK(status)) {
7432 return status;
7436 * Don't lie to client. If we can't really delete due to
7437 * non-POSIX opens return SHARING_VIOLATION.
7440 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7441 NULL);
7442 if (lck == NULL) {
7443 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7444 "lock for file %s\n", fsp_str_dbg(fsp)));
7445 close_file(req, fsp, NORMAL_CLOSE);
7446 return NT_STATUS_INVALID_PARAMETER;
7450 * See if others still have the file open. If this is the case, then
7451 * don't delete. If all opens are POSIX delete we can set the delete
7452 * on close disposition.
7454 for (i=0; i<lck->num_share_modes; i++) {
7455 struct share_mode_entry *e = &lck->share_modes[i];
7456 if (is_valid_share_mode_entry(e)) {
7457 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7458 continue;
7460 /* Fail with sharing violation. */
7461 close_file(req, fsp, NORMAL_CLOSE);
7462 TALLOC_FREE(lck);
7463 return NT_STATUS_SHARING_VIOLATION;
7468 * Set the delete on close.
7470 status = smb_set_file_disposition_info(conn,
7471 &del,
7473 fsp,
7474 smb_fname);
7476 if (!NT_STATUS_IS_OK(status)) {
7477 close_file(req, fsp, NORMAL_CLOSE);
7478 TALLOC_FREE(lck);
7479 return status;
7481 TALLOC_FREE(lck);
7482 return close_file(req, fsp, NORMAL_CLOSE);
7485 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7486 struct smb_request *req,
7487 TALLOC_CTX *mem_ctx,
7488 uint16_t info_level,
7489 files_struct *fsp,
7490 struct smb_filename *smb_fname,
7491 char **ppdata, int total_data,
7492 int *ret_data_size)
7494 char *pdata = *ppdata;
7495 NTSTATUS status = NT_STATUS_OK;
7496 int data_return_size = 0;
7498 *ret_data_size = 0;
7500 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7501 return NT_STATUS_INVALID_LEVEL;
7504 if (!CAN_WRITE(conn)) {
7505 /* Allow POSIX opens. The open path will deny
7506 * any non-readonly opens. */
7507 if (info_level != SMB_POSIX_PATH_OPEN) {
7508 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7512 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7513 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7514 fsp ? fsp->fnum : -1, info_level, total_data));
7516 switch (info_level) {
7518 case SMB_INFO_STANDARD:
7520 status = smb_set_info_standard(conn,
7521 pdata,
7522 total_data,
7523 fsp,
7524 smb_fname);
7525 break;
7528 case SMB_INFO_SET_EA:
7530 status = smb_info_set_ea(conn,
7531 pdata,
7532 total_data,
7533 fsp,
7534 smb_fname);
7535 break;
7538 case SMB_SET_FILE_BASIC_INFO:
7539 case SMB_FILE_BASIC_INFORMATION:
7541 status = smb_set_file_basic_info(conn,
7542 pdata,
7543 total_data,
7544 fsp,
7545 smb_fname);
7546 break;
7549 case SMB_FILE_ALLOCATION_INFORMATION:
7550 case SMB_SET_FILE_ALLOCATION_INFO:
7552 status = smb_set_file_allocation_info(conn, req,
7553 pdata,
7554 total_data,
7555 fsp,
7556 smb_fname);
7557 break;
7560 case SMB_FILE_END_OF_FILE_INFORMATION:
7561 case SMB_SET_FILE_END_OF_FILE_INFO:
7564 * XP/Win7 both fail after the createfile with
7565 * SMB_SET_FILE_END_OF_FILE_INFO but not
7566 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7567 * The level is known here, so pass it down
7568 * appropriately.
7570 bool should_fail =
7571 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7573 status = smb_set_file_end_of_file_info(conn, req,
7574 pdata,
7575 total_data,
7576 fsp,
7577 smb_fname,
7578 should_fail);
7579 break;
7582 case SMB_FILE_DISPOSITION_INFORMATION:
7583 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7585 #if 0
7586 /* JRA - We used to just ignore this on a path ?
7587 * Shouldn't this be invalid level on a pathname
7588 * based call ?
7590 if (tran_call != TRANSACT2_SETFILEINFO) {
7591 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7593 #endif
7594 status = smb_set_file_disposition_info(conn,
7595 pdata,
7596 total_data,
7597 fsp,
7598 smb_fname);
7599 break;
7602 case SMB_FILE_POSITION_INFORMATION:
7604 status = smb_file_position_information(conn,
7605 pdata,
7606 total_data,
7607 fsp);
7608 break;
7611 case SMB_FILE_FULL_EA_INFORMATION:
7613 status = smb_set_file_full_ea_info(conn,
7614 pdata,
7615 total_data,
7616 fsp);
7617 break;
7620 /* From tridge Samba4 :
7621 * MODE_INFORMATION in setfileinfo (I have no
7622 * idea what "mode information" on a file is - it takes a value of 0,
7623 * 2, 4 or 6. What could it be?).
7626 case SMB_FILE_MODE_INFORMATION:
7628 status = smb_file_mode_information(conn,
7629 pdata,
7630 total_data);
7631 break;
7635 * CIFS UNIX extensions.
7638 case SMB_SET_FILE_UNIX_BASIC:
7640 status = smb_set_file_unix_basic(conn, req,
7641 pdata,
7642 total_data,
7643 fsp,
7644 smb_fname);
7645 break;
7648 case SMB_SET_FILE_UNIX_INFO2:
7650 status = smb_set_file_unix_info2(conn, req,
7651 pdata,
7652 total_data,
7653 fsp,
7654 smb_fname);
7655 break;
7658 case SMB_SET_FILE_UNIX_LINK:
7660 if (fsp) {
7661 /* We must have a pathname for this. */
7662 return NT_STATUS_INVALID_LEVEL;
7664 status = smb_set_file_unix_link(conn, req, pdata,
7665 total_data, smb_fname);
7666 break;
7669 case SMB_SET_FILE_UNIX_HLINK:
7671 if (fsp) {
7672 /* We must have a pathname for this. */
7673 return NT_STATUS_INVALID_LEVEL;
7675 status = smb_set_file_unix_hlink(conn, req,
7676 pdata, total_data,
7677 smb_fname);
7678 break;
7681 case SMB_FILE_RENAME_INFORMATION:
7683 status = smb_file_rename_information(conn, req,
7684 pdata, total_data,
7685 fsp, smb_fname);
7686 break;
7689 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7691 /* SMB2 rename information. */
7692 status = smb2_file_rename_information(conn, req,
7693 pdata, total_data,
7694 fsp, smb_fname);
7695 break;
7698 case SMB_FILE_LINK_INFORMATION:
7700 status = smb_file_link_information(conn, req,
7701 pdata, total_data,
7702 fsp, smb_fname);
7703 break;
7706 #if defined(HAVE_POSIX_ACLS)
7707 case SMB_SET_POSIX_ACL:
7709 status = smb_set_posix_acl(conn,
7710 pdata,
7711 total_data,
7712 fsp,
7713 smb_fname);
7714 break;
7716 #endif
7718 case SMB_SET_POSIX_LOCK:
7720 if (!fsp) {
7721 return NT_STATUS_INVALID_LEVEL;
7723 status = smb_set_posix_lock(conn, req,
7724 pdata, total_data, fsp);
7725 break;
7728 case SMB_POSIX_PATH_OPEN:
7730 if (fsp) {
7731 /* We must have a pathname for this. */
7732 return NT_STATUS_INVALID_LEVEL;
7735 status = smb_posix_open(conn, req,
7736 ppdata,
7737 total_data,
7738 smb_fname,
7739 &data_return_size);
7740 break;
7743 case SMB_POSIX_PATH_UNLINK:
7745 if (fsp) {
7746 /* We must have a pathname for this. */
7747 return NT_STATUS_INVALID_LEVEL;
7750 status = smb_posix_unlink(conn, req,
7751 pdata,
7752 total_data,
7753 smb_fname);
7754 break;
7757 default:
7758 return NT_STATUS_INVALID_LEVEL;
7761 if (!NT_STATUS_IS_OK(status)) {
7762 return status;
7765 *ret_data_size = data_return_size;
7766 return NT_STATUS_OK;
7769 /****************************************************************************
7770 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7771 ****************************************************************************/
7773 static void call_trans2setfilepathinfo(connection_struct *conn,
7774 struct smb_request *req,
7775 unsigned int tran_call,
7776 char **pparams, int total_params,
7777 char **ppdata, int total_data,
7778 unsigned int max_data_bytes)
7780 char *params = *pparams;
7781 char *pdata = *ppdata;
7782 uint16 info_level;
7783 struct smb_filename *smb_fname = NULL;
7784 files_struct *fsp = NULL;
7785 NTSTATUS status = NT_STATUS_OK;
7786 int data_return_size = 0;
7788 if (!params) {
7789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7790 return;
7793 if (tran_call == TRANSACT2_SETFILEINFO) {
7794 if (total_params < 4) {
7795 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7796 return;
7799 fsp = file_fsp(req, SVAL(params,0));
7800 /* Basic check for non-null fsp. */
7801 if (!check_fsp_open(conn, req, fsp)) {
7802 return;
7804 info_level = SVAL(params,2);
7806 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7807 &smb_fname);
7808 if (!NT_STATUS_IS_OK(status)) {
7809 reply_nterror(req, status);
7810 return;
7813 if(fsp->is_directory || fsp->fh->fd == -1) {
7815 * This is actually a SETFILEINFO on a directory
7816 * handle (returned from an NT SMB). NT5.0 seems
7817 * to do this call. JRA.
7819 if (INFO_LEVEL_IS_UNIX(info_level)) {
7820 /* Always do lstat for UNIX calls. */
7821 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7822 DEBUG(3,("call_trans2setfilepathinfo: "
7823 "SMB_VFS_LSTAT of %s failed "
7824 "(%s)\n",
7825 smb_fname_str_dbg(smb_fname),
7826 strerror(errno)));
7827 reply_nterror(req, map_nt_error_from_unix(errno));
7828 return;
7830 } else {
7831 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7832 DEBUG(3,("call_trans2setfilepathinfo: "
7833 "fileinfo of %s failed (%s)\n",
7834 smb_fname_str_dbg(smb_fname),
7835 strerror(errno)));
7836 reply_nterror(req, map_nt_error_from_unix(errno));
7837 return;
7840 } else if (fsp->print_file) {
7842 * Doing a DELETE_ON_CLOSE should cancel a print job.
7844 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7845 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7847 DEBUG(3,("call_trans2setfilepathinfo: "
7848 "Cancelling print job (%s)\n",
7849 fsp_str_dbg(fsp)));
7851 SSVAL(params,0,0);
7852 send_trans2_replies(conn, req, params, 2,
7853 *ppdata, 0,
7854 max_data_bytes);
7855 return;
7856 } else {
7857 reply_nterror(req,
7858 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7859 return;
7861 } else {
7863 * Original code - this is an open file.
7865 if (!check_fsp(conn, req, fsp)) {
7866 return;
7869 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7870 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7871 "of fnum %d failed (%s)\n", fsp->fnum,
7872 strerror(errno)));
7873 reply_nterror(req, map_nt_error_from_unix(errno));
7874 return;
7877 } else {
7878 char *fname = NULL;
7880 /* set path info */
7881 if (total_params < 7) {
7882 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7883 return;
7886 info_level = SVAL(params,0);
7887 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7888 total_params - 6, STR_TERMINATE,
7889 &status);
7890 if (!NT_STATUS_IS_OK(status)) {
7891 reply_nterror(req, status);
7892 return;
7895 status = filename_convert(req, conn,
7896 req->flags2 & FLAGS2_DFS_PATHNAMES,
7897 fname,
7899 NULL,
7900 &smb_fname);
7901 if (!NT_STATUS_IS_OK(status)) {
7902 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7903 reply_botherror(req,
7904 NT_STATUS_PATH_NOT_COVERED,
7905 ERRSRV, ERRbadpath);
7906 return;
7908 reply_nterror(req, status);
7909 return;
7912 if (INFO_LEVEL_IS_UNIX(info_level)) {
7914 * For CIFS UNIX extensions the target name may not exist.
7917 /* Always do lstat for UNIX calls. */
7918 SMB_VFS_LSTAT(conn, smb_fname);
7920 } else if (!VALID_STAT(smb_fname->st) &&
7921 SMB_VFS_STAT(conn, smb_fname)) {
7922 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7923 "%s failed (%s)\n",
7924 smb_fname_str_dbg(smb_fname),
7925 strerror(errno)));
7926 reply_nterror(req, map_nt_error_from_unix(errno));
7927 return;
7931 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7932 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7933 fsp ? fsp->fnum : -1, info_level,total_data));
7935 /* Realloc the parameter size */
7936 *pparams = (char *)SMB_REALLOC(*pparams,2);
7937 if (*pparams == NULL) {
7938 reply_nterror(req, NT_STATUS_NO_MEMORY);
7939 return;
7941 params = *pparams;
7943 SSVAL(params,0,0);
7945 status = smbd_do_setfilepathinfo(conn, req, req,
7946 info_level,
7947 fsp,
7948 smb_fname,
7949 ppdata, total_data,
7950 &data_return_size);
7951 if (!NT_STATUS_IS_OK(status)) {
7952 if (open_was_deferred(req->mid)) {
7953 /* We have re-scheduled this call. */
7954 return;
7956 if (blocking_lock_was_deferred_smb1(req->mid)) {
7957 /* We have re-scheduled this call. */
7958 return;
7960 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7961 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7962 ERRSRV, ERRbadpath);
7963 return;
7965 if (info_level == SMB_POSIX_PATH_OPEN) {
7966 reply_openerror(req, status);
7967 return;
7970 reply_nterror(req, status);
7971 return;
7974 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7975 max_data_bytes);
7977 return;
7980 /****************************************************************************
7981 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7982 ****************************************************************************/
7984 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7985 char **pparams, int total_params,
7986 char **ppdata, int total_data,
7987 unsigned int max_data_bytes)
7989 struct smb_filename *smb_dname = NULL;
7990 char *params = *pparams;
7991 char *pdata = *ppdata;
7992 char *directory = NULL;
7993 NTSTATUS status = NT_STATUS_OK;
7994 struct ea_list *ea_list = NULL;
7995 TALLOC_CTX *ctx = talloc_tos();
7997 if (!CAN_WRITE(conn)) {
7998 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7999 return;
8002 if (total_params < 5) {
8003 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8004 return;
8007 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
8008 total_params - 4, STR_TERMINATE,
8009 &status);
8010 if (!NT_STATUS_IS_OK(status)) {
8011 reply_nterror(req, status);
8012 return;
8015 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8017 status = filename_convert(ctx,
8018 conn,
8019 req->flags2 & FLAGS2_DFS_PATHNAMES,
8020 directory,
8022 NULL,
8023 &smb_dname);
8025 if (!NT_STATUS_IS_OK(status)) {
8026 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8027 reply_botherror(req,
8028 NT_STATUS_PATH_NOT_COVERED,
8029 ERRSRV, ERRbadpath);
8030 return;
8032 reply_nterror(req, status);
8033 return;
8037 * OS/2 workplace shell seems to send SET_EA requests of "null"
8038 * length (4 bytes containing IVAL 4).
8039 * They seem to have no effect. Bug #3212. JRA.
8042 if (total_data && (total_data != 4)) {
8043 /* Any data in this call is an EA list. */
8044 if (total_data < 10) {
8045 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8046 goto out;
8049 if (IVAL(pdata,0) > total_data) {
8050 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8051 IVAL(pdata,0), (unsigned int)total_data));
8052 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8053 goto out;
8056 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8057 total_data - 4);
8058 if (!ea_list) {
8059 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8060 goto out;
8063 if (!lp_ea_support(SNUM(conn))) {
8064 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8065 goto out;
8068 /* If total_data == 4 Windows doesn't care what values
8069 * are placed in that field, it just ignores them.
8070 * The System i QNTC IBM SMB client puts bad values here,
8071 * so ignore them. */
8073 status = create_directory(conn, req, smb_dname);
8075 if (!NT_STATUS_IS_OK(status)) {
8076 reply_nterror(req, status);
8077 goto out;
8080 /* Try and set any given EA. */
8081 if (ea_list) {
8082 status = set_ea(conn, NULL, smb_dname, ea_list);
8083 if (!NT_STATUS_IS_OK(status)) {
8084 reply_nterror(req, status);
8085 goto out;
8089 /* Realloc the parameter and data sizes */
8090 *pparams = (char *)SMB_REALLOC(*pparams,2);
8091 if(*pparams == NULL) {
8092 reply_nterror(req, NT_STATUS_NO_MEMORY);
8093 goto out;
8095 params = *pparams;
8097 SSVAL(params,0,0);
8099 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8101 out:
8102 TALLOC_FREE(smb_dname);
8103 return;
8106 /****************************************************************************
8107 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8108 We don't actually do this - we just send a null response.
8109 ****************************************************************************/
8111 static void call_trans2findnotifyfirst(connection_struct *conn,
8112 struct smb_request *req,
8113 char **pparams, int total_params,
8114 char **ppdata, int total_data,
8115 unsigned int max_data_bytes)
8117 char *params = *pparams;
8118 uint16 info_level;
8120 if (total_params < 6) {
8121 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8122 return;
8125 info_level = SVAL(params,4);
8126 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8128 switch (info_level) {
8129 case 1:
8130 case 2:
8131 break;
8132 default:
8133 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8134 return;
8137 /* Realloc the parameter and data sizes */
8138 *pparams = (char *)SMB_REALLOC(*pparams,6);
8139 if (*pparams == NULL) {
8140 reply_nterror(req, NT_STATUS_NO_MEMORY);
8141 return;
8143 params = *pparams;
8145 SSVAL(params,0,fnf_handle);
8146 SSVAL(params,2,0); /* No changes */
8147 SSVAL(params,4,0); /* No EA errors */
8149 fnf_handle++;
8151 if(fnf_handle == 0)
8152 fnf_handle = 257;
8154 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8156 return;
8159 /****************************************************************************
8160 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8161 changes). Currently this does nothing.
8162 ****************************************************************************/
8164 static void call_trans2findnotifynext(connection_struct *conn,
8165 struct smb_request *req,
8166 char **pparams, int total_params,
8167 char **ppdata, int total_data,
8168 unsigned int max_data_bytes)
8170 char *params = *pparams;
8172 DEBUG(3,("call_trans2findnotifynext\n"));
8174 /* Realloc the parameter and data sizes */
8175 *pparams = (char *)SMB_REALLOC(*pparams,4);
8176 if (*pparams == NULL) {
8177 reply_nterror(req, NT_STATUS_NO_MEMORY);
8178 return;
8180 params = *pparams;
8182 SSVAL(params,0,0); /* No changes */
8183 SSVAL(params,2,0); /* No EA errors */
8185 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8187 return;
8190 /****************************************************************************
8191 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8192 ****************************************************************************/
8194 static void call_trans2getdfsreferral(connection_struct *conn,
8195 struct smb_request *req,
8196 char **pparams, int total_params,
8197 char **ppdata, int total_data,
8198 unsigned int max_data_bytes)
8200 char *params = *pparams;
8201 char *pathname = NULL;
8202 int reply_size = 0;
8203 int max_referral_level;
8204 NTSTATUS status = NT_STATUS_OK;
8205 TALLOC_CTX *ctx = talloc_tos();
8207 DEBUG(10,("call_trans2getdfsreferral\n"));
8209 if (total_params < 3) {
8210 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8211 return;
8214 max_referral_level = SVAL(params,0);
8216 if(!lp_host_msdfs()) {
8217 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8218 return;
8221 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8222 total_params - 2, STR_TERMINATE);
8223 if (!pathname) {
8224 reply_nterror(req, NT_STATUS_NOT_FOUND);
8225 return;
8227 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8228 ppdata,&status)) < 0) {
8229 reply_nterror(req, status);
8230 return;
8233 SSVAL(req->inbuf, smb_flg2,
8234 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8235 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8237 return;
8240 #define LMCAT_SPL 0x53
8241 #define LMFUNC_GETJOBID 0x60
8243 /****************************************************************************
8244 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8245 ****************************************************************************/
8247 static void call_trans2ioctl(connection_struct *conn,
8248 struct smb_request *req,
8249 char **pparams, int total_params,
8250 char **ppdata, int total_data,
8251 unsigned int max_data_bytes)
8253 char *pdata = *ppdata;
8254 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8256 /* check for an invalid fid before proceeding */
8258 if (!fsp) {
8259 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8260 return;
8263 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8264 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8265 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8266 if (*ppdata == NULL) {
8267 reply_nterror(req, NT_STATUS_NO_MEMORY);
8268 return;
8270 pdata = *ppdata;
8272 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8273 CAN ACCEPT THIS IN UNICODE. JRA. */
8275 /* Job number */
8276 if (fsp->print_file) {
8277 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8278 } else {
8279 SSVAL(pdata, 0, 0);
8281 srvstr_push(pdata, req->flags2, pdata + 2,
8282 global_myname(), 15,
8283 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8284 srvstr_push(pdata, req->flags2, pdata+18,
8285 lp_servicename(SNUM(conn)), 13,
8286 STR_ASCII|STR_TERMINATE); /* Service name */
8287 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8288 max_data_bytes);
8289 return;
8292 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8293 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8296 /****************************************************************************
8297 Reply to a SMBfindclose (stop trans2 directory search).
8298 ****************************************************************************/
8300 void reply_findclose(struct smb_request *req)
8302 int dptr_num;
8303 struct smbd_server_connection *sconn = smbd_server_conn;
8305 START_PROFILE(SMBfindclose);
8307 if (req->wct < 1) {
8308 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8309 END_PROFILE(SMBfindclose);
8310 return;
8313 dptr_num = SVALS(req->vwv+0, 0);
8315 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8317 dptr_close(sconn, &dptr_num);
8319 reply_outbuf(req, 0, 0);
8321 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8323 END_PROFILE(SMBfindclose);
8324 return;
8327 /****************************************************************************
8328 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8329 ****************************************************************************/
8331 void reply_findnclose(struct smb_request *req)
8333 int dptr_num;
8335 START_PROFILE(SMBfindnclose);
8337 if (req->wct < 1) {
8338 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8339 END_PROFILE(SMBfindnclose);
8340 return;
8343 dptr_num = SVAL(req->vwv+0, 0);
8345 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8347 /* We never give out valid handles for a
8348 findnotifyfirst - so any dptr_num is ok here.
8349 Just ignore it. */
8351 reply_outbuf(req, 0, 0);
8353 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8355 END_PROFILE(SMBfindnclose);
8356 return;
8359 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8360 struct trans_state *state)
8362 if (get_Protocol() >= PROTOCOL_NT1) {
8363 req->flags2 |= 0x40; /* IS_LONG_NAME */
8364 SSVAL(req->inbuf,smb_flg2,req->flags2);
8367 if (conn->encrypt_level == Required && !req->encrypted) {
8368 if (state->call != TRANSACT2_QFSINFO &&
8369 state->call != TRANSACT2_SETFSINFO) {
8370 DEBUG(0,("handle_trans2: encryption required "
8371 "with call 0x%x\n",
8372 (unsigned int)state->call));
8373 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8374 return;
8378 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8380 /* Now we must call the relevant TRANS2 function */
8381 switch(state->call) {
8382 case TRANSACT2_OPEN:
8384 START_PROFILE(Trans2_open);
8385 call_trans2open(conn, req,
8386 &state->param, state->total_param,
8387 &state->data, state->total_data,
8388 state->max_data_return);
8389 END_PROFILE(Trans2_open);
8390 break;
8393 case TRANSACT2_FINDFIRST:
8395 START_PROFILE(Trans2_findfirst);
8396 call_trans2findfirst(conn, req,
8397 &state->param, state->total_param,
8398 &state->data, state->total_data,
8399 state->max_data_return);
8400 END_PROFILE(Trans2_findfirst);
8401 break;
8404 case TRANSACT2_FINDNEXT:
8406 START_PROFILE(Trans2_findnext);
8407 call_trans2findnext(conn, req,
8408 &state->param, state->total_param,
8409 &state->data, state->total_data,
8410 state->max_data_return);
8411 END_PROFILE(Trans2_findnext);
8412 break;
8415 case TRANSACT2_QFSINFO:
8417 START_PROFILE(Trans2_qfsinfo);
8418 call_trans2qfsinfo(conn, req,
8419 &state->param, state->total_param,
8420 &state->data, state->total_data,
8421 state->max_data_return);
8422 END_PROFILE(Trans2_qfsinfo);
8423 break;
8426 case TRANSACT2_SETFSINFO:
8428 START_PROFILE(Trans2_setfsinfo);
8429 call_trans2setfsinfo(conn, req,
8430 &state->param, state->total_param,
8431 &state->data, state->total_data,
8432 state->max_data_return);
8433 END_PROFILE(Trans2_setfsinfo);
8434 break;
8437 case TRANSACT2_QPATHINFO:
8438 case TRANSACT2_QFILEINFO:
8440 START_PROFILE(Trans2_qpathinfo);
8441 call_trans2qfilepathinfo(conn, req, state->call,
8442 &state->param, state->total_param,
8443 &state->data, state->total_data,
8444 state->max_data_return);
8445 END_PROFILE(Trans2_qpathinfo);
8446 break;
8449 case TRANSACT2_SETPATHINFO:
8450 case TRANSACT2_SETFILEINFO:
8452 START_PROFILE(Trans2_setpathinfo);
8453 call_trans2setfilepathinfo(conn, req, state->call,
8454 &state->param, state->total_param,
8455 &state->data, state->total_data,
8456 state->max_data_return);
8457 END_PROFILE(Trans2_setpathinfo);
8458 break;
8461 case TRANSACT2_FINDNOTIFYFIRST:
8463 START_PROFILE(Trans2_findnotifyfirst);
8464 call_trans2findnotifyfirst(conn, req,
8465 &state->param, state->total_param,
8466 &state->data, state->total_data,
8467 state->max_data_return);
8468 END_PROFILE(Trans2_findnotifyfirst);
8469 break;
8472 case TRANSACT2_FINDNOTIFYNEXT:
8474 START_PROFILE(Trans2_findnotifynext);
8475 call_trans2findnotifynext(conn, req,
8476 &state->param, state->total_param,
8477 &state->data, state->total_data,
8478 state->max_data_return);
8479 END_PROFILE(Trans2_findnotifynext);
8480 break;
8483 case TRANSACT2_MKDIR:
8485 START_PROFILE(Trans2_mkdir);
8486 call_trans2mkdir(conn, req,
8487 &state->param, state->total_param,
8488 &state->data, state->total_data,
8489 state->max_data_return);
8490 END_PROFILE(Trans2_mkdir);
8491 break;
8494 case TRANSACT2_GET_DFS_REFERRAL:
8496 START_PROFILE(Trans2_get_dfs_referral);
8497 call_trans2getdfsreferral(conn, req,
8498 &state->param, state->total_param,
8499 &state->data, state->total_data,
8500 state->max_data_return);
8501 END_PROFILE(Trans2_get_dfs_referral);
8502 break;
8505 case TRANSACT2_IOCTL:
8507 START_PROFILE(Trans2_ioctl);
8508 call_trans2ioctl(conn, req,
8509 &state->param, state->total_param,
8510 &state->data, state->total_data,
8511 state->max_data_return);
8512 END_PROFILE(Trans2_ioctl);
8513 break;
8516 default:
8517 /* Error in request */
8518 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8519 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8523 /****************************************************************************
8524 Reply to a SMBtrans2.
8525 ****************************************************************************/
8527 void reply_trans2(struct smb_request *req)
8529 connection_struct *conn = req->conn;
8530 unsigned int dsoff;
8531 unsigned int dscnt;
8532 unsigned int psoff;
8533 unsigned int pscnt;
8534 unsigned int tran_call;
8535 struct trans_state *state;
8536 NTSTATUS result;
8538 START_PROFILE(SMBtrans2);
8540 if (req->wct < 14) {
8541 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8542 END_PROFILE(SMBtrans2);
8543 return;
8546 dsoff = SVAL(req->vwv+12, 0);
8547 dscnt = SVAL(req->vwv+11, 0);
8548 psoff = SVAL(req->vwv+10, 0);
8549 pscnt = SVAL(req->vwv+9, 0);
8550 tran_call = SVAL(req->vwv+14, 0);
8552 result = allow_new_trans(conn->pending_trans, req->mid);
8553 if (!NT_STATUS_IS_OK(result)) {
8554 DEBUG(2, ("Got invalid trans2 request: %s\n",
8555 nt_errstr(result)));
8556 reply_nterror(req, result);
8557 END_PROFILE(SMBtrans2);
8558 return;
8561 if (IS_IPC(conn)) {
8562 switch (tran_call) {
8563 /* List the allowed trans2 calls on IPC$ */
8564 case TRANSACT2_OPEN:
8565 case TRANSACT2_GET_DFS_REFERRAL:
8566 case TRANSACT2_QFILEINFO:
8567 case TRANSACT2_QFSINFO:
8568 case TRANSACT2_SETFSINFO:
8569 break;
8570 default:
8571 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8572 END_PROFILE(SMBtrans2);
8573 return;
8577 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8578 DEBUG(0, ("talloc failed\n"));
8579 reply_nterror(req, NT_STATUS_NO_MEMORY);
8580 END_PROFILE(SMBtrans2);
8581 return;
8584 state->cmd = SMBtrans2;
8586 state->mid = req->mid;
8587 state->vuid = req->vuid;
8588 state->setup_count = SVAL(req->vwv+13, 0);
8589 state->setup = NULL;
8590 state->total_param = SVAL(req->vwv+0, 0);
8591 state->param = NULL;
8592 state->total_data = SVAL(req->vwv+1, 0);
8593 state->data = NULL;
8594 state->max_param_return = SVAL(req->vwv+2, 0);
8595 state->max_data_return = SVAL(req->vwv+3, 0);
8596 state->max_setup_return = SVAL(req->vwv+4, 0);
8597 state->close_on_completion = BITSETW(req->vwv+5, 0);
8598 state->one_way = BITSETW(req->vwv+5, 1);
8600 state->call = tran_call;
8602 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8603 is so as a sanity check */
8604 if (state->setup_count != 1) {
8606 * Need to have rc=0 for ioctl to get job id for OS/2.
8607 * Network printing will fail if function is not successful.
8608 * Similar function in reply.c will be used if protocol
8609 * is LANMAN1.0 instead of LM1.2X002.
8610 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8611 * outbuf doesn't have to be set(only job id is used).
8613 if ( (state->setup_count == 4)
8614 && (tran_call == TRANSACT2_IOCTL)
8615 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8616 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8617 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8618 } else {
8619 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8620 DEBUG(2,("Transaction is %d\n",tran_call));
8621 TALLOC_FREE(state);
8622 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8623 END_PROFILE(SMBtrans2);
8624 return;
8628 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8629 goto bad_param;
8631 if (state->total_data) {
8633 if (trans_oob(state->total_data, 0, dscnt)
8634 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8635 goto bad_param;
8638 /* Can't use talloc here, the core routines do realloc on the
8639 * params and data. */
8640 state->data = (char *)SMB_MALLOC(state->total_data);
8641 if (state->data == NULL) {
8642 DEBUG(0,("reply_trans2: data malloc fail for %u "
8643 "bytes !\n", (unsigned int)state->total_data));
8644 TALLOC_FREE(state);
8645 reply_nterror(req, NT_STATUS_NO_MEMORY);
8646 END_PROFILE(SMBtrans2);
8647 return;
8650 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8653 if (state->total_param) {
8655 if (trans_oob(state->total_param, 0, pscnt)
8656 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8657 goto bad_param;
8660 /* Can't use talloc here, the core routines do realloc on the
8661 * params and data. */
8662 state->param = (char *)SMB_MALLOC(state->total_param);
8663 if (state->param == NULL) {
8664 DEBUG(0,("reply_trans: param malloc fail for %u "
8665 "bytes !\n", (unsigned int)state->total_param));
8666 SAFE_FREE(state->data);
8667 TALLOC_FREE(state);
8668 reply_nterror(req, NT_STATUS_NO_MEMORY);
8669 END_PROFILE(SMBtrans2);
8670 return;
8673 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8676 state->received_data = dscnt;
8677 state->received_param = pscnt;
8679 if ((state->received_param == state->total_param) &&
8680 (state->received_data == state->total_data)) {
8682 handle_trans2(conn, req, state);
8684 SAFE_FREE(state->data);
8685 SAFE_FREE(state->param);
8686 TALLOC_FREE(state);
8687 END_PROFILE(SMBtrans2);
8688 return;
8691 DLIST_ADD(conn->pending_trans, state);
8693 /* We need to send an interim response then receive the rest
8694 of the parameter/data bytes */
8695 reply_outbuf(req, 0, 0);
8696 show_msg((char *)req->outbuf);
8697 END_PROFILE(SMBtrans2);
8698 return;
8700 bad_param:
8702 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8703 SAFE_FREE(state->data);
8704 SAFE_FREE(state->param);
8705 TALLOC_FREE(state);
8706 END_PROFILE(SMBtrans2);
8707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8711 /****************************************************************************
8712 Reply to a SMBtranss2
8713 ****************************************************************************/
8715 void reply_transs2(struct smb_request *req)
8717 connection_struct *conn = req->conn;
8718 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8719 struct trans_state *state;
8721 START_PROFILE(SMBtranss2);
8723 show_msg((char *)req->inbuf);
8725 if (req->wct < 8) {
8726 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8727 END_PROFILE(SMBtranss2);
8728 return;
8731 for (state = conn->pending_trans; state != NULL;
8732 state = state->next) {
8733 if (state->mid == req->mid) {
8734 break;
8738 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8739 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8740 END_PROFILE(SMBtranss2);
8741 return;
8744 /* Revise state->total_param and state->total_data in case they have
8745 changed downwards */
8747 if (SVAL(req->vwv+0, 0) < state->total_param)
8748 state->total_param = SVAL(req->vwv+0, 0);
8749 if (SVAL(req->vwv+1, 0) < state->total_data)
8750 state->total_data = SVAL(req->vwv+1, 0);
8752 pcnt = SVAL(req->vwv+2, 0);
8753 poff = SVAL(req->vwv+3, 0);
8754 pdisp = SVAL(req->vwv+4, 0);
8756 dcnt = SVAL(req->vwv+5, 0);
8757 doff = SVAL(req->vwv+6, 0);
8758 ddisp = SVAL(req->vwv+7, 0);
8760 state->received_param += pcnt;
8761 state->received_data += dcnt;
8763 if ((state->received_data > state->total_data) ||
8764 (state->received_param > state->total_param))
8765 goto bad_param;
8767 if (pcnt) {
8768 if (trans_oob(state->total_param, pdisp, pcnt)
8769 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8770 goto bad_param;
8772 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8775 if (dcnt) {
8776 if (trans_oob(state->total_data, ddisp, dcnt)
8777 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8778 goto bad_param;
8780 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8783 if ((state->received_param < state->total_param) ||
8784 (state->received_data < state->total_data)) {
8785 END_PROFILE(SMBtranss2);
8786 return;
8789 handle_trans2(conn, req, state);
8791 DLIST_REMOVE(conn->pending_trans, state);
8792 SAFE_FREE(state->data);
8793 SAFE_FREE(state->param);
8794 TALLOC_FREE(state);
8796 END_PROFILE(SMBtranss2);
8797 return;
8799 bad_param:
8801 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8802 DLIST_REMOVE(conn->pending_trans, state);
8803 SAFE_FREE(state->data);
8804 SAFE_FREE(state->param);
8805 TALLOC_FREE(state);
8806 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8807 END_PROFILE(SMBtranss2);
8808 return;