Implement rename/move in SMB2 from Windows7.
[Samba.git] / source3 / smbd / trans2.c
blobeff5fba6760649b73e9fb3ac14876aa9561ed8d7
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "version.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 #define DIR_ENTRY_SAFETY_MARGIN 4096
33 static char *store_file_unix_basic(connection_struct *conn,
34 char *pdata,
35 files_struct *fsp,
36 const SMB_STRUCT_STAT *psbuf);
38 static char *store_file_unix_basic_info2(connection_struct *conn,
39 char *pdata,
40 files_struct *fsp,
41 const SMB_STRUCT_STAT *psbuf);
43 /********************************************************************
44 Roundup a value to the nearest allocation roundup size boundary.
45 Only do this for Windows clients.
46 ********************************************************************/
48 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
50 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
52 /* Only roundup for Windows clients. */
53 enum remote_arch_types ra_type = get_remote_arch();
54 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
55 val = SMB_ROUNDUP(val,rval);
57 return val;
60 /****************************************************************************
61 Utility functions for dealing with extended attributes.
62 ****************************************************************************/
64 /****************************************************************************
65 Refuse to allow clients to overwrite our private xattrs.
66 ****************************************************************************/
68 static bool samba_private_attr_name(const char *unix_ea_name)
70 static const char * const prohibited_ea_names[] = {
71 SAMBA_POSIX_INHERITANCE_EA_NAME,
72 SAMBA_XATTR_DOS_ATTRIB,
73 SAMBA_XATTR_MARKER,
74 XATTR_NTACL_NAME,
75 NULL
78 int i;
80 for (i = 0; prohibited_ea_names[i]; i++) {
81 if (strequal( prohibited_ea_names[i], unix_ea_name))
82 return true;
84 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
86 return true;
88 return false;
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
96 files_struct *fsp, const char *fname,
97 const char *ea_name, struct ea_struct *pea)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size = 256;
101 char *val = NULL;
102 ssize_t sizeret;
104 again:
106 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
107 if (!val) {
108 return NT_STATUS_NO_MEMORY;
111 if (fsp && fsp->fh->fd != -1) {
112 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
113 } else {
114 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
117 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
118 attr_size = 65536;
119 goto again;
122 if (sizeret == -1) {
123 return map_nt_error_from_unix(errno);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
127 dump_data(10, (uint8 *)val, sizeret);
129 pea->flags = 0;
130 if (strnequal(ea_name, "user.", 5)) {
131 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
132 } else {
133 pea->name = talloc_strdup(mem_ctx, ea_name);
135 if (pea->name == NULL) {
136 TALLOC_FREE(val);
137 return NT_STATUS_NO_MEMORY;
139 pea->value.data = (unsigned char *)val;
140 pea->value.length = (size_t)sizeret;
141 return NT_STATUS_OK;
144 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
145 files_struct *fsp, const char *fname,
146 char ***pnames, size_t *pnum_names)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size = 1024;
150 char *ea_namelist = NULL;
152 char *p;
153 char **names, **tmp;
154 size_t num_names;
155 ssize_t sizeret = -1;
157 if (!lp_ea_support(SNUM(conn))) {
158 if (pnames) {
159 *pnames = NULL;
161 *pnum_names = 0;
162 return NT_STATUS_OK;
166 * TALLOC the result early to get the talloc hierarchy right.
169 names = TALLOC_ARRAY(mem_ctx, char *, 1);
170 if (names == NULL) {
171 DEBUG(0, ("talloc failed\n"));
172 return NT_STATUS_NO_MEMORY;
175 while (ea_namelist_size <= 65536) {
177 ea_namelist = TALLOC_REALLOC_ARRAY(
178 names, ea_namelist, char, ea_namelist_size);
179 if (ea_namelist == NULL) {
180 DEBUG(0, ("talloc failed\n"));
181 TALLOC_FREE(names);
182 return NT_STATUS_NO_MEMORY;
185 if (fsp && fsp->fh->fd != -1) {
186 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
187 ea_namelist_size);
188 } else {
189 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
190 ea_namelist_size);
193 if ((sizeret == -1) && (errno == ERANGE)) {
194 ea_namelist_size *= 2;
196 else {
197 break;
201 if (sizeret == -1) {
202 TALLOC_FREE(names);
203 return map_nt_error_from_unix(errno);
206 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
207 (unsigned int)sizeret));
209 if (sizeret == 0) {
210 TALLOC_FREE(names);
211 if (pnames) {
212 *pnames = NULL;
214 *pnum_names = 0;
215 return NT_STATUS_OK;
219 * Ensure the result is 0-terminated
222 if (ea_namelist[sizeret-1] != '\0') {
223 TALLOC_FREE(names);
224 return NT_STATUS_INTERNAL_ERROR;
228 * count the names
230 num_names = 0;
232 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
233 num_names += 1;
236 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
237 if (tmp == NULL) {
238 DEBUG(0, ("talloc failed\n"));
239 TALLOC_FREE(names);
240 return NT_STATUS_NO_MEMORY;
243 names = tmp;
244 num_names = 0;
246 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
247 names[num_names++] = p;
250 if (pnames) {
251 *pnames = names;
252 } else {
253 TALLOC_FREE(names);
255 *pnum_names = num_names;
256 return NT_STATUS_OK;
259 /****************************************************************************
260 Return a linked list of the total EA's. Plus the total size
261 ****************************************************************************/
263 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
264 const char *fname, size_t *pea_total_len)
266 /* Get a list of all xattrs. Max namesize is 64k. */
267 size_t i, num_names;
268 char **names;
269 struct ea_list *ea_list_head = NULL;
270 NTSTATUS status;
272 *pea_total_len = 0;
274 if (!lp_ea_support(SNUM(conn))) {
275 return NULL;
278 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
279 &names, &num_names);
281 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
282 return NULL;
285 for (i=0; i<num_names; i++) {
286 struct ea_list *listp;
287 fstring dos_ea_name;
289 if (strnequal(names[i], "system.", 7)
290 || samba_private_attr_name(names[i]))
291 continue;
293 listp = TALLOC_P(mem_ctx, struct ea_list);
294 if (listp == NULL) {
295 return NULL;
298 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
299 fname, names[i],
300 &listp->ea))) {
301 return NULL;
304 push_ascii_fstring(dos_ea_name, listp->ea.name);
306 *pea_total_len +=
307 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
309 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
310 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
311 (unsigned int)listp->ea.value.length));
313 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
317 /* Add on 4 for total length. */
318 if (*pea_total_len) {
319 *pea_total_len += 4;
322 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
323 (unsigned int)*pea_total_len));
325 return ea_list_head;
328 /****************************************************************************
329 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
330 that was filled.
331 ****************************************************************************/
333 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
334 connection_struct *conn, struct ea_list *ea_list)
336 unsigned int ret_data_size = 4;
337 char *p = pdata;
339 SMB_ASSERT(total_data_size >= 4);
341 if (!lp_ea_support(SNUM(conn))) {
342 SIVAL(pdata,4,0);
343 return 4;
346 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
347 size_t dos_namelen;
348 fstring dos_ea_name;
349 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
350 dos_namelen = strlen(dos_ea_name);
351 if (dos_namelen > 255 || dos_namelen == 0) {
352 break;
354 if (ea_list->ea.value.length > 65535) {
355 break;
357 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
358 break;
361 /* We know we have room. */
362 SCVAL(p,0,ea_list->ea.flags);
363 SCVAL(p,1,dos_namelen);
364 SSVAL(p,2,ea_list->ea.value.length);
365 fstrcpy(p+4, dos_ea_name);
366 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
368 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
369 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
372 ret_data_size = PTR_DIFF(p, pdata);
373 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
374 SIVAL(pdata,0,ret_data_size);
375 return ret_data_size;
378 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
379 char *pdata,
380 unsigned int total_data_size,
381 unsigned int *ret_data_size,
382 connection_struct *conn,
383 struct ea_list *ea_list)
385 uint8_t *p = (uint8_t *)pdata;
386 uint8_t *last_start = NULL;
388 *ret_data_size = 0;
390 if (!lp_ea_support(SNUM(conn))) {
391 return NT_STATUS_NO_EAS_ON_FILE;
394 for (; ea_list; ea_list = ea_list->next) {
395 size_t dos_namelen;
396 fstring dos_ea_name;
397 size_t this_size;
399 if (last_start) {
400 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
402 last_start = p;
404 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
405 dos_namelen = strlen(dos_ea_name);
406 if (dos_namelen > 255 || dos_namelen == 0) {
407 return NT_STATUS_INTERNAL_ERROR;
409 if (ea_list->ea.value.length > 65535) {
410 return NT_STATUS_INTERNAL_ERROR;
413 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
415 if (ea_list->next) {
416 size_t pad = 4 - (this_size % 4);
417 this_size += pad;
420 if (this_size > total_data_size) {
421 return NT_STATUS_INFO_LENGTH_MISMATCH;
424 /* We know we have room. */
425 SIVAL(p, 0x00, 0); /* next offset */
426 SCVAL(p, 0x04, ea_list->ea.flags);
427 SCVAL(p, 0x05, dos_namelen);
428 SSVAL(p, 0x06, ea_list->ea.value.length);
429 fstrcpy((char *)(p+0x08), dos_ea_name);
430 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
432 total_data_size -= this_size;
433 p += this_size;
436 *ret_data_size = PTR_DIFF(p, pdata);
437 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
438 return NT_STATUS_OK;
441 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
443 size_t total_ea_len = 0;
444 TALLOC_CTX *mem_ctx = NULL;
446 if (!lp_ea_support(SNUM(conn))) {
447 return 0;
449 mem_ctx = talloc_tos();
450 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
451 return total_ea_len;
454 /****************************************************************************
455 Ensure the EA name is case insensitive by matching any existing EA name.
456 ****************************************************************************/
458 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
460 size_t total_ea_len;
461 TALLOC_CTX *mem_ctx = talloc_tos();
462 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
464 for (; ea_list; ea_list = ea_list->next) {
465 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
466 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
467 &unix_ea_name[5], ea_list->ea.name));
468 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
469 break;
474 /****************************************************************************
475 Set or delete an extended attribute.
476 ****************************************************************************/
478 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
479 const struct smb_filename *smb_fname, struct ea_list *ea_list)
481 char *fname = NULL;
483 if (!lp_ea_support(SNUM(conn))) {
484 return NT_STATUS_EAS_NOT_SUPPORTED;
487 /* For now setting EAs on streams isn't supported. */
488 fname = smb_fname->base_name;
490 for (;ea_list; ea_list = ea_list->next) {
491 int ret;
492 fstring unix_ea_name;
494 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
495 fstrcat(unix_ea_name, ea_list->ea.name);
497 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
499 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
501 if (samba_private_attr_name(unix_ea_name)) {
502 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
503 return NT_STATUS_ACCESS_DENIED;
506 if (ea_list->ea.value.length == 0) {
507 /* Remove the attribute. */
508 if (fsp && (fsp->fh->fd != -1)) {
509 DEBUG(10,("set_ea: deleting ea name %s on "
510 "file %s by file descriptor.\n",
511 unix_ea_name, fsp_str_dbg(fsp)));
512 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
513 } else {
514 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
515 unix_ea_name, fname));
516 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
518 #ifdef ENOATTR
519 /* Removing a non existent attribute always succeeds. */
520 if (ret == -1 && errno == ENOATTR) {
521 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
522 unix_ea_name));
523 ret = 0;
525 #endif
526 } else {
527 if (fsp && (fsp->fh->fd != -1)) {
528 DEBUG(10,("set_ea: setting ea name %s on file "
529 "%s by file descriptor.\n",
530 unix_ea_name, fsp_str_dbg(fsp)));
531 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
532 ea_list->ea.value.data, ea_list->ea.value.length, 0);
533 } else {
534 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
535 unix_ea_name, fname));
536 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
537 ea_list->ea.value.data, ea_list->ea.value.length, 0);
541 if (ret == -1) {
542 #ifdef ENOTSUP
543 if (errno == ENOTSUP) {
544 return NT_STATUS_EAS_NOT_SUPPORTED;
546 #endif
547 return map_nt_error_from_unix(errno);
551 return NT_STATUS_OK;
553 /****************************************************************************
554 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
555 ****************************************************************************/
557 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
559 struct ea_list *ea_list_head = NULL;
560 size_t converted_size, offset = 0;
562 while (offset + 2 < data_size) {
563 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
564 unsigned int namelen = CVAL(pdata,offset);
566 offset++; /* Go past the namelen byte. */
568 /* integer wrap paranioa. */
569 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
570 (offset > data_size) || (namelen > data_size) ||
571 (offset + namelen >= data_size)) {
572 break;
574 /* Ensure the name is null terminated. */
575 if (pdata[offset + namelen] != '\0') {
576 return NULL;
578 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
579 &converted_size)) {
580 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
581 "failed: %s", strerror(errno)));
583 if (!eal->ea.name) {
584 return NULL;
587 offset += (namelen + 1); /* Go past the name + terminating zero. */
588 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
589 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
592 return ea_list_head;
595 /****************************************************************************
596 Read one EA list entry from the buffer.
597 ****************************************************************************/
599 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
601 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
602 uint16 val_len;
603 unsigned int namelen;
604 size_t converted_size;
606 if (!eal) {
607 return NULL;
610 if (data_size < 6) {
611 return NULL;
614 eal->ea.flags = CVAL(pdata,0);
615 namelen = CVAL(pdata,1);
616 val_len = SVAL(pdata,2);
618 if (4 + namelen + 1 + val_len > data_size) {
619 return NULL;
622 /* Ensure the name is null terminated. */
623 if (pdata[namelen + 4] != '\0') {
624 return NULL;
626 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
627 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
628 strerror(errno)));
630 if (!eal->ea.name) {
631 return NULL;
634 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
635 if (!eal->ea.value.data) {
636 return NULL;
639 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
641 /* Ensure we're null terminated just in case we print the value. */
642 eal->ea.value.data[val_len] = '\0';
643 /* But don't count the null. */
644 eal->ea.value.length--;
646 if (pbytes_used) {
647 *pbytes_used = 4 + namelen + 1 + val_len;
650 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
651 dump_data(10, eal->ea.value.data, eal->ea.value.length);
653 return eal;
656 /****************************************************************************
657 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
658 ****************************************************************************/
660 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
662 struct ea_list *ea_list_head = NULL;
663 size_t offset = 0;
664 size_t bytes_used = 0;
666 while (offset < data_size) {
667 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
669 if (!eal) {
670 return NULL;
673 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
674 offset += bytes_used;
677 return ea_list_head;
680 /****************************************************************************
681 Count the total EA size needed.
682 ****************************************************************************/
684 static size_t ea_list_size(struct ea_list *ealist)
686 fstring dos_ea_name;
687 struct ea_list *listp;
688 size_t ret = 0;
690 for (listp = ealist; listp; listp = listp->next) {
691 push_ascii_fstring(dos_ea_name, listp->ea.name);
692 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
694 /* Add on 4 for total length. */
695 if (ret) {
696 ret += 4;
699 return ret;
702 /****************************************************************************
703 Return a union of EA's from a file list and a list of names.
704 The TALLOC context for the two lists *MUST* be identical as we steal
705 memory from one list to add to another. JRA.
706 ****************************************************************************/
708 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
710 struct ea_list *nlistp, *flistp;
712 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
713 for (flistp = file_list; flistp; flistp = flistp->next) {
714 if (strequal(nlistp->ea.name, flistp->ea.name)) {
715 break;
719 if (flistp) {
720 /* Copy the data from this entry. */
721 nlistp->ea.flags = flistp->ea.flags;
722 nlistp->ea.value = flistp->ea.value;
723 } else {
724 /* Null entry. */
725 nlistp->ea.flags = 0;
726 ZERO_STRUCT(nlistp->ea.value);
730 *total_ea_len = ea_list_size(name_list);
731 return name_list;
734 /****************************************************************************
735 Send the required number of replies back.
736 We assume all fields other than the data fields are
737 set correctly for the type of call.
738 HACK ! Always assumes smb_setup field is zero.
739 ****************************************************************************/
741 void send_trans2_replies(connection_struct *conn,
742 struct smb_request *req,
743 const char *params,
744 int paramsize,
745 const char *pdata,
746 int datasize,
747 int max_data_bytes)
749 /* As we are using a protocol > LANMAN1 then the max_send
750 variable must have been set in the sessetupX call.
751 This takes precedence over the max_xmit field in the
752 global struct. These different max_xmit variables should
753 be merged as this is now too confusing */
755 int data_to_send = datasize;
756 int params_to_send = paramsize;
757 int useable_space;
758 const char *pp = params;
759 const char *pd = pdata;
760 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
761 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
762 int data_alignment_offset = 0;
763 bool overflow = False;
764 struct smbd_server_connection *sconn = smbd_server_conn;
765 int max_send = sconn->smb1.sessions.max_send;
767 /* Modify the data_to_send and datasize and set the error if
768 we're trying to send more than max_data_bytes. We still send
769 the part of the packet(s) that fit. Strange, but needed
770 for OS/2. */
772 if (max_data_bytes > 0 && datasize > max_data_bytes) {
773 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
774 max_data_bytes, datasize ));
775 datasize = data_to_send = max_data_bytes;
776 overflow = True;
779 /* If there genuinely are no parameters or data to send just send the empty packet */
781 if(params_to_send == 0 && data_to_send == 0) {
782 reply_outbuf(req, 10, 0);
783 show_msg((char *)req->outbuf);
784 if (!srv_send_smb(smbd_server_fd(),
785 (char *)req->outbuf,
786 true, req->seqnum+1,
787 IS_CONN_ENCRYPTED(conn),
788 &req->pcd)) {
789 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
791 TALLOC_FREE(req->outbuf);
792 return;
795 /* When sending params and data ensure that both are nicely aligned */
796 /* Only do this alignment when there is also data to send - else
797 can cause NT redirector problems. */
799 if (((params_to_send % 4) != 0) && (data_to_send != 0))
800 data_alignment_offset = 4 - (params_to_send % 4);
802 /* Space is bufsize minus Netbios over TCP header minus SMB header */
803 /* The alignment_offset is to align the param bytes on an even byte
804 boundary. NT 4.0 Beta needs this to work correctly. */
806 useable_space = max_send - (smb_size
807 + 2 * 10 /* wct */
808 + alignment_offset
809 + data_alignment_offset);
811 if (useable_space < 0) {
812 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
813 "= %d!!!", useable_space));
814 exit_server_cleanly("send_trans2_replies: Not enough space");
817 while (params_to_send || data_to_send) {
818 /* Calculate whether we will totally or partially fill this packet */
820 total_sent_thistime = params_to_send + data_to_send;
822 /* We can never send more than useable_space */
824 * Note that 'useable_space' does not include the alignment offsets,
825 * but we must include the alignment offsets in the calculation of
826 * the length of the data we send over the wire, as the alignment offsets
827 * are sent here. Fix from Marc_Jacobsen@hp.com.
830 total_sent_thistime = MIN(total_sent_thistime, useable_space);
832 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
833 + data_alignment_offset);
836 * We might have SMBtrans2s in req which was transferred to
837 * the outbuf, fix that.
839 SCVAL(req->outbuf, smb_com, SMBtrans2);
841 /* Set total params and data to be sent */
842 SSVAL(req->outbuf,smb_tprcnt,paramsize);
843 SSVAL(req->outbuf,smb_tdrcnt,datasize);
845 /* Calculate how many parameters and data we can fit into
846 * this packet. Parameters get precedence
849 params_sent_thistime = MIN(params_to_send,useable_space);
850 data_sent_thistime = useable_space - params_sent_thistime;
851 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
853 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
855 /* smb_proff is the offset from the start of the SMB header to the
856 parameter bytes, however the first 4 bytes of outbuf are
857 the Netbios over TCP header. Thus use smb_base() to subtract
858 them from the calculation */
860 SSVAL(req->outbuf,smb_proff,
861 ((smb_buf(req->outbuf)+alignment_offset)
862 - smb_base(req->outbuf)));
864 if(params_sent_thistime == 0)
865 SSVAL(req->outbuf,smb_prdisp,0);
866 else
867 /* Absolute displacement of param bytes sent in this packet */
868 SSVAL(req->outbuf,smb_prdisp,pp - params);
870 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
871 if(data_sent_thistime == 0) {
872 SSVAL(req->outbuf,smb_droff,0);
873 SSVAL(req->outbuf,smb_drdisp, 0);
874 } else {
875 /* The offset of the data bytes is the offset of the
876 parameter bytes plus the number of parameters being sent this time */
877 SSVAL(req->outbuf, smb_droff,
878 ((smb_buf(req->outbuf)+alignment_offset)
879 - smb_base(req->outbuf))
880 + params_sent_thistime + data_alignment_offset);
881 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
884 /* Initialize the padding for alignment */
886 if (alignment_offset != 0) {
887 memset(smb_buf(req->outbuf), 0, alignment_offset);
890 /* Copy the param bytes into the packet */
892 if(params_sent_thistime) {
893 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
894 params_sent_thistime);
897 /* Copy in the data bytes */
898 if(data_sent_thistime) {
899 if (data_alignment_offset != 0) {
900 memset((smb_buf(req->outbuf)+alignment_offset+
901 params_sent_thistime), 0,
902 data_alignment_offset);
904 memcpy(smb_buf(req->outbuf)+alignment_offset
905 +params_sent_thistime+data_alignment_offset,
906 pd,data_sent_thistime);
909 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
910 params_sent_thistime, data_sent_thistime, useable_space));
911 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
912 params_to_send, data_to_send, paramsize, datasize));
914 if (overflow) {
915 error_packet_set((char *)req->outbuf,
916 ERRDOS,ERRbufferoverflow,
917 STATUS_BUFFER_OVERFLOW,
918 __LINE__,__FILE__);
921 /* Send the packet */
922 show_msg((char *)req->outbuf);
923 if (!srv_send_smb(smbd_server_fd(),
924 (char *)req->outbuf,
925 true, req->seqnum+1,
926 IS_CONN_ENCRYPTED(conn),
927 &req->pcd))
928 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
930 TALLOC_FREE(req->outbuf);
932 pp += params_sent_thistime;
933 pd += data_sent_thistime;
935 params_to_send -= params_sent_thistime;
936 data_to_send -= data_sent_thistime;
938 /* Sanity check */
939 if(params_to_send < 0 || data_to_send < 0) {
940 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
941 params_to_send, data_to_send));
942 return;
946 return;
949 /****************************************************************************
950 Reply to a TRANSACT2_OPEN.
951 ****************************************************************************/
953 static void call_trans2open(connection_struct *conn,
954 struct smb_request *req,
955 char **pparams, int total_params,
956 char **ppdata, int total_data,
957 unsigned int max_data_bytes)
959 struct smb_filename *smb_fname = NULL;
960 char *params = *pparams;
961 char *pdata = *ppdata;
962 int deny_mode;
963 int32 open_attr;
964 bool oplock_request;
965 #if 0
966 bool return_additional_info;
967 int16 open_sattr;
968 time_t open_time;
969 #endif
970 int open_ofun;
971 uint32 open_size;
972 char *pname;
973 char *fname = NULL;
974 SMB_OFF_T size=0;
975 int fattr=0,mtime=0;
976 SMB_INO_T inode = 0;
977 int smb_action = 0;
978 files_struct *fsp;
979 struct ea_list *ea_list = NULL;
980 uint16 flags = 0;
981 NTSTATUS status;
982 uint32 access_mask;
983 uint32 share_mode;
984 uint32 create_disposition;
985 uint32 create_options = 0;
986 TALLOC_CTX *ctx = talloc_tos();
989 * Ensure we have enough parameters to perform the operation.
992 if (total_params < 29) {
993 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
994 goto out;
997 flags = SVAL(params, 0);
998 deny_mode = SVAL(params, 2);
999 open_attr = SVAL(params,6);
1000 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1001 if (oplock_request) {
1002 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1005 #if 0
1006 return_additional_info = BITSETW(params,0);
1007 open_sattr = SVAL(params, 4);
1008 open_time = make_unix_date3(params+8);
1009 #endif
1010 open_ofun = SVAL(params,12);
1011 open_size = IVAL(params,14);
1012 pname = &params[28];
1014 if (IS_IPC(conn)) {
1015 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1016 goto out;
1019 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1020 total_params - 28, STR_TERMINATE,
1021 &status);
1022 if (!NT_STATUS_IS_OK(status)) {
1023 reply_nterror(req, status);
1024 goto out;
1027 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1028 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1029 (unsigned int)open_ofun, open_size));
1031 status = filename_convert(ctx,
1032 conn,
1033 req->flags2 & FLAGS2_DFS_PATHNAMES,
1034 fname,
1036 NULL,
1037 &smb_fname);
1038 if (!NT_STATUS_IS_OK(status)) {
1039 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1040 reply_botherror(req,
1041 NT_STATUS_PATH_NOT_COVERED,
1042 ERRSRV, ERRbadpath);
1043 goto out;
1045 reply_nterror(req, status);
1046 goto out;
1049 if (open_ofun == 0) {
1050 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1051 goto out;
1054 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1055 &access_mask, &share_mode,
1056 &create_disposition,
1057 &create_options)) {
1058 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1059 goto out;
1062 /* Any data in this call is an EA list. */
1063 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1064 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1065 goto out;
1068 if (total_data != 4) {
1069 if (total_data < 10) {
1070 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1071 goto out;
1074 if (IVAL(pdata,0) > total_data) {
1075 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1076 IVAL(pdata,0), (unsigned int)total_data));
1077 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1078 goto out;
1081 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1082 total_data - 4);
1083 if (!ea_list) {
1084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1085 goto out;
1087 } else if (IVAL(pdata,0) != 4) {
1088 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1089 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 NULL, /* sd */
1105 ea_list, /* ea_list */
1106 &fsp, /* result */
1107 &smb_action); /* psbuf */
1109 if (!NT_STATUS_IS_OK(status)) {
1110 if (open_was_deferred(req->mid)) {
1111 /* We have re-scheduled this call. */
1112 goto out;
1114 reply_openerror(req, status);
1115 goto out;
1118 size = get_file_size_stat(&smb_fname->st);
1119 fattr = dos_mode(conn, smb_fname);
1120 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1121 inode = smb_fname->st.st_ex_ino;
1122 if (fattr & aDIR) {
1123 close_file(req, fsp, ERROR_CLOSE);
1124 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1125 goto out;
1128 /* Realloc the size of parameters and data we will return */
1129 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1130 if(*pparams == NULL ) {
1131 reply_nterror(req, NT_STATUS_NO_MEMORY);
1132 goto out;
1134 params = *pparams;
1136 SSVAL(params,0,fsp->fnum);
1137 SSVAL(params,2,fattr);
1138 srv_put_dos_date2(params,4, mtime);
1139 SIVAL(params,8, (uint32)size);
1140 SSVAL(params,12,deny_mode);
1141 SSVAL(params,14,0); /* open_type - file or directory. */
1142 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1144 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1145 smb_action |= EXTENDED_OPLOCK_GRANTED;
1148 SSVAL(params,18,smb_action);
1151 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1153 SIVAL(params,20,inode);
1154 SSVAL(params,24,0); /* Padding. */
1155 if (flags & 8) {
1156 uint32 ea_size = estimate_ea_size(conn, fsp,
1157 fsp->fsp_name->base_name);
1158 SIVAL(params, 26, ea_size);
1159 } else {
1160 SIVAL(params, 26, 0);
1163 /* Send the required number of replies */
1164 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1165 out:
1166 TALLOC_FREE(smb_fname);
1169 /*********************************************************
1170 Routine to check if a given string matches exactly.
1171 as a special case a mask of "." does NOT match. That
1172 is required for correct wildcard semantics
1173 Case can be significant or not.
1174 **********************************************************/
1176 static bool exact_match(bool has_wild,
1177 bool case_sensitive,
1178 const char *str,
1179 const char *mask)
1181 if (mask[0] == '.' && mask[1] == 0) {
1182 return false;
1185 if (has_wild) {
1186 return false;
1189 if (case_sensitive) {
1190 return strcmp(str,mask)==0;
1191 } else {
1192 return StrCaseCmp(str,mask) == 0;
1196 /****************************************************************************
1197 Return the filetype for UNIX extensions.
1198 ****************************************************************************/
1200 static uint32 unix_filetype(mode_t mode)
1202 if(S_ISREG(mode))
1203 return UNIX_TYPE_FILE;
1204 else if(S_ISDIR(mode))
1205 return UNIX_TYPE_DIR;
1206 #ifdef S_ISLNK
1207 else if(S_ISLNK(mode))
1208 return UNIX_TYPE_SYMLINK;
1209 #endif
1210 #ifdef S_ISCHR
1211 else if(S_ISCHR(mode))
1212 return UNIX_TYPE_CHARDEV;
1213 #endif
1214 #ifdef S_ISBLK
1215 else if(S_ISBLK(mode))
1216 return UNIX_TYPE_BLKDEV;
1217 #endif
1218 #ifdef S_ISFIFO
1219 else if(S_ISFIFO(mode))
1220 return UNIX_TYPE_FIFO;
1221 #endif
1222 #ifdef S_ISSOCK
1223 else if(S_ISSOCK(mode))
1224 return UNIX_TYPE_SOCKET;
1225 #endif
1227 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1228 return UNIX_TYPE_UNKNOWN;
1231 /****************************************************************************
1232 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1233 ****************************************************************************/
1235 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1237 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1238 const SMB_STRUCT_STAT *psbuf,
1239 uint32 perms,
1240 enum perm_type ptype,
1241 mode_t *ret_perms)
1243 mode_t ret = 0;
1245 if (perms == SMB_MODE_NO_CHANGE) {
1246 if (!VALID_STAT(*psbuf)) {
1247 return NT_STATUS_INVALID_PARAMETER;
1248 } else {
1249 *ret_perms = psbuf->st_ex_mode;
1250 return NT_STATUS_OK;
1254 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1255 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1256 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1257 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1258 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1259 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1260 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1261 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1262 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1263 #ifdef S_ISVTX
1264 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1265 #endif
1266 #ifdef S_ISGID
1267 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1268 #endif
1269 #ifdef S_ISUID
1270 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1271 #endif
1273 switch (ptype) {
1274 case PERM_NEW_FILE:
1275 /* Apply mode mask */
1276 ret &= lp_create_mask(SNUM(conn));
1277 /* Add in force bits */
1278 ret |= lp_force_create_mode(SNUM(conn));
1279 break;
1280 case PERM_NEW_DIR:
1281 ret &= lp_dir_mask(SNUM(conn));
1282 /* Add in force bits */
1283 ret |= lp_force_dir_mode(SNUM(conn));
1284 break;
1285 case PERM_EXISTING_FILE:
1286 /* Apply mode mask */
1287 ret &= lp_security_mask(SNUM(conn));
1288 /* Add in force bits */
1289 ret |= lp_force_security_mode(SNUM(conn));
1290 break;
1291 case PERM_EXISTING_DIR:
1292 /* Apply mode mask */
1293 ret &= lp_dir_security_mask(SNUM(conn));
1294 /* Add in force bits */
1295 ret |= lp_force_dir_security_mode(SNUM(conn));
1296 break;
1299 *ret_perms = ret;
1300 return NT_STATUS_OK;
1303 /****************************************************************************
1304 Needed to show the msdfs symlinks as directories. Modifies psbuf
1305 to be a directory if it's a msdfs link.
1306 ****************************************************************************/
1308 static bool check_msdfs_link(connection_struct *conn,
1309 const char *pathname,
1310 SMB_STRUCT_STAT *psbuf)
1312 int saved_errno = errno;
1313 if(lp_host_msdfs() &&
1314 lp_msdfs_root(SNUM(conn)) &&
1315 is_msdfs_link(conn, pathname, psbuf)) {
1317 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1318 "as a directory\n",
1319 pathname));
1320 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1321 errno = saved_errno;
1322 return true;
1324 errno = saved_errno;
1325 return false;
1329 /****************************************************************************
1330 Get a level dependent lanman2 dir entry.
1331 ****************************************************************************/
1333 struct smbd_dirptr_lanman2_state {
1334 connection_struct *conn;
1335 uint32_t info_level;
1336 bool check_mangled_names;
1337 bool has_wild;
1338 bool got_exact_match;
1341 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1342 void *private_data,
1343 const char *dname,
1344 const char *mask,
1345 char **_fname)
1347 struct smbd_dirptr_lanman2_state *state =
1348 (struct smbd_dirptr_lanman2_state *)private_data;
1349 bool ok;
1350 char mangled_name[13]; /* mangled 8.3 name. */
1351 bool got_match;
1352 const char *fname;
1354 /* Mangle fname if it's an illegal name. */
1355 if (mangle_must_mangle(dname, state->conn->params)) {
1356 ok = name_to_8_3(dname, mangled_name,
1357 true, state->conn->params);
1358 if (!ok) {
1359 return false;
1361 fname = mangled_name;
1362 } else {
1363 fname = dname;
1366 got_match = exact_match(state->has_wild,
1367 state->conn->case_sensitive,
1368 fname, mask);
1369 state->got_exact_match = got_match;
1370 if (!got_match) {
1371 got_match = mask_match(fname, mask,
1372 state->conn->case_sensitive);
1375 if(!got_match && state->check_mangled_names &&
1376 !mangle_is_8_3(fname, false, state->conn->params)) {
1378 * It turns out that NT matches wildcards against
1379 * both long *and* short names. This may explain some
1380 * of the wildcard wierdness from old DOS clients
1381 * that some people have been seeing.... JRA.
1383 /* Force the mangling into 8.3. */
1384 ok = name_to_8_3(fname, mangled_name,
1385 false, state->conn->params);
1386 if (!ok) {
1387 return false;
1390 got_match = exact_match(state->has_wild,
1391 state->conn->case_sensitive,
1392 mangled_name, mask);
1393 state->got_exact_match = got_match;
1394 if (!got_match) {
1395 got_match = mask_match(mangled_name, mask,
1396 state->conn->case_sensitive);
1400 if (!got_match) {
1401 return false;
1404 *_fname = talloc_strdup(ctx, fname);
1405 if (*_fname == NULL) {
1406 return false;
1409 return true;
1412 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1413 void *private_data,
1414 struct smb_filename *smb_fname,
1415 uint32_t *_mode)
1417 struct smbd_dirptr_lanman2_state *state =
1418 (struct smbd_dirptr_lanman2_state *)private_data;
1419 bool ms_dfs_link = false;
1420 uint32_t mode = 0;
1422 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1423 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1424 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1425 "Couldn't lstat [%s] (%s)\n",
1426 smb_fname_str_dbg(smb_fname),
1427 strerror(errno)));
1428 return false;
1430 } else if (!VALID_STAT(smb_fname->st) &&
1431 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1432 /* Needed to show the msdfs symlinks as
1433 * directories */
1435 ms_dfs_link = check_msdfs_link(state->conn,
1436 smb_fname->base_name,
1437 &smb_fname->st);
1438 if (!ms_dfs_link) {
1439 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1440 "Couldn't stat [%s] (%s)\n",
1441 smb_fname_str_dbg(smb_fname),
1442 strerror(errno)));
1443 return false;
1447 if (ms_dfs_link) {
1448 mode = dos_mode_msdfs(state->conn, smb_fname);
1449 } else {
1450 mode = dos_mode(state->conn, smb_fname);
1453 *_mode = mode;
1454 return true;
1457 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1458 connection_struct *conn,
1459 uint16_t flags2,
1460 uint32_t info_level,
1461 struct ea_list *name_list,
1462 bool check_mangled_names,
1463 bool requires_resume_key,
1464 uint32_t mode,
1465 const char *fname,
1466 const struct smb_filename *smb_fname,
1467 uint64_t space_remaining,
1468 uint8_t align,
1469 bool do_pad,
1470 char *base_data,
1471 char **ppdata,
1472 char *end_data,
1473 bool *out_of_space,
1474 uint64_t *last_entry_off)
1476 char *p, *q, *pdata = *ppdata;
1477 uint32_t reskey=0;
1478 uint64_t file_size = 0;
1479 uint64_t allocation_size = 0;
1480 uint32_t len;
1481 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1482 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1483 time_t c_date = (time_t)0;
1484 char *nameptr;
1485 char *last_entry_ptr;
1486 bool was_8_3;
1487 off_t off;
1488 off_t pad = 0;
1490 *out_of_space = false;
1492 ZERO_STRUCT(mdate_ts);
1493 ZERO_STRUCT(adate_ts);
1494 ZERO_STRUCT(create_date_ts);
1495 ZERO_STRUCT(cdate_ts);
1497 if (!(mode & aDIR)) {
1498 file_size = get_file_size_stat(&smb_fname->st);
1500 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1502 mdate_ts = smb_fname->st.st_ex_mtime;
1503 adate_ts = smb_fname->st.st_ex_atime;
1504 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1505 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1507 if (lp_dos_filetime_resolution(SNUM(conn))) {
1508 dos_filetime_timespec(&create_date_ts);
1509 dos_filetime_timespec(&mdate_ts);
1510 dos_filetime_timespec(&adate_ts);
1511 dos_filetime_timespec(&cdate_ts);
1514 create_date = convert_timespec_to_time_t(create_date_ts);
1515 mdate = convert_timespec_to_time_t(mdate_ts);
1516 adate = convert_timespec_to_time_t(adate_ts);
1517 c_date = convert_timespec_to_time_t(cdate_ts);
1519 /* align the record */
1520 off = PTR_DIFF(pdata, base_data);
1521 pad = (off + (align-1)) & ~(align-1);
1522 pad -= off;
1523 off += pad;
1524 /* initialize padding to 0 */
1525 if (pad) {
1526 memset(pdata, 0, pad);
1528 space_remaining -= pad;
1530 pdata += pad;
1531 p = pdata;
1532 last_entry_ptr = p;
1534 pad = 0;
1535 off = 0;
1537 switch (info_level) {
1538 case SMB_FIND_INFO_STANDARD:
1539 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1540 if(requires_resume_key) {
1541 SIVAL(p,0,reskey);
1542 p += 4;
1544 srv_put_dos_date2(p,0,create_date);
1545 srv_put_dos_date2(p,4,adate);
1546 srv_put_dos_date2(p,8,mdate);
1547 SIVAL(p,12,(uint32)file_size);
1548 SIVAL(p,16,(uint32)allocation_size);
1549 SSVAL(p,20,mode);
1550 p += 23;
1551 nameptr = p;
1552 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1553 p += ucs2_align(base_data, p, 0);
1555 len = srvstr_push(base_data, flags2, p,
1556 fname, PTR_DIFF(end_data, p),
1557 STR_TERMINATE);
1558 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1559 if (len > 2) {
1560 SCVAL(nameptr, -1, len - 2);
1561 } else {
1562 SCVAL(nameptr, -1, 0);
1564 } else {
1565 if (len > 1) {
1566 SCVAL(nameptr, -1, len - 1);
1567 } else {
1568 SCVAL(nameptr, -1, 0);
1571 p += len;
1572 break;
1574 case SMB_FIND_EA_SIZE:
1575 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1576 if (requires_resume_key) {
1577 SIVAL(p,0,reskey);
1578 p += 4;
1580 srv_put_dos_date2(p,0,create_date);
1581 srv_put_dos_date2(p,4,adate);
1582 srv_put_dos_date2(p,8,mdate);
1583 SIVAL(p,12,(uint32)file_size);
1584 SIVAL(p,16,(uint32)allocation_size);
1585 SSVAL(p,20,mode);
1587 unsigned int ea_size = estimate_ea_size(conn, NULL,
1588 smb_fname->base_name);
1589 SIVAL(p,22,ea_size); /* Extended attributes */
1591 p += 27;
1592 nameptr = p - 1;
1593 len = srvstr_push(base_data, flags2,
1594 p, fname, PTR_DIFF(end_data, p),
1595 STR_TERMINATE | STR_NOALIGN);
1596 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1597 if (len > 2) {
1598 len -= 2;
1599 } else {
1600 len = 0;
1602 } else {
1603 if (len > 1) {
1604 len -= 1;
1605 } else {
1606 len = 0;
1609 SCVAL(nameptr,0,len);
1610 p += len;
1611 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1612 break;
1614 case SMB_FIND_EA_LIST:
1616 struct ea_list *file_list = NULL;
1617 size_t ea_len = 0;
1619 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1620 if (!name_list) {
1621 return false;
1623 if (requires_resume_key) {
1624 SIVAL(p,0,reskey);
1625 p += 4;
1627 srv_put_dos_date2(p,0,create_date);
1628 srv_put_dos_date2(p,4,adate);
1629 srv_put_dos_date2(p,8,mdate);
1630 SIVAL(p,12,(uint32)file_size);
1631 SIVAL(p,16,(uint32)allocation_size);
1632 SSVAL(p,20,mode);
1633 p += 22; /* p now points to the EA area. */
1635 file_list = get_ea_list_from_file(ctx, conn, NULL,
1636 smb_fname->base_name,
1637 &ea_len);
1638 name_list = ea_list_union(name_list, file_list, &ea_len);
1640 /* We need to determine if this entry will fit in the space available. */
1641 /* Max string size is 255 bytes. */
1642 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1643 *out_of_space = true;
1644 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1645 return False; /* Not finished - just out of space */
1648 /* Push the ea_data followed by the name. */
1649 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1650 nameptr = p;
1651 len = srvstr_push(base_data, flags2,
1652 p + 1, fname, PTR_DIFF(end_data, p+1),
1653 STR_TERMINATE | STR_NOALIGN);
1654 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1655 if (len > 2) {
1656 len -= 2;
1657 } else {
1658 len = 0;
1660 } else {
1661 if (len > 1) {
1662 len -= 1;
1663 } else {
1664 len = 0;
1667 SCVAL(nameptr,0,len);
1668 p += len + 1;
1669 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1670 break;
1673 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1674 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1675 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1676 p += 4;
1677 SIVAL(p,0,reskey); p += 4;
1678 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1679 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1680 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1681 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1682 SOFF_T(p,0,file_size); p += 8;
1683 SOFF_T(p,0,allocation_size); p += 8;
1684 SIVAL(p,0,mode); p += 4;
1685 q = p; p += 4; /* q is placeholder for name length. */
1687 unsigned int ea_size = estimate_ea_size(conn, NULL,
1688 smb_fname->base_name);
1689 SIVAL(p,0,ea_size); /* Extended attributes */
1690 p += 4;
1692 /* Clear the short name buffer. This is
1693 * IMPORTANT as not doing so will trigger
1694 * a Win2k client bug. JRA.
1696 if (!was_8_3 && check_mangled_names) {
1697 char mangled_name[13]; /* mangled 8.3 name. */
1698 if (!name_to_8_3(fname,mangled_name,True,
1699 conn->params)) {
1700 /* Error - mangle failed ! */
1701 memset(mangled_name,'\0',12);
1703 mangled_name[12] = 0;
1704 len = srvstr_push(base_data, flags2,
1705 p+2, mangled_name, 24,
1706 STR_UPPER|STR_UNICODE);
1707 if (len < 24) {
1708 memset(p + 2 + len,'\0',24 - len);
1710 SSVAL(p, 0, len);
1711 } else {
1712 memset(p,'\0',26);
1714 p += 2 + 24;
1715 len = srvstr_push(base_data, flags2, p,
1716 fname, PTR_DIFF(end_data, p),
1717 STR_TERMINATE_ASCII);
1718 SIVAL(q,0,len);
1719 p += len;
1721 len = PTR_DIFF(p, pdata);
1722 pad = (len + (align-1)) & ~(align-1);
1724 * offset to the next entry, the caller
1725 * will overwrite it for the last entry
1726 * that's why we always include the padding
1728 SIVAL(pdata,0,pad);
1730 * set padding to zero
1732 if (do_pad) {
1733 memset(p, 0, pad - len);
1734 p = pdata + pad;
1735 } else {
1736 p = pdata + len;
1738 break;
1740 case SMB_FIND_FILE_DIRECTORY_INFO:
1741 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1742 p += 4;
1743 SIVAL(p,0,reskey); p += 4;
1744 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1745 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1746 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1747 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1748 SOFF_T(p,0,file_size); p += 8;
1749 SOFF_T(p,0,allocation_size); p += 8;
1750 SIVAL(p,0,mode); p += 4;
1751 len = srvstr_push(base_data, flags2,
1752 p + 4, fname, PTR_DIFF(end_data, p+4),
1753 STR_TERMINATE_ASCII);
1754 SIVAL(p,0,len);
1755 p += 4 + len;
1757 len = PTR_DIFF(p, pdata);
1758 pad = (len + (align-1)) & ~(align-1);
1760 * offset to the next entry, the caller
1761 * will overwrite it for the last entry
1762 * that's why we always include the padding
1764 SIVAL(pdata,0,pad);
1766 * set padding to zero
1768 if (do_pad) {
1769 memset(p, 0, pad - len);
1770 p = pdata + pad;
1771 } else {
1772 p = pdata + len;
1774 break;
1776 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1777 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1778 p += 4;
1779 SIVAL(p,0,reskey); p += 4;
1780 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1781 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1782 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1783 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1784 SOFF_T(p,0,file_size); p += 8;
1785 SOFF_T(p,0,allocation_size); p += 8;
1786 SIVAL(p,0,mode); p += 4;
1787 q = p; p += 4; /* q is placeholder for name length. */
1789 unsigned int ea_size = estimate_ea_size(conn, NULL,
1790 smb_fname->base_name);
1791 SIVAL(p,0,ea_size); /* Extended attributes */
1792 p +=4;
1794 len = srvstr_push(base_data, flags2, p,
1795 fname, PTR_DIFF(end_data, p),
1796 STR_TERMINATE_ASCII);
1797 SIVAL(q, 0, len);
1798 p += len;
1800 len = PTR_DIFF(p, pdata);
1801 pad = (len + (align-1)) & ~(align-1);
1803 * offset to the next entry, the caller
1804 * will overwrite it for the last entry
1805 * that's why we always include the padding
1807 SIVAL(pdata,0,pad);
1809 * set padding to zero
1811 if (do_pad) {
1812 memset(p, 0, pad - len);
1813 p = pdata + pad;
1814 } else {
1815 p = pdata + len;
1817 break;
1819 case SMB_FIND_FILE_NAMES_INFO:
1820 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1821 p += 4;
1822 SIVAL(p,0,reskey); p += 4;
1823 p += 4;
1824 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1825 acl on a dir (tridge) */
1826 len = srvstr_push(base_data, flags2, p,
1827 fname, PTR_DIFF(end_data, p),
1828 STR_TERMINATE_ASCII);
1829 SIVAL(p, -4, len);
1830 p += len;
1832 len = PTR_DIFF(p, pdata);
1833 pad = (len + (align-1)) & ~(align-1);
1835 * offset to the next entry, the caller
1836 * will overwrite it for the last entry
1837 * that's why we always include the padding
1839 SIVAL(pdata,0,pad);
1841 * set padding to zero
1843 if (do_pad) {
1844 memset(p, 0, pad - len);
1845 p = pdata + pad;
1846 } else {
1847 p = pdata + len;
1849 break;
1851 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1852 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1853 p += 4;
1854 SIVAL(p,0,reskey); p += 4;
1855 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1856 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1857 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1858 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1859 SOFF_T(p,0,file_size); p += 8;
1860 SOFF_T(p,0,allocation_size); p += 8;
1861 SIVAL(p,0,mode); p += 4;
1862 q = p; p += 4; /* q is placeholder for name length. */
1864 unsigned int ea_size = estimate_ea_size(conn, NULL,
1865 smb_fname->base_name);
1866 SIVAL(p,0,ea_size); /* Extended attributes */
1867 p +=4;
1869 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1870 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1871 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1872 len = srvstr_push(base_data, flags2, p,
1873 fname, PTR_DIFF(end_data, p),
1874 STR_TERMINATE_ASCII);
1875 SIVAL(q, 0, len);
1876 p += len;
1878 len = PTR_DIFF(p, pdata);
1879 pad = (len + (align-1)) & ~(align-1);
1881 * offset to the next entry, the caller
1882 * will overwrite it for the last entry
1883 * that's why we always include the padding
1885 SIVAL(pdata,0,pad);
1887 * set padding to zero
1889 if (do_pad) {
1890 memset(p, 0, pad - len);
1891 p = pdata + pad;
1892 } else {
1893 p = pdata + len;
1895 break;
1897 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1898 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1899 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1900 p += 4;
1901 SIVAL(p,0,reskey); p += 4;
1902 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1903 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1904 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1905 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1906 SOFF_T(p,0,file_size); p += 8;
1907 SOFF_T(p,0,allocation_size); p += 8;
1908 SIVAL(p,0,mode); p += 4;
1909 q = p; p += 4; /* q is placeholder for name length */
1911 unsigned int ea_size = estimate_ea_size(conn, NULL,
1912 smb_fname->base_name);
1913 SIVAL(p,0,ea_size); /* Extended attributes */
1914 p +=4;
1916 /* Clear the short name buffer. This is
1917 * IMPORTANT as not doing so will trigger
1918 * a Win2k client bug. JRA.
1920 if (!was_8_3 && check_mangled_names) {
1921 char mangled_name[13]; /* mangled 8.3 name. */
1922 if (!name_to_8_3(fname,mangled_name,True,
1923 conn->params)) {
1924 /* Error - mangle failed ! */
1925 memset(mangled_name,'\0',12);
1927 mangled_name[12] = 0;
1928 len = srvstr_push(base_data, flags2,
1929 p+2, mangled_name, 24,
1930 STR_UPPER|STR_UNICODE);
1931 SSVAL(p, 0, len);
1932 if (len < 24) {
1933 memset(p + 2 + len,'\0',24 - len);
1935 SSVAL(p, 0, len);
1936 } else {
1937 memset(p,'\0',26);
1939 p += 26;
1940 SSVAL(p,0,0); p += 2; /* Reserved ? */
1941 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1942 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1943 len = srvstr_push(base_data, flags2, p,
1944 fname, PTR_DIFF(end_data, p),
1945 STR_TERMINATE_ASCII);
1946 SIVAL(q,0,len);
1947 p += len;
1949 len = PTR_DIFF(p, pdata);
1950 pad = (len + (align-1)) & ~(align-1);
1952 * offset to the next entry, the caller
1953 * will overwrite it for the last entry
1954 * that's why we always include the padding
1956 SIVAL(pdata,0,pad);
1958 * set padding to zero
1960 if (do_pad) {
1961 memset(p, 0, pad - len);
1962 p = pdata + pad;
1963 } else {
1964 p = pdata + len;
1966 break;
1968 /* CIFS UNIX Extension. */
1970 case SMB_FIND_FILE_UNIX:
1971 case SMB_FIND_FILE_UNIX_INFO2:
1972 p+= 4;
1973 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1975 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1977 if (info_level == SMB_FIND_FILE_UNIX) {
1978 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1979 p = store_file_unix_basic(conn, p,
1980 NULL, &smb_fname->st);
1981 len = srvstr_push(base_data, flags2, p,
1982 fname, PTR_DIFF(end_data, p),
1983 STR_TERMINATE);
1984 } else {
1985 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1986 p = store_file_unix_basic_info2(conn, p,
1987 NULL, &smb_fname->st);
1988 nameptr = p;
1989 p += 4;
1990 len = srvstr_push(base_data, flags2, p, fname,
1991 PTR_DIFF(end_data, p), 0);
1992 SIVAL(nameptr, 0, len);
1995 p += len;
1997 len = PTR_DIFF(p, pdata);
1998 pad = (len + (align-1)) & ~(align-1);
2000 * offset to the next entry, the caller
2001 * will overwrite it for the last entry
2002 * that's why we always include the padding
2004 SIVAL(pdata,0,pad);
2006 * set padding to zero
2008 if (do_pad) {
2009 memset(p, 0, pad - len);
2010 p = pdata + pad;
2011 } else {
2012 p = pdata + len;
2014 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2016 break;
2018 default:
2019 return false;
2022 if (PTR_DIFF(p,pdata) > space_remaining) {
2023 *out_of_space = true;
2024 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2025 return false; /* Not finished - just out of space */
2028 /* Setup the last entry pointer, as an offset from base_data */
2029 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2030 /* Advance the data pointer to the next slot */
2031 *ppdata = p;
2033 return true;
2036 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2037 connection_struct *conn,
2038 struct dptr_struct *dirptr,
2039 uint16 flags2,
2040 const char *path_mask,
2041 uint32 dirtype,
2042 int info_level,
2043 int requires_resume_key,
2044 bool dont_descend,
2045 bool ask_sharemode,
2046 uint8_t align,
2047 bool do_pad,
2048 char **ppdata,
2049 char *base_data,
2050 char *end_data,
2051 int space_remaining,
2052 bool *out_of_space,
2053 bool *got_exact_match,
2054 int *_last_entry_off,
2055 struct ea_list *name_list)
2057 const char *p;
2058 const char *mask = NULL;
2059 long prev_dirpos = 0;
2060 uint32_t mode = 0;
2061 char *fname = NULL;
2062 struct smb_filename *smb_fname = NULL;
2063 struct smbd_dirptr_lanman2_state state;
2064 bool ok;
2065 uint64_t last_entry_off = 0;
2067 ZERO_STRUCT(state);
2068 state.conn = conn;
2069 state.info_level = info_level;
2070 state.check_mangled_names = lp_manglednames(conn->params);
2071 state.has_wild = dptr_has_wild(dirptr);
2072 state.got_exact_match = false;
2074 *out_of_space = false;
2075 *got_exact_match = false;
2077 p = strrchr_m(path_mask,'/');
2078 if(p != NULL) {
2079 if(p[1] == '\0') {
2080 mask = "*.*";
2081 } else {
2082 mask = p+1;
2084 } else {
2085 mask = path_mask;
2088 ok = smbd_dirptr_get_entry(ctx,
2089 dirptr,
2090 mask,
2091 dirtype,
2092 dont_descend,
2093 ask_sharemode,
2094 smbd_dirptr_lanman2_match_fn,
2095 smbd_dirptr_lanman2_mode_fn,
2096 &state,
2097 &fname,
2098 &smb_fname,
2099 &mode,
2100 &prev_dirpos);
2101 if (!ok) {
2102 return false;
2105 *got_exact_match = state.got_exact_match;
2107 ok = smbd_marshall_dir_entry(ctx,
2108 conn,
2109 flags2,
2110 info_level,
2111 name_list,
2112 state.check_mangled_names,
2113 requires_resume_key,
2114 mode,
2115 fname,
2116 smb_fname,
2117 space_remaining,
2118 align,
2119 do_pad,
2120 base_data,
2121 ppdata,
2122 end_data,
2123 out_of_space,
2124 &last_entry_off);
2125 TALLOC_FREE(fname);
2126 TALLOC_FREE(smb_fname);
2127 if (*out_of_space) {
2128 dptr_SeekDir(dirptr, prev_dirpos);
2129 return false;
2131 if (!ok) {
2132 return false;
2135 *_last_entry_off = last_entry_off;
2136 return true;
2139 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2140 connection_struct *conn,
2141 struct dptr_struct *dirptr,
2142 uint16 flags2,
2143 const char *path_mask,
2144 uint32 dirtype,
2145 int info_level,
2146 bool requires_resume_key,
2147 bool dont_descend,
2148 bool ask_sharemode,
2149 char **ppdata,
2150 char *base_data,
2151 char *end_data,
2152 int space_remaining,
2153 bool *out_of_space,
2154 bool *got_exact_match,
2155 int *last_entry_off,
2156 struct ea_list *name_list)
2158 uint8_t align = 4;
2159 const bool do_pad = true;
2161 if (info_level >= 1 && info_level <= 3) {
2162 /* No alignment on earlier info levels. */
2163 align = 1;
2166 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2167 path_mask, dirtype, info_level,
2168 requires_resume_key, dont_descend, ask_sharemode,
2169 align, do_pad,
2170 ppdata, base_data, end_data,
2171 space_remaining,
2172 out_of_space, got_exact_match,
2173 last_entry_off, name_list);
2176 /****************************************************************************
2177 Reply to a TRANS2_FINDFIRST.
2178 ****************************************************************************/
2180 static void call_trans2findfirst(connection_struct *conn,
2181 struct smb_request *req,
2182 char **pparams, int total_params,
2183 char **ppdata, int total_data,
2184 unsigned int max_data_bytes)
2186 /* We must be careful here that we don't return more than the
2187 allowed number of data bytes. If this means returning fewer than
2188 maxentries then so be it. We assume that the redirector has
2189 enough room for the fixed number of parameter bytes it has
2190 requested. */
2191 struct smb_filename *smb_dname = NULL;
2192 char *params = *pparams;
2193 char *pdata = *ppdata;
2194 char *data_end;
2195 uint32 dirtype;
2196 int maxentries;
2197 uint16 findfirst_flags;
2198 bool close_after_first;
2199 bool close_if_end;
2200 bool requires_resume_key;
2201 int info_level;
2202 char *directory = NULL;
2203 char *mask = NULL;
2204 char *p;
2205 int last_entry_off=0;
2206 int dptr_num = -1;
2207 int numentries = 0;
2208 int i;
2209 bool finished = False;
2210 bool dont_descend = False;
2211 bool out_of_space = False;
2212 int space_remaining;
2213 bool mask_contains_wcard = False;
2214 struct ea_list *ea_list = NULL;
2215 NTSTATUS ntstatus = NT_STATUS_OK;
2216 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2217 TALLOC_CTX *ctx = talloc_tos();
2218 struct dptr_struct *dirptr = NULL;
2219 struct smbd_server_connection *sconn = smbd_server_conn;
2221 if (total_params < 13) {
2222 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2223 goto out;
2226 dirtype = SVAL(params,0);
2227 maxentries = SVAL(params,2);
2228 findfirst_flags = SVAL(params,4);
2229 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2230 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2231 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2232 info_level = SVAL(params,6);
2234 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2235 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2236 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2237 info_level, max_data_bytes));
2239 if (!maxentries) {
2240 /* W2K3 seems to treat zero as 1. */
2241 maxentries = 1;
2244 switch (info_level) {
2245 case SMB_FIND_INFO_STANDARD:
2246 case SMB_FIND_EA_SIZE:
2247 case SMB_FIND_EA_LIST:
2248 case SMB_FIND_FILE_DIRECTORY_INFO:
2249 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2250 case SMB_FIND_FILE_NAMES_INFO:
2251 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2252 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2253 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2254 break;
2255 case SMB_FIND_FILE_UNIX:
2256 case SMB_FIND_FILE_UNIX_INFO2:
2257 /* Always use filesystem for UNIX mtime query. */
2258 ask_sharemode = false;
2259 if (!lp_unix_extensions()) {
2260 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2261 goto out;
2263 break;
2264 default:
2265 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2266 goto out;
2269 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2270 params+12, total_params - 12,
2271 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2272 if (!NT_STATUS_IS_OK(ntstatus)) {
2273 reply_nterror(req, ntstatus);
2274 goto out;
2277 ntstatus = filename_convert(ctx, conn,
2278 req->flags2 & FLAGS2_DFS_PATHNAMES,
2279 directory,
2280 (UCF_SAVE_LCOMP |
2281 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2282 &mask_contains_wcard,
2283 &smb_dname);
2284 if (!NT_STATUS_IS_OK(ntstatus)) {
2285 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2286 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2287 ERRSRV, ERRbadpath);
2288 goto out;
2290 reply_nterror(req, ntstatus);
2291 goto out;
2294 mask = smb_dname->original_lcomp;
2296 directory = smb_dname->base_name;
2298 p = strrchr_m(directory,'/');
2299 if(p == NULL) {
2300 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2301 if((directory[0] == '.') && (directory[1] == '\0')) {
2302 mask = talloc_strdup(ctx,"*");
2303 if (!mask) {
2304 reply_nterror(req, NT_STATUS_NO_MEMORY);
2305 goto out;
2307 mask_contains_wcard = True;
2309 directory = talloc_strdup(talloc_tos(), "./");
2310 if (!directory) {
2311 reply_nterror(req, NT_STATUS_NO_MEMORY);
2312 goto out;
2314 } else {
2315 *p = 0;
2318 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2320 if (info_level == SMB_FIND_EA_LIST) {
2321 uint32 ea_size;
2323 if (total_data < 4) {
2324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2325 goto out;
2328 ea_size = IVAL(pdata,0);
2329 if (ea_size != total_data) {
2330 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2331 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2333 goto out;
2336 if (!lp_ea_support(SNUM(conn))) {
2337 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2338 goto out;
2341 /* Pull out the list of names. */
2342 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2343 if (!ea_list) {
2344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2345 goto out;
2349 *ppdata = (char *)SMB_REALLOC(
2350 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2351 if(*ppdata == NULL ) {
2352 reply_nterror(req, NT_STATUS_NO_MEMORY);
2353 goto out;
2355 pdata = *ppdata;
2356 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2358 /* Realloc the params space */
2359 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2360 if (*pparams == NULL) {
2361 reply_nterror(req, NT_STATUS_NO_MEMORY);
2362 goto out;
2364 params = *pparams;
2366 /* Save the wildcard match and attribs we are using on this directory -
2367 needed as lanman2 assumes these are being saved between calls */
2369 ntstatus = dptr_create(conn,
2370 directory,
2371 False,
2372 True,
2373 req->smbpid,
2374 mask,
2375 mask_contains_wcard,
2376 dirtype,
2377 &dirptr);
2379 if (!NT_STATUS_IS_OK(ntstatus)) {
2380 reply_nterror(req, ntstatus);
2381 goto out;
2384 dptr_num = dptr_dnum(dirptr);
2385 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2387 /* Initialize per TRANS2_FIND_FIRST operation data */
2388 dptr_init_search_op(dirptr);
2390 /* We don't need to check for VOL here as this is returned by
2391 a different TRANS2 call. */
2393 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2394 directory,lp_dontdescend(SNUM(conn))));
2395 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2396 dont_descend = True;
2398 p = pdata;
2399 space_remaining = max_data_bytes;
2400 out_of_space = False;
2402 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2403 bool got_exact_match = False;
2405 /* this is a heuristic to avoid seeking the dirptr except when
2406 absolutely necessary. It allows for a filename of about 40 chars */
2407 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2408 out_of_space = True;
2409 finished = False;
2410 } else {
2411 finished = !get_lanman2_dir_entry(ctx,
2412 conn,
2413 dirptr,
2414 req->flags2,
2415 mask,dirtype,info_level,
2416 requires_resume_key,dont_descend,
2417 ask_sharemode,
2418 &p,pdata,data_end,
2419 space_remaining, &out_of_space,
2420 &got_exact_match,
2421 &last_entry_off, ea_list);
2424 if (finished && out_of_space)
2425 finished = False;
2427 if (!finished && !out_of_space)
2428 numentries++;
2431 * As an optimisation if we know we aren't looking
2432 * for a wildcard name (ie. the name matches the wildcard exactly)
2433 * then we can finish on any (first) match.
2434 * This speeds up large directory searches. JRA.
2437 if(got_exact_match)
2438 finished = True;
2440 /* Ensure space_remaining never goes -ve. */
2441 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2442 space_remaining = 0;
2443 out_of_space = true;
2444 } else {
2445 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2449 /* Check if we can close the dirptr */
2450 if(close_after_first || (finished && close_if_end)) {
2451 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2452 dptr_close(sconn, &dptr_num);
2456 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2457 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2458 * the protocol level is less than NT1. Tested with smbclient. JRA.
2459 * This should fix the OS/2 client bug #2335.
2462 if(numentries == 0) {
2463 dptr_close(sconn, &dptr_num);
2464 if (get_Protocol() < PROTOCOL_NT1) {
2465 reply_force_doserror(req, ERRDOS, ERRnofiles);
2466 goto out;
2467 } else {
2468 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2469 ERRDOS, ERRbadfile);
2470 goto out;
2474 /* At this point pdata points to numentries directory entries. */
2476 /* Set up the return parameter block */
2477 SSVAL(params,0,dptr_num);
2478 SSVAL(params,2,numentries);
2479 SSVAL(params,4,finished);
2480 SSVAL(params,6,0); /* Never an EA error */
2481 SSVAL(params,8,last_entry_off);
2483 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2484 max_data_bytes);
2486 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2487 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2488 if (!directory) {
2489 reply_nterror(req, NT_STATUS_NO_MEMORY);
2493 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2494 smb_fn_name(req->cmd),
2495 mask, directory, dirtype, numentries ) );
2498 * Force a name mangle here to ensure that the
2499 * mask as an 8.3 name is top of the mangled cache.
2500 * The reasons for this are subtle. Don't remove
2501 * this code unless you know what you are doing
2502 * (see PR#13758). JRA.
2505 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2506 char mangled_name[13];
2507 name_to_8_3(mask, mangled_name, True, conn->params);
2509 out:
2510 TALLOC_FREE(smb_dname);
2511 return;
2514 /****************************************************************************
2515 Reply to a TRANS2_FINDNEXT.
2516 ****************************************************************************/
2518 static void call_trans2findnext(connection_struct *conn,
2519 struct smb_request *req,
2520 char **pparams, int total_params,
2521 char **ppdata, int total_data,
2522 unsigned int max_data_bytes)
2524 /* We must be careful here that we don't return more than the
2525 allowed number of data bytes. If this means returning fewer than
2526 maxentries then so be it. We assume that the redirector has
2527 enough room for the fixed number of parameter bytes it has
2528 requested. */
2529 char *params = *pparams;
2530 char *pdata = *ppdata;
2531 char *data_end;
2532 int dptr_num;
2533 int maxentries;
2534 uint16 info_level;
2535 uint32 resume_key;
2536 uint16 findnext_flags;
2537 bool close_after_request;
2538 bool close_if_end;
2539 bool requires_resume_key;
2540 bool continue_bit;
2541 bool mask_contains_wcard = False;
2542 char *resume_name = NULL;
2543 const char *mask = NULL;
2544 const char *directory = NULL;
2545 char *p = NULL;
2546 uint16 dirtype;
2547 int numentries = 0;
2548 int i, last_entry_off=0;
2549 bool finished = False;
2550 bool dont_descend = False;
2551 bool out_of_space = False;
2552 int space_remaining;
2553 struct ea_list *ea_list = NULL;
2554 NTSTATUS ntstatus = NT_STATUS_OK;
2555 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2556 TALLOC_CTX *ctx = talloc_tos();
2557 struct dptr_struct *dirptr;
2558 struct smbd_server_connection *sconn = smbd_server_conn;
2560 if (total_params < 13) {
2561 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2562 return;
2565 dptr_num = SVAL(params,0);
2566 maxentries = SVAL(params,2);
2567 info_level = SVAL(params,4);
2568 resume_key = IVAL(params,6);
2569 findnext_flags = SVAL(params,10);
2570 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2571 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2572 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2573 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2575 if (!continue_bit) {
2576 /* We only need resume_name if continue_bit is zero. */
2577 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2578 params+12,
2579 total_params - 12, STR_TERMINATE, &ntstatus,
2580 &mask_contains_wcard);
2581 if (!NT_STATUS_IS_OK(ntstatus)) {
2582 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2583 complain (it thinks we're asking for the directory above the shared
2584 path or an invalid name). Catch this as the resume name is only compared, never used in
2585 a file access. JRA. */
2586 srvstr_pull_talloc(ctx, params, req->flags2,
2587 &resume_name, params+12,
2588 total_params - 12,
2589 STR_TERMINATE);
2591 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2592 reply_nterror(req, ntstatus);
2593 return;
2598 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2599 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2600 resume_key = %d resume name = %s continue=%d level = %d\n",
2601 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2602 requires_resume_key, resume_key,
2603 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2605 if (!maxentries) {
2606 /* W2K3 seems to treat zero as 1. */
2607 maxentries = 1;
2610 switch (info_level) {
2611 case SMB_FIND_INFO_STANDARD:
2612 case SMB_FIND_EA_SIZE:
2613 case SMB_FIND_EA_LIST:
2614 case SMB_FIND_FILE_DIRECTORY_INFO:
2615 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2616 case SMB_FIND_FILE_NAMES_INFO:
2617 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2618 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2619 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2620 break;
2621 case SMB_FIND_FILE_UNIX:
2622 case SMB_FIND_FILE_UNIX_INFO2:
2623 /* Always use filesystem for UNIX mtime query. */
2624 ask_sharemode = false;
2625 if (!lp_unix_extensions()) {
2626 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2627 return;
2629 break;
2630 default:
2631 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2632 return;
2635 if (info_level == SMB_FIND_EA_LIST) {
2636 uint32 ea_size;
2638 if (total_data < 4) {
2639 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2640 return;
2643 ea_size = IVAL(pdata,0);
2644 if (ea_size != total_data) {
2645 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2646 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2647 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2648 return;
2651 if (!lp_ea_support(SNUM(conn))) {
2652 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2653 return;
2656 /* Pull out the list of names. */
2657 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2658 if (!ea_list) {
2659 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2660 return;
2664 *ppdata = (char *)SMB_REALLOC(
2665 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2666 if(*ppdata == NULL) {
2667 reply_nterror(req, NT_STATUS_NO_MEMORY);
2668 return;
2671 pdata = *ppdata;
2672 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2674 /* Realloc the params space */
2675 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2676 if(*pparams == NULL ) {
2677 reply_nterror(req, NT_STATUS_NO_MEMORY);
2678 return;
2681 params = *pparams;
2683 /* Check that the dptr is valid */
2684 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2685 reply_nterror(req, STATUS_NO_MORE_FILES);
2686 return;
2689 directory = dptr_path(sconn, dptr_num);
2691 /* Get the wildcard mask from the dptr */
2692 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2693 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2694 reply_nterror(req, STATUS_NO_MORE_FILES);
2695 return;
2698 mask = p;
2700 /* Get the attr mask from the dptr */
2701 dirtype = dptr_attr(sconn, dptr_num);
2703 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2704 dptr_num, mask, dirtype,
2705 (long)dirptr,
2706 dptr_TellDir(dirptr)));
2708 /* Initialize per TRANS2_FIND_NEXT operation data */
2709 dptr_init_search_op(dirptr);
2711 /* We don't need to check for VOL here as this is returned by
2712 a different TRANS2 call. */
2714 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2715 directory,lp_dontdescend(SNUM(conn))));
2716 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2717 dont_descend = True;
2719 p = pdata;
2720 space_remaining = max_data_bytes;
2721 out_of_space = False;
2724 * Seek to the correct position. We no longer use the resume key but
2725 * depend on the last file name instead.
2728 if(!continue_bit && resume_name && *resume_name) {
2729 SMB_STRUCT_STAT st;
2731 long current_pos = 0;
2733 * Remember, name_to_8_3 is called by
2734 * get_lanman2_dir_entry(), so the resume name
2735 * could be mangled. Ensure we check the unmangled name.
2738 if (mangle_is_mangled(resume_name, conn->params)) {
2739 char *new_resume_name = NULL;
2740 mangle_lookup_name_from_8_3(ctx,
2741 resume_name,
2742 &new_resume_name,
2743 conn->params);
2744 if (new_resume_name) {
2745 resume_name = new_resume_name;
2750 * Fix for NT redirector problem triggered by resume key indexes
2751 * changing between directory scans. We now return a resume key of 0
2752 * and instead look for the filename to continue from (also given
2753 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2754 * findfirst/findnext (as is usual) then the directory pointer
2755 * should already be at the correct place.
2758 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2759 } /* end if resume_name && !continue_bit */
2761 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2762 bool got_exact_match = False;
2764 /* this is a heuristic to avoid seeking the dirptr except when
2765 absolutely necessary. It allows for a filename of about 40 chars */
2766 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2767 out_of_space = True;
2768 finished = False;
2769 } else {
2770 finished = !get_lanman2_dir_entry(ctx,
2771 conn,
2772 dirptr,
2773 req->flags2,
2774 mask,dirtype,info_level,
2775 requires_resume_key,dont_descend,
2776 ask_sharemode,
2777 &p,pdata,data_end,
2778 space_remaining, &out_of_space,
2779 &got_exact_match,
2780 &last_entry_off, ea_list);
2783 if (finished && out_of_space)
2784 finished = False;
2786 if (!finished && !out_of_space)
2787 numentries++;
2790 * As an optimisation if we know we aren't looking
2791 * for a wildcard name (ie. the name matches the wildcard exactly)
2792 * then we can finish on any (first) match.
2793 * This speeds up large directory searches. JRA.
2796 if(got_exact_match)
2797 finished = True;
2799 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2802 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2803 smb_fn_name(req->cmd),
2804 mask, directory, dirtype, numentries ) );
2806 /* Check if we can close the dirptr */
2807 if(close_after_request || (finished && close_if_end)) {
2808 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2809 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2812 /* Set up the return parameter block */
2813 SSVAL(params,0,numentries);
2814 SSVAL(params,2,finished);
2815 SSVAL(params,4,0); /* Never an EA error */
2816 SSVAL(params,6,last_entry_off);
2818 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2819 max_data_bytes);
2821 return;
2824 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2826 E_md4hash(lp_servicename(SNUM(conn)),objid);
2827 return objid;
2830 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2832 SMB_ASSERT(extended_info != NULL);
2834 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2835 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2836 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2837 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2838 #ifdef SAMBA_VERSION_REVISION
2839 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2840 #endif
2841 extended_info->samba_subversion = 0;
2842 #ifdef SAMBA_VERSION_RC_RELEASE
2843 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2844 #else
2845 #ifdef SAMBA_VERSION_PRE_RELEASE
2846 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2847 #endif
2848 #endif
2849 #ifdef SAMBA_VERSION_VENDOR_PATCH
2850 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2851 #endif
2852 extended_info->samba_gitcommitdate = 0;
2853 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2854 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2855 #endif
2857 memset(extended_info->samba_version_string, 0,
2858 sizeof(extended_info->samba_version_string));
2860 snprintf (extended_info->samba_version_string,
2861 sizeof(extended_info->samba_version_string),
2862 "%s", samba_version_string());
2865 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2866 TALLOC_CTX *mem_ctx,
2867 uint16_t info_level,
2868 uint16_t flags2,
2869 unsigned int max_data_bytes,
2870 char **ppdata,
2871 int *ret_data_len)
2873 char *pdata, *end_data;
2874 int data_len = 0, len;
2875 const char *vname = volume_label(SNUM(conn));
2876 int snum = SNUM(conn);
2877 char *fstype = lp_fstype(SNUM(conn));
2878 uint32 additional_flags = 0;
2879 struct smb_filename smb_fname_dot;
2880 SMB_STRUCT_STAT st;
2882 if (IS_IPC(conn)) {
2883 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2884 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2885 "info level (0x%x) on IPC$.\n",
2886 (unsigned int)info_level));
2887 return NT_STATUS_ACCESS_DENIED;
2891 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2893 ZERO_STRUCT(smb_fname_dot);
2894 smb_fname_dot.base_name = discard_const_p(char, ".");
2896 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2897 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2898 return map_nt_error_from_unix(errno);
2901 st = smb_fname_dot.st;
2903 *ppdata = (char *)SMB_REALLOC(
2904 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2905 if (*ppdata == NULL) {
2906 return NT_STATUS_NO_MEMORY;
2909 pdata = *ppdata;
2910 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2911 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2913 switch (info_level) {
2914 case SMB_INFO_ALLOCATION:
2916 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2917 data_len = 18;
2918 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2919 return map_nt_error_from_unix(errno);
2922 block_size = lp_block_size(snum);
2923 if (bsize < block_size) {
2924 uint64_t factor = block_size/bsize;
2925 bsize = block_size;
2926 dsize /= factor;
2927 dfree /= factor;
2929 if (bsize > block_size) {
2930 uint64_t factor = bsize/block_size;
2931 bsize = block_size;
2932 dsize *= factor;
2933 dfree *= factor;
2935 bytes_per_sector = 512;
2936 sectors_per_unit = bsize/bytes_per_sector;
2938 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2939 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2940 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2942 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2943 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2944 SIVAL(pdata,l1_cUnit,dsize);
2945 SIVAL(pdata,l1_cUnitAvail,dfree);
2946 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2947 break;
2950 case SMB_INFO_VOLUME:
2951 /* Return volume name */
2953 * Add volume serial number - hash of a combination of
2954 * the called hostname and the service name.
2956 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2958 * Win2k3 and previous mess this up by sending a name length
2959 * one byte short. I believe only older clients (OS/2 Win9x) use
2960 * this call so try fixing this by adding a terminating null to
2961 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2963 len = srvstr_push(
2964 pdata, flags2,
2965 pdata+l2_vol_szVolLabel, vname,
2966 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2967 STR_NOALIGN|STR_TERMINATE);
2968 SCVAL(pdata,l2_vol_cch,len);
2969 data_len = l2_vol_szVolLabel + len;
2970 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2971 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2972 len, vname));
2973 break;
2975 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2976 case SMB_FS_ATTRIBUTE_INFORMATION:
2978 additional_flags = 0;
2979 #if defined(HAVE_SYS_QUOTAS)
2980 additional_flags |= FILE_VOLUME_QUOTAS;
2981 #endif
2983 if(lp_nt_acl_support(SNUM(conn))) {
2984 additional_flags |= FILE_PERSISTENT_ACLS;
2987 /* Capabilities are filled in at connection time through STATVFS call */
2988 additional_flags |= conn->fs_capabilities;
2989 additional_flags |= lp_parm_int(conn->params->service,
2990 "share", "fake_fscaps",
2993 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2994 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2995 additional_flags); /* FS ATTRIBUTES */
2997 SIVAL(pdata,4,255); /* Max filename component length */
2998 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2999 and will think we can't do long filenames */
3000 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3001 PTR_DIFF(end_data, pdata+12),
3002 STR_UNICODE);
3003 SIVAL(pdata,8,len);
3004 data_len = 12 + len;
3005 break;
3007 case SMB_QUERY_FS_LABEL_INFO:
3008 case SMB_FS_LABEL_INFORMATION:
3009 len = srvstr_push(pdata, flags2, pdata+4, vname,
3010 PTR_DIFF(end_data, pdata+4), 0);
3011 data_len = 4 + len;
3012 SIVAL(pdata,0,len);
3013 break;
3015 case SMB_QUERY_FS_VOLUME_INFO:
3016 case SMB_FS_VOLUME_INFORMATION:
3019 * Add volume serial number - hash of a combination of
3020 * the called hostname and the service name.
3022 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3023 (str_checksum(get_local_machine_name())<<16));
3025 /* Max label len is 32 characters. */
3026 len = srvstr_push(pdata, flags2, pdata+18, vname,
3027 PTR_DIFF(end_data, pdata+18),
3028 STR_UNICODE);
3029 SIVAL(pdata,12,len);
3030 data_len = 18+len;
3032 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3033 (int)strlen(vname),vname, lp_servicename(snum)));
3034 break;
3036 case SMB_QUERY_FS_SIZE_INFO:
3037 case SMB_FS_SIZE_INFORMATION:
3039 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3040 data_len = 24;
3041 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3042 return map_nt_error_from_unix(errno);
3044 block_size = lp_block_size(snum);
3045 if (bsize < block_size) {
3046 uint64_t factor = block_size/bsize;
3047 bsize = block_size;
3048 dsize /= factor;
3049 dfree /= factor;
3051 if (bsize > block_size) {
3052 uint64_t factor = bsize/block_size;
3053 bsize = block_size;
3054 dsize *= factor;
3055 dfree *= factor;
3057 bytes_per_sector = 512;
3058 sectors_per_unit = bsize/bytes_per_sector;
3059 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3060 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3061 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3062 SBIG_UINT(pdata,0,dsize);
3063 SBIG_UINT(pdata,8,dfree);
3064 SIVAL(pdata,16,sectors_per_unit);
3065 SIVAL(pdata,20,bytes_per_sector);
3066 break;
3069 case SMB_FS_FULL_SIZE_INFORMATION:
3071 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3072 data_len = 32;
3073 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3074 return map_nt_error_from_unix(errno);
3076 block_size = lp_block_size(snum);
3077 if (bsize < block_size) {
3078 uint64_t factor = block_size/bsize;
3079 bsize = block_size;
3080 dsize /= factor;
3081 dfree /= factor;
3083 if (bsize > block_size) {
3084 uint64_t factor = bsize/block_size;
3085 bsize = block_size;
3086 dsize *= factor;
3087 dfree *= factor;
3089 bytes_per_sector = 512;
3090 sectors_per_unit = bsize/bytes_per_sector;
3091 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3092 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3093 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3094 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3095 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3096 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3097 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3098 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3099 break;
3102 case SMB_QUERY_FS_DEVICE_INFO:
3103 case SMB_FS_DEVICE_INFORMATION:
3104 data_len = 8;
3105 SIVAL(pdata,0,0); /* dev type */
3106 SIVAL(pdata,4,0); /* characteristics */
3107 break;
3109 #ifdef HAVE_SYS_QUOTAS
3110 case SMB_FS_QUOTA_INFORMATION:
3112 * what we have to send --metze:
3114 * Unknown1: 24 NULL bytes
3115 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3116 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3117 * Quota Flags: 2 byte :
3118 * Unknown3: 6 NULL bytes
3120 * 48 bytes total
3122 * details for Quota Flags:
3124 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3125 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3126 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3127 * 0x0001 Enable Quotas: enable quota for this fs
3131 /* we need to fake up a fsp here,
3132 * because its not send in this call
3134 files_struct fsp;
3135 SMB_NTQUOTA_STRUCT quotas;
3137 ZERO_STRUCT(fsp);
3138 ZERO_STRUCT(quotas);
3140 fsp.conn = conn;
3141 fsp.fnum = -1;
3143 /* access check */
3144 if (conn->server_info->utok.uid != sec_initial_uid()) {
3145 DEBUG(0,("set_user_quota: access_denied "
3146 "service [%s] user [%s]\n",
3147 lp_servicename(SNUM(conn)),
3148 conn->server_info->unix_name));
3149 return NT_STATUS_ACCESS_DENIED;
3152 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3153 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3154 return map_nt_error_from_unix(errno);
3157 data_len = 48;
3159 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3160 lp_servicename(SNUM(conn))));
3162 /* Unknown1 24 NULL bytes*/
3163 SBIG_UINT(pdata,0,(uint64_t)0);
3164 SBIG_UINT(pdata,8,(uint64_t)0);
3165 SBIG_UINT(pdata,16,(uint64_t)0);
3167 /* Default Soft Quota 8 bytes */
3168 SBIG_UINT(pdata,24,quotas.softlim);
3170 /* Default Hard Quota 8 bytes */
3171 SBIG_UINT(pdata,32,quotas.hardlim);
3173 /* Quota flag 2 bytes */
3174 SSVAL(pdata,40,quotas.qflags);
3176 /* Unknown3 6 NULL bytes */
3177 SSVAL(pdata,42,0);
3178 SIVAL(pdata,44,0);
3180 break;
3182 #endif /* HAVE_SYS_QUOTAS */
3183 case SMB_FS_OBJECTID_INFORMATION:
3185 unsigned char objid[16];
3186 struct smb_extended_info extended_info;
3187 memcpy(pdata,create_volume_objectid(conn, objid),16);
3188 samba_extended_info_version (&extended_info);
3189 SIVAL(pdata,16,extended_info.samba_magic);
3190 SIVAL(pdata,20,extended_info.samba_version);
3191 SIVAL(pdata,24,extended_info.samba_subversion);
3192 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3193 memcpy(pdata+36,extended_info.samba_version_string,28);
3194 data_len = 64;
3195 break;
3199 * Query the version and capabilities of the CIFS UNIX extensions
3200 * in use.
3203 case SMB_QUERY_CIFS_UNIX_INFO:
3205 bool large_write = lp_min_receive_file_size() &&
3206 !srv_is_signing_active(smbd_server_conn);
3207 bool large_read = !srv_is_signing_active(smbd_server_conn);
3208 int encrypt_caps = 0;
3210 if (!lp_unix_extensions()) {
3211 return NT_STATUS_INVALID_LEVEL;
3214 switch (conn->encrypt_level) {
3215 case 0:
3216 encrypt_caps = 0;
3217 break;
3218 case 1:
3219 case Auto:
3220 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3221 break;
3222 case Required:
3223 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3224 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3225 large_write = false;
3226 large_read = false;
3227 break;
3230 data_len = 12;
3231 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3232 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3234 /* We have POSIX ACLs, pathname, encryption,
3235 * large read/write, and locking capability. */
3237 SBIG_UINT(pdata,4,((uint64_t)(
3238 CIFS_UNIX_POSIX_ACLS_CAP|
3239 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3240 CIFS_UNIX_FCNTL_LOCKS_CAP|
3241 CIFS_UNIX_EXTATTR_CAP|
3242 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3243 encrypt_caps|
3244 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3245 (large_write ?
3246 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3247 break;
3250 case SMB_QUERY_POSIX_FS_INFO:
3252 int rc;
3253 vfs_statvfs_struct svfs;
3255 if (!lp_unix_extensions()) {
3256 return NT_STATUS_INVALID_LEVEL;
3259 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3261 if (!rc) {
3262 data_len = 56;
3263 SIVAL(pdata,0,svfs.OptimalTransferSize);
3264 SIVAL(pdata,4,svfs.BlockSize);
3265 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3266 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3267 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3268 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3269 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3270 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3271 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3272 #ifdef EOPNOTSUPP
3273 } else if (rc == EOPNOTSUPP) {
3274 return NT_STATUS_INVALID_LEVEL;
3275 #endif /* EOPNOTSUPP */
3276 } else {
3277 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3278 return NT_STATUS_DOS(ERRSRV, ERRerror);
3280 break;
3283 case SMB_QUERY_POSIX_WHOAMI:
3285 uint32_t flags = 0;
3286 uint32_t sid_bytes;
3287 int i;
3289 if (!lp_unix_extensions()) {
3290 return NT_STATUS_INVALID_LEVEL;
3293 if (max_data_bytes < 40) {
3294 return NT_STATUS_BUFFER_TOO_SMALL;
3297 /* We ARE guest if global_sid_Builtin_Guests is
3298 * in our list of SIDs.
3300 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3301 conn->server_info->ptok)) {
3302 flags |= SMB_WHOAMI_GUEST;
3305 /* We are NOT guest if global_sid_Authenticated_Users
3306 * is in our list of SIDs.
3308 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3309 conn->server_info->ptok)) {
3310 flags &= ~SMB_WHOAMI_GUEST;
3313 /* NOTE: 8 bytes for UID/GID, irrespective of native
3314 * platform size. This matches
3315 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3317 data_len = 4 /* flags */
3318 + 4 /* flag mask */
3319 + 8 /* uid */
3320 + 8 /* gid */
3321 + 4 /* ngroups */
3322 + 4 /* num_sids */
3323 + 4 /* SID bytes */
3324 + 4 /* pad/reserved */
3325 + (conn->server_info->utok.ngroups * 8)
3326 /* groups list */
3327 + (conn->server_info->ptok->num_sids *
3328 SID_MAX_SIZE)
3329 /* SID list */;
3331 SIVAL(pdata, 0, flags);
3332 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3333 SBIG_UINT(pdata, 8,
3334 (uint64_t)conn->server_info->utok.uid);
3335 SBIG_UINT(pdata, 16,
3336 (uint64_t)conn->server_info->utok.gid);
3339 if (data_len >= max_data_bytes) {
3340 /* Potential overflow, skip the GIDs and SIDs. */
3342 SIVAL(pdata, 24, 0); /* num_groups */
3343 SIVAL(pdata, 28, 0); /* num_sids */
3344 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3345 SIVAL(pdata, 36, 0); /* reserved */
3347 data_len = 40;
3348 break;
3351 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3352 SIVAL(pdata, 28, conn->server_info->num_sids);
3354 /* We walk the SID list twice, but this call is fairly
3355 * infrequent, and I don't expect that it's performance
3356 * sensitive -- jpeach
3358 for (i = 0, sid_bytes = 0;
3359 i < conn->server_info->ptok->num_sids; ++i) {
3360 sid_bytes += ndr_size_dom_sid(
3361 &conn->server_info->ptok->user_sids[i],
3362 NULL,
3366 /* SID list byte count */
3367 SIVAL(pdata, 32, sid_bytes);
3369 /* 4 bytes pad/reserved - must be zero */
3370 SIVAL(pdata, 36, 0);
3371 data_len = 40;
3373 /* GID list */
3374 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3375 SBIG_UINT(pdata, data_len,
3376 (uint64_t)conn->server_info->utok.groups[i]);
3377 data_len += 8;
3380 /* SID list */
3381 for (i = 0;
3382 i < conn->server_info->ptok->num_sids; ++i) {
3383 int sid_len = ndr_size_dom_sid(
3384 &conn->server_info->ptok->user_sids[i],
3385 NULL,
3388 sid_linearize(pdata + data_len, sid_len,
3389 &conn->server_info->ptok->user_sids[i]);
3390 data_len += sid_len;
3393 break;
3396 case SMB_MAC_QUERY_FS_INFO:
3398 * Thursby MAC extension... ONLY on NTFS filesystems
3399 * once we do streams then we don't need this
3401 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3402 data_len = 88;
3403 SIVAL(pdata,84,0x100); /* Don't support mac... */
3404 break;
3406 /* drop through */
3407 default:
3408 return NT_STATUS_INVALID_LEVEL;
3411 *ret_data_len = data_len;
3412 return NT_STATUS_OK;
3415 /****************************************************************************
3416 Reply to a TRANS2_QFSINFO (query filesystem info).
3417 ****************************************************************************/
3419 static void call_trans2qfsinfo(connection_struct *conn,
3420 struct smb_request *req,
3421 char **pparams, int total_params,
3422 char **ppdata, int total_data,
3423 unsigned int max_data_bytes)
3425 char *params = *pparams;
3426 uint16_t info_level;
3427 int data_len = 0;
3428 NTSTATUS status;
3430 if (total_params < 2) {
3431 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3432 return;
3435 info_level = SVAL(params,0);
3437 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3438 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3439 DEBUG(0,("call_trans2qfsinfo: encryption required "
3440 "and info level 0x%x sent.\n",
3441 (unsigned int)info_level));
3442 exit_server_cleanly("encryption required "
3443 "on connection");
3444 return;
3448 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3450 status = smbd_do_qfsinfo(conn, req,
3451 info_level,
3452 req->flags2,
3453 max_data_bytes,
3454 ppdata, &data_len);
3455 if (!NT_STATUS_IS_OK(status)) {
3456 reply_nterror(req, status);
3457 return;
3460 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3461 max_data_bytes);
3463 DEBUG( 4, ( "%s info_level = %d\n",
3464 smb_fn_name(req->cmd), info_level) );
3466 return;
3469 /****************************************************************************
3470 Reply to a TRANS2_SETFSINFO (set filesystem info).
3471 ****************************************************************************/
3473 static void call_trans2setfsinfo(connection_struct *conn,
3474 struct smb_request *req,
3475 char **pparams, int total_params,
3476 char **ppdata, int total_data,
3477 unsigned int max_data_bytes)
3479 char *pdata = *ppdata;
3480 char *params = *pparams;
3481 uint16 info_level;
3483 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3485 /* */
3486 if (total_params < 4) {
3487 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3488 total_params));
3489 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3490 return;
3493 info_level = SVAL(params,2);
3495 if (IS_IPC(conn)) {
3496 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3497 info_level != SMB_SET_CIFS_UNIX_INFO) {
3498 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3499 "info level (0x%x) on IPC$.\n",
3500 (unsigned int)info_level));
3501 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3502 return;
3506 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3507 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3508 DEBUG(0,("call_trans2setfsinfo: encryption required "
3509 "and info level 0x%x sent.\n",
3510 (unsigned int)info_level));
3511 exit_server_cleanly("encryption required "
3512 "on connection");
3513 return;
3517 switch(info_level) {
3518 case SMB_SET_CIFS_UNIX_INFO:
3520 uint16 client_unix_major;
3521 uint16 client_unix_minor;
3522 uint32 client_unix_cap_low;
3523 uint32 client_unix_cap_high;
3525 if (!lp_unix_extensions()) {
3526 reply_nterror(req,
3527 NT_STATUS_INVALID_LEVEL);
3528 return;
3531 /* There should be 12 bytes of capabilities set. */
3532 if (total_data < 8) {
3533 reply_nterror(
3534 req,
3535 NT_STATUS_INVALID_PARAMETER);
3536 return;
3538 client_unix_major = SVAL(pdata,0);
3539 client_unix_minor = SVAL(pdata,2);
3540 client_unix_cap_low = IVAL(pdata,4);
3541 client_unix_cap_high = IVAL(pdata,8);
3542 /* Just print these values for now. */
3543 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3544 cap_low = 0x%x, cap_high = 0x%x\n",
3545 (unsigned int)client_unix_major,
3546 (unsigned int)client_unix_minor,
3547 (unsigned int)client_unix_cap_low,
3548 (unsigned int)client_unix_cap_high ));
3550 /* Here is where we must switch to posix pathname processing... */
3551 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3552 lp_set_posix_pathnames();
3553 mangle_change_to_posix();
3556 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3557 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3558 /* Client that knows how to do posix locks,
3559 * but not posix open/mkdir operations. Set a
3560 * default type for read/write checks. */
3562 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3565 break;
3568 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3570 NTSTATUS status;
3571 size_t param_len = 0;
3572 size_t data_len = total_data;
3574 if (!lp_unix_extensions()) {
3575 reply_nterror(
3576 req,
3577 NT_STATUS_INVALID_LEVEL);
3578 return;
3581 if (lp_smb_encrypt(SNUM(conn)) == false) {
3582 reply_nterror(
3583 req,
3584 NT_STATUS_NOT_SUPPORTED);
3585 return;
3588 DEBUG( 4,("call_trans2setfsinfo: "
3589 "request transport encryption.\n"));
3591 status = srv_request_encryption_setup(conn,
3592 (unsigned char **)ppdata,
3593 &data_len,
3594 (unsigned char **)pparams,
3595 &param_len);
3597 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3598 !NT_STATUS_IS_OK(status)) {
3599 reply_nterror(req, status);
3600 return;
3603 send_trans2_replies(conn, req,
3604 *pparams,
3605 param_len,
3606 *ppdata,
3607 data_len,
3608 max_data_bytes);
3610 if (NT_STATUS_IS_OK(status)) {
3611 /* Server-side transport
3612 * encryption is now *on*. */
3613 status = srv_encryption_start(conn);
3614 if (!NT_STATUS_IS_OK(status)) {
3615 exit_server_cleanly(
3616 "Failure in setting "
3617 "up encrypted transport");
3620 return;
3623 case SMB_FS_QUOTA_INFORMATION:
3625 files_struct *fsp = NULL;
3626 SMB_NTQUOTA_STRUCT quotas;
3628 ZERO_STRUCT(quotas);
3630 /* access check */
3631 if ((conn->server_info->utok.uid != sec_initial_uid())
3632 ||!CAN_WRITE(conn)) {
3633 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3634 lp_servicename(SNUM(conn)),
3635 conn->server_info->unix_name));
3636 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3637 return;
3640 /* note: normaly there're 48 bytes,
3641 * but we didn't use the last 6 bytes for now
3642 * --metze
3644 fsp = file_fsp(req, SVAL(params,0));
3646 if (!check_fsp_ntquota_handle(conn, req,
3647 fsp)) {
3648 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3649 reply_nterror(
3650 req, NT_STATUS_INVALID_HANDLE);
3651 return;
3654 if (total_data < 42) {
3655 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3656 total_data));
3657 reply_nterror(
3658 req,
3659 NT_STATUS_INVALID_PARAMETER);
3660 return;
3663 /* unknown_1 24 NULL bytes in pdata*/
3665 /* the soft quotas 8 bytes (uint64_t)*/
3666 quotas.softlim = (uint64_t)IVAL(pdata,24);
3667 #ifdef LARGE_SMB_OFF_T
3668 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3669 #else /* LARGE_SMB_OFF_T */
3670 if ((IVAL(pdata,28) != 0)&&
3671 ((quotas.softlim != 0xFFFFFFFF)||
3672 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3673 /* more than 32 bits? */
3674 reply_nterror(
3675 req,
3676 NT_STATUS_INVALID_PARAMETER);
3677 return;
3679 #endif /* LARGE_SMB_OFF_T */
3681 /* the hard quotas 8 bytes (uint64_t)*/
3682 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3683 #ifdef LARGE_SMB_OFF_T
3684 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3685 #else /* LARGE_SMB_OFF_T */
3686 if ((IVAL(pdata,36) != 0)&&
3687 ((quotas.hardlim != 0xFFFFFFFF)||
3688 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3689 /* more than 32 bits? */
3690 reply_nterror(
3691 req,
3692 NT_STATUS_INVALID_PARAMETER);
3693 return;
3695 #endif /* LARGE_SMB_OFF_T */
3697 /* quota_flags 2 bytes **/
3698 quotas.qflags = SVAL(pdata,40);
3700 /* unknown_2 6 NULL bytes follow*/
3702 /* now set the quotas */
3703 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3704 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3705 reply_nterror(req, map_nt_error_from_unix(errno));
3706 return;
3709 break;
3711 default:
3712 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3713 info_level));
3714 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3715 return;
3716 break;
3720 * sending this reply works fine,
3721 * but I'm not sure it's the same
3722 * like windows do...
3723 * --metze
3725 reply_outbuf(req, 10, 0);
3728 #if defined(HAVE_POSIX_ACLS)
3729 /****************************************************************************
3730 Utility function to count the number of entries in a POSIX acl.
3731 ****************************************************************************/
3733 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3735 unsigned int ace_count = 0;
3736 int entry_id = SMB_ACL_FIRST_ENTRY;
3737 SMB_ACL_ENTRY_T entry;
3739 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3740 /* get_next... */
3741 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3742 entry_id = SMB_ACL_NEXT_ENTRY;
3744 ace_count++;
3746 return ace_count;
3749 /****************************************************************************
3750 Utility function to marshall a POSIX acl into wire format.
3751 ****************************************************************************/
3753 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3755 int entry_id = SMB_ACL_FIRST_ENTRY;
3756 SMB_ACL_ENTRY_T entry;
3758 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3759 SMB_ACL_TAG_T tagtype;
3760 SMB_ACL_PERMSET_T permset;
3761 unsigned char perms = 0;
3762 unsigned int own_grp;
3764 /* get_next... */
3765 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3766 entry_id = SMB_ACL_NEXT_ENTRY;
3769 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3770 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3771 return False;
3774 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3775 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3776 return False;
3779 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3780 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3781 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3783 SCVAL(pdata,1,perms);
3785 switch (tagtype) {
3786 case SMB_ACL_USER_OBJ:
3787 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3788 own_grp = (unsigned int)pst->st_ex_uid;
3789 SIVAL(pdata,2,own_grp);
3790 SIVAL(pdata,6,0);
3791 break;
3792 case SMB_ACL_USER:
3794 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3795 if (!puid) {
3796 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3797 return False;
3799 own_grp = (unsigned int)*puid;
3800 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3801 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3802 SIVAL(pdata,2,own_grp);
3803 SIVAL(pdata,6,0);
3804 break;
3806 case SMB_ACL_GROUP_OBJ:
3807 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3808 own_grp = (unsigned int)pst->st_ex_gid;
3809 SIVAL(pdata,2,own_grp);
3810 SIVAL(pdata,6,0);
3811 break;
3812 case SMB_ACL_GROUP:
3814 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3815 if (!pgid) {
3816 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3817 return False;
3819 own_grp = (unsigned int)*pgid;
3820 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3821 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3822 SIVAL(pdata,2,own_grp);
3823 SIVAL(pdata,6,0);
3824 break;
3826 case SMB_ACL_MASK:
3827 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3828 SIVAL(pdata,2,0xFFFFFFFF);
3829 SIVAL(pdata,6,0xFFFFFFFF);
3830 break;
3831 case SMB_ACL_OTHER:
3832 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3833 SIVAL(pdata,2,0xFFFFFFFF);
3834 SIVAL(pdata,6,0xFFFFFFFF);
3835 break;
3836 default:
3837 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3838 return False;
3840 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3843 return True;
3845 #endif
3847 /****************************************************************************
3848 Store the FILE_UNIX_BASIC info.
3849 ****************************************************************************/
3851 static char *store_file_unix_basic(connection_struct *conn,
3852 char *pdata,
3853 files_struct *fsp,
3854 const SMB_STRUCT_STAT *psbuf)
3856 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3857 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3859 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3860 pdata += 8;
3862 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3863 pdata += 8;
3865 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3866 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3867 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3868 pdata += 24;
3870 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3871 SIVAL(pdata,4,0);
3872 pdata += 8;
3874 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3875 SIVAL(pdata,4,0);
3876 pdata += 8;
3878 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3879 pdata += 4;
3881 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3882 SIVAL(pdata,4,0);
3883 pdata += 8;
3885 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3886 SIVAL(pdata,4,0);
3887 pdata += 8;
3889 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3890 pdata += 8;
3892 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3893 SIVAL(pdata,4,0);
3894 pdata += 8;
3896 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3897 SIVAL(pdata,4,0);
3898 pdata += 8;
3900 return pdata;
3903 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3904 * the chflags(2) (or equivalent) flags.
3906 * XXX: this really should be behind the VFS interface. To do this, we would
3907 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3908 * Each VFS module could then implement its own mapping as appropriate for the
3909 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3911 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3912 info2_flags_map[] =
3914 #ifdef UF_NODUMP
3915 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3916 #endif
3918 #ifdef UF_IMMUTABLE
3919 { UF_IMMUTABLE, EXT_IMMUTABLE },
3920 #endif
3922 #ifdef UF_APPEND
3923 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3924 #endif
3926 #ifdef UF_HIDDEN
3927 { UF_HIDDEN, EXT_HIDDEN },
3928 #endif
3930 /* Do not remove. We need to guarantee that this array has at least one
3931 * entry to build on HP-UX.
3933 { 0, 0 }
3937 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3938 uint32 *smb_fflags, uint32 *smb_fmask)
3940 int i;
3942 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3943 *smb_fmask |= info2_flags_map[i].smb_fflag;
3944 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3945 *smb_fflags |= info2_flags_map[i].smb_fflag;
3950 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3951 const uint32 smb_fflags,
3952 const uint32 smb_fmask,
3953 int *stat_fflags)
3955 uint32 max_fmask = 0;
3956 int i;
3958 *stat_fflags = psbuf->st_ex_flags;
3960 /* For each flags requested in smb_fmask, check the state of the
3961 * corresponding flag in smb_fflags and set or clear the matching
3962 * stat flag.
3965 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3966 max_fmask |= info2_flags_map[i].smb_fflag;
3967 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3968 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3969 *stat_fflags |= info2_flags_map[i].stat_fflag;
3970 } else {
3971 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3976 /* If smb_fmask is asking to set any bits that are not supported by
3977 * our flag mappings, we should fail.
3979 if ((smb_fmask & max_fmask) != smb_fmask) {
3980 return False;
3983 return True;
3987 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3988 * of file flags and birth (create) time.
3990 static char *store_file_unix_basic_info2(connection_struct *conn,
3991 char *pdata,
3992 files_struct *fsp,
3993 const SMB_STRUCT_STAT *psbuf)
3995 uint32 file_flags = 0;
3996 uint32 flags_mask = 0;
3998 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4000 /* Create (birth) time 64 bit */
4001 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4002 pdata += 8;
4004 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4005 SIVAL(pdata, 0, file_flags); /* flags */
4006 SIVAL(pdata, 4, flags_mask); /* mask */
4007 pdata += 8;
4009 return pdata;
4012 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4013 const struct stream_struct *streams,
4014 char *data,
4015 unsigned int max_data_bytes,
4016 unsigned int *data_size)
4018 unsigned int i;
4019 unsigned int ofs = 0;
4021 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4022 unsigned int next_offset;
4023 size_t namelen;
4024 smb_ucs2_t *namebuf;
4026 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4027 streams[i].name, &namelen) ||
4028 namelen <= 2)
4030 return NT_STATUS_INVALID_PARAMETER;
4034 * name_buf is now null-terminated, we need to marshall as not
4035 * terminated
4038 namelen -= 2;
4040 SIVAL(data, ofs+4, namelen);
4041 SOFF_T(data, ofs+8, streams[i].size);
4042 SOFF_T(data, ofs+16, streams[i].alloc_size);
4043 memcpy(data+ofs+24, namebuf, namelen);
4044 TALLOC_FREE(namebuf);
4046 next_offset = ofs + 24 + namelen;
4048 if (i == num_streams-1) {
4049 SIVAL(data, ofs, 0);
4051 else {
4052 unsigned int align = ndr_align_size(next_offset, 8);
4054 memset(data+next_offset, 0, align);
4055 next_offset += align;
4057 SIVAL(data, ofs, next_offset - ofs);
4058 ofs = next_offset;
4061 ofs = next_offset;
4064 *data_size = ofs;
4066 return NT_STATUS_OK;
4069 /****************************************************************************
4070 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4071 ****************************************************************************/
4073 static void call_trans2qpipeinfo(connection_struct *conn,
4074 struct smb_request *req,
4075 unsigned int tran_call,
4076 char **pparams, int total_params,
4077 char **ppdata, int total_data,
4078 unsigned int max_data_bytes)
4080 char *params = *pparams;
4081 char *pdata = *ppdata;
4082 unsigned int data_size = 0;
4083 unsigned int param_size = 2;
4084 uint16 info_level;
4085 files_struct *fsp;
4087 if (!params) {
4088 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4089 return;
4092 if (total_params < 4) {
4093 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4094 return;
4097 fsp = file_fsp(req, SVAL(params,0));
4098 if (!fsp_is_np(fsp)) {
4099 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4100 return;
4103 info_level = SVAL(params,2);
4105 *pparams = (char *)SMB_REALLOC(*pparams,2);
4106 if (*pparams == NULL) {
4107 reply_nterror(req, NT_STATUS_NO_MEMORY);
4108 return;
4110 params = *pparams;
4111 SSVAL(params,0,0);
4112 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4113 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4114 if (*ppdata == NULL ) {
4115 reply_nterror(req, NT_STATUS_NO_MEMORY);
4116 return;
4118 pdata = *ppdata;
4120 switch (info_level) {
4121 case SMB_FILE_STANDARD_INFORMATION:
4122 memset(pdata,0,24);
4123 SOFF_T(pdata,0,4096LL);
4124 SIVAL(pdata,16,1);
4125 SIVAL(pdata,20,1);
4126 data_size = 24;
4127 break;
4129 default:
4130 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4131 return;
4134 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4135 max_data_bytes);
4137 return;
4140 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4141 TALLOC_CTX *mem_ctx,
4142 uint16_t info_level,
4143 files_struct *fsp,
4144 struct smb_filename *smb_fname,
4145 bool delete_pending,
4146 struct timespec write_time_ts,
4147 bool ms_dfs_link,
4148 struct ea_list *ea_list,
4149 int lock_data_count,
4150 char *lock_data,
4151 uint16_t flags2,
4152 unsigned int max_data_bytes,
4153 char **ppdata,
4154 unsigned int *pdata_size)
4156 char *pdata = *ppdata;
4157 char *dstart, *dend;
4158 unsigned int data_size;
4159 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4160 time_t create_time, mtime, atime, c_time;
4161 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4162 char *p;
4163 char *base_name;
4164 char *dos_fname;
4165 int mode;
4166 int nlink;
4167 NTSTATUS status;
4168 uint64_t file_size = 0;
4169 uint64_t pos = 0;
4170 uint64_t allocation_size = 0;
4171 uint64_t file_index = 0;
4172 uint32_t access_mask = 0;
4174 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4175 return NT_STATUS_INVALID_LEVEL;
4178 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4179 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4180 info_level, max_data_bytes));
4182 if (ms_dfs_link) {
4183 mode = dos_mode_msdfs(conn, smb_fname);
4184 } else {
4185 mode = dos_mode(conn, smb_fname);
4188 nlink = psbuf->st_ex_nlink;
4190 if (nlink && (mode&aDIR)) {
4191 nlink = 1;
4194 if ((nlink > 0) && delete_pending) {
4195 nlink -= 1;
4198 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4199 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4200 if (*ppdata == NULL) {
4201 return NT_STATUS_NO_MEMORY;
4203 pdata = *ppdata;
4204 dstart = pdata;
4205 dend = dstart + data_size - 1;
4207 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4208 update_stat_ex_mtime(psbuf, write_time_ts);
4211 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4212 mtime_ts = psbuf->st_ex_mtime;
4213 atime_ts = psbuf->st_ex_atime;
4214 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4216 if (lp_dos_filetime_resolution(SNUM(conn))) {
4217 dos_filetime_timespec(&create_time_ts);
4218 dos_filetime_timespec(&mtime_ts);
4219 dos_filetime_timespec(&atime_ts);
4220 dos_filetime_timespec(&ctime_ts);
4223 create_time = convert_timespec_to_time_t(create_time_ts);
4224 mtime = convert_timespec_to_time_t(mtime_ts);
4225 atime = convert_timespec_to_time_t(atime_ts);
4226 c_time = convert_timespec_to_time_t(ctime_ts);
4228 p = strrchr_m(smb_fname->base_name,'/');
4229 if (!p)
4230 base_name = smb_fname->base_name;
4231 else
4232 base_name = p+1;
4234 /* NT expects the name to be in an exact form of the *full*
4235 filename. See the trans2 torture test */
4236 if (ISDOT(base_name)) {
4237 dos_fname = talloc_strdup(mem_ctx, "\\");
4238 if (!dos_fname) {
4239 return NT_STATUS_NO_MEMORY;
4241 } else {
4242 dos_fname = talloc_asprintf(mem_ctx,
4243 "\\%s",
4244 smb_fname->base_name);
4245 if (!dos_fname) {
4246 return NT_STATUS_NO_MEMORY;
4248 if (is_ntfs_stream_smb_fname(smb_fname)) {
4249 dos_fname = talloc_asprintf(dos_fname, "%s",
4250 smb_fname->stream_name);
4251 if (!dos_fname) {
4252 return NT_STATUS_NO_MEMORY;
4256 string_replace(dos_fname, '/', '\\');
4259 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4261 if (!fsp) {
4262 /* Do we have this path open ? */
4263 files_struct *fsp1;
4264 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4265 fsp1 = file_find_di_first(fileid);
4266 if (fsp1 && fsp1->initial_allocation_size) {
4267 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4271 if (!(mode & aDIR)) {
4272 file_size = get_file_size_stat(psbuf);
4275 if (fsp) {
4276 pos = fsp->fh->position_information;
4279 if (fsp) {
4280 access_mask = fsp->access_mask;
4281 } else {
4282 /* GENERIC_EXECUTE mapping from Windows */
4283 access_mask = 0x12019F;
4286 /* This should be an index number - looks like
4287 dev/ino to me :-)
4289 I think this causes us to fail the IFSKIT
4290 BasicFileInformationTest. -tpot */
4291 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4292 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4294 switch (info_level) {
4295 case SMB_INFO_STANDARD:
4296 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4297 data_size = 22;
4298 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4299 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4300 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4301 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4302 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4303 SSVAL(pdata,l1_attrFile,mode);
4304 break;
4306 case SMB_INFO_QUERY_EA_SIZE:
4308 unsigned int ea_size =
4309 estimate_ea_size(conn, fsp,
4310 smb_fname->base_name);
4311 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4312 data_size = 26;
4313 srv_put_dos_date2(pdata,0,create_time);
4314 srv_put_dos_date2(pdata,4,atime);
4315 srv_put_dos_date2(pdata,8,mtime); /* write time */
4316 SIVAL(pdata,12,(uint32)file_size);
4317 SIVAL(pdata,16,(uint32)allocation_size);
4318 SSVAL(pdata,20,mode);
4319 SIVAL(pdata,22,ea_size);
4320 break;
4323 case SMB_INFO_IS_NAME_VALID:
4324 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4325 if (fsp) {
4326 /* os/2 needs this ? really ?*/
4327 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4329 /* This is only reached for qpathinfo */
4330 data_size = 0;
4331 break;
4333 case SMB_INFO_QUERY_EAS_FROM_LIST:
4335 size_t total_ea_len = 0;
4336 struct ea_list *ea_file_list = NULL;
4338 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4340 ea_file_list =
4341 get_ea_list_from_file(mem_ctx, conn, fsp,
4342 smb_fname->base_name,
4343 &total_ea_len);
4344 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4346 if (!ea_list || (total_ea_len > data_size)) {
4347 data_size = 4;
4348 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4349 break;
4352 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4353 break;
4356 case SMB_INFO_QUERY_ALL_EAS:
4358 /* We have data_size bytes to put EA's into. */
4359 size_t total_ea_len = 0;
4361 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4363 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4364 smb_fname->base_name,
4365 &total_ea_len);
4366 if (!ea_list || (total_ea_len > data_size)) {
4367 data_size = 4;
4368 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4369 break;
4372 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4373 break;
4376 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4378 /* This is FileFullEaInformation - 0xF which maps to
4379 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4381 /* We have data_size bytes to put EA's into. */
4382 size_t total_ea_len = 0;
4383 struct ea_list *ea_file_list = NULL;
4385 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4387 /*TODO: add filtering and index handling */
4389 ea_file_list =
4390 get_ea_list_from_file(mem_ctx, conn, fsp,
4391 smb_fname->base_name,
4392 &total_ea_len);
4393 if (!ea_file_list) {
4394 return NT_STATUS_NO_EAS_ON_FILE;
4397 status = fill_ea_chained_buffer(mem_ctx,
4398 pdata,
4399 data_size,
4400 &data_size,
4401 conn, ea_file_list);
4402 if (!NT_STATUS_IS_OK(status)) {
4403 return status;
4405 break;
4408 case SMB_FILE_BASIC_INFORMATION:
4409 case SMB_QUERY_FILE_BASIC_INFO:
4411 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4412 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4413 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4414 } else {
4415 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4416 data_size = 40;
4417 SIVAL(pdata,36,0);
4419 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4420 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4421 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4422 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4423 SIVAL(pdata,32,mode);
4425 DEBUG(5,("SMB_QFBI - "));
4426 DEBUG(5,("create: %s ", ctime(&create_time)));
4427 DEBUG(5,("access: %s ", ctime(&atime)));
4428 DEBUG(5,("write: %s ", ctime(&mtime)));
4429 DEBUG(5,("change: %s ", ctime(&c_time)));
4430 DEBUG(5,("mode: %x\n", mode));
4431 break;
4433 case SMB_FILE_STANDARD_INFORMATION:
4434 case SMB_QUERY_FILE_STANDARD_INFO:
4436 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4437 data_size = 24;
4438 SOFF_T(pdata,0,allocation_size);
4439 SOFF_T(pdata,8,file_size);
4440 SIVAL(pdata,16,nlink);
4441 SCVAL(pdata,20,delete_pending?1:0);
4442 SCVAL(pdata,21,(mode&aDIR)?1:0);
4443 SSVAL(pdata,22,0); /* Padding. */
4444 break;
4446 case SMB_FILE_EA_INFORMATION:
4447 case SMB_QUERY_FILE_EA_INFO:
4449 unsigned int ea_size =
4450 estimate_ea_size(conn, fsp, smb_fname->base_name);
4451 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4452 data_size = 4;
4453 SIVAL(pdata,0,ea_size);
4454 break;
4457 /* Get the 8.3 name - used if NT SMB was negotiated. */
4458 case SMB_QUERY_FILE_ALT_NAME_INFO:
4459 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4461 int len;
4462 char mangled_name[13];
4463 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4464 if (!name_to_8_3(base_name,mangled_name,
4465 True,conn->params)) {
4466 return NT_STATUS_NO_MEMORY;
4468 len = srvstr_push(dstart, flags2,
4469 pdata+4, mangled_name,
4470 PTR_DIFF(dend, pdata+4),
4471 STR_UNICODE);
4472 data_size = 4 + len;
4473 SIVAL(pdata,0,len);
4474 break;
4477 case SMB_QUERY_FILE_NAME_INFO:
4479 int len;
4481 this must be *exactly* right for ACLs on mapped drives to work
4483 len = srvstr_push(dstart, flags2,
4484 pdata+4, dos_fname,
4485 PTR_DIFF(dend, pdata+4),
4486 STR_UNICODE);
4487 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4488 data_size = 4 + len;
4489 SIVAL(pdata,0,len);
4490 break;
4493 case SMB_FILE_ALLOCATION_INFORMATION:
4494 case SMB_QUERY_FILE_ALLOCATION_INFO:
4495 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4496 data_size = 8;
4497 SOFF_T(pdata,0,allocation_size);
4498 break;
4500 case SMB_FILE_END_OF_FILE_INFORMATION:
4501 case SMB_QUERY_FILE_END_OF_FILEINFO:
4502 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4503 data_size = 8;
4504 SOFF_T(pdata,0,file_size);
4505 break;
4507 case SMB_QUERY_FILE_ALL_INFO:
4508 case SMB_FILE_ALL_INFORMATION:
4510 int len;
4511 unsigned int ea_size =
4512 estimate_ea_size(conn, fsp, smb_fname->base_name);
4513 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4514 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4515 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4516 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4517 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4518 SIVAL(pdata,32,mode);
4519 SIVAL(pdata,36,0); /* padding. */
4520 pdata += 40;
4521 SOFF_T(pdata,0,allocation_size);
4522 SOFF_T(pdata,8,file_size);
4523 SIVAL(pdata,16,nlink);
4524 SCVAL(pdata,20,delete_pending);
4525 SCVAL(pdata,21,(mode&aDIR)?1:0);
4526 SSVAL(pdata,22,0);
4527 pdata += 24;
4528 SIVAL(pdata,0,ea_size);
4529 pdata += 4; /* EA info */
4530 len = srvstr_push(dstart, flags2,
4531 pdata+4, dos_fname,
4532 PTR_DIFF(dend, pdata+4),
4533 STR_UNICODE);
4534 SIVAL(pdata,0,len);
4535 pdata += 4 + len;
4536 data_size = PTR_DIFF(pdata,(*ppdata));
4537 break;
4540 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4542 int len;
4543 unsigned int ea_size =
4544 estimate_ea_size(conn, fsp, smb_fname->base_name);
4545 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4546 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4547 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4548 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4549 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4550 SIVAL(pdata, 0x20, mode);
4551 SIVAL(pdata, 0x24, 0); /* padding. */
4552 SBVAL(pdata, 0x28, allocation_size);
4553 SBVAL(pdata, 0x30, file_size);
4554 SIVAL(pdata, 0x38, nlink);
4555 SCVAL(pdata, 0x3C, delete_pending);
4556 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4557 SSVAL(pdata, 0x3E, 0); /* padding */
4558 SBVAL(pdata, 0x40, file_index);
4559 SIVAL(pdata, 0x48, ea_size);
4560 SIVAL(pdata, 0x4C, access_mask);
4561 SBVAL(pdata, 0x50, pos);
4562 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4563 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4565 pdata += 0x60;
4567 len = srvstr_push(dstart, flags2,
4568 pdata+4, dos_fname,
4569 PTR_DIFF(dend, pdata+4),
4570 STR_UNICODE);
4571 SIVAL(pdata,0,len);
4572 pdata += 4 + len;
4573 data_size = PTR_DIFF(pdata,(*ppdata));
4574 break;
4576 case SMB_FILE_INTERNAL_INFORMATION:
4578 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4579 SBVAL(pdata, 0, file_index);
4580 data_size = 8;
4581 break;
4583 case SMB_FILE_ACCESS_INFORMATION:
4584 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4585 SIVAL(pdata, 0, access_mask);
4586 data_size = 4;
4587 break;
4589 case SMB_FILE_NAME_INFORMATION:
4590 /* Pathname with leading '\'. */
4592 size_t byte_len;
4593 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4594 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4595 SIVAL(pdata,0,byte_len);
4596 data_size = 4 + byte_len;
4597 break;
4600 case SMB_FILE_DISPOSITION_INFORMATION:
4601 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4602 data_size = 1;
4603 SCVAL(pdata,0,delete_pending);
4604 break;
4606 case SMB_FILE_POSITION_INFORMATION:
4607 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4608 data_size = 8;
4609 SOFF_T(pdata,0,pos);
4610 break;
4612 case SMB_FILE_MODE_INFORMATION:
4613 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4614 SIVAL(pdata,0,mode);
4615 data_size = 4;
4616 break;
4618 case SMB_FILE_ALIGNMENT_INFORMATION:
4619 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4620 SIVAL(pdata,0,0); /* No alignment needed. */
4621 data_size = 4;
4622 break;
4625 * NT4 server just returns "invalid query" to this - if we try
4626 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4627 * want this. JRA.
4629 /* The first statement above is false - verified using Thursby
4630 * client against NT4 -- gcolley.
4632 case SMB_QUERY_FILE_STREAM_INFO:
4633 case SMB_FILE_STREAM_INFORMATION: {
4634 unsigned int num_streams;
4635 struct stream_struct *streams;
4637 DEBUG(10,("smbd_do_qfilepathinfo: "
4638 "SMB_FILE_STREAM_INFORMATION\n"));
4640 if (is_ntfs_stream_smb_fname(smb_fname)) {
4641 return NT_STATUS_INVALID_PARAMETER;
4644 status = SMB_VFS_STREAMINFO(
4645 conn, fsp, smb_fname->base_name, talloc_tos(),
4646 &num_streams, &streams);
4648 if (!NT_STATUS_IS_OK(status)) {
4649 DEBUG(10, ("could not get stream info: %s\n",
4650 nt_errstr(status)));
4651 return status;
4654 status = marshall_stream_info(num_streams, streams,
4655 pdata, max_data_bytes,
4656 &data_size);
4658 if (!NT_STATUS_IS_OK(status)) {
4659 DEBUG(10, ("marshall_stream_info failed: %s\n",
4660 nt_errstr(status)));
4661 return status;
4664 TALLOC_FREE(streams);
4666 break;
4668 case SMB_QUERY_COMPRESSION_INFO:
4669 case SMB_FILE_COMPRESSION_INFORMATION:
4670 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4671 SOFF_T(pdata,0,file_size);
4672 SIVAL(pdata,8,0); /* ??? */
4673 SIVAL(pdata,12,0); /* ??? */
4674 data_size = 16;
4675 break;
4677 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4678 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4679 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4680 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4681 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4682 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4683 SOFF_T(pdata,32,allocation_size);
4684 SOFF_T(pdata,40,file_size);
4685 SIVAL(pdata,48,mode);
4686 SIVAL(pdata,52,0); /* ??? */
4687 data_size = 56;
4688 break;
4690 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4691 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4692 SIVAL(pdata,0,mode);
4693 SIVAL(pdata,4,0);
4694 data_size = 8;
4695 break;
4698 * CIFS UNIX Extensions.
4701 case SMB_QUERY_FILE_UNIX_BASIC:
4703 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4704 data_size = PTR_DIFF(pdata,(*ppdata));
4707 int i;
4708 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4710 for (i=0; i<100; i++)
4711 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4712 DEBUG(4,("\n"));
4715 break;
4717 case SMB_QUERY_FILE_UNIX_INFO2:
4719 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4720 data_size = PTR_DIFF(pdata,(*ppdata));
4723 int i;
4724 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4726 for (i=0; i<100; i++)
4727 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4728 DEBUG(4,("\n"));
4731 break;
4733 case SMB_QUERY_FILE_UNIX_LINK:
4735 int len;
4736 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4738 if (!buffer) {
4739 return NT_STATUS_NO_MEMORY;
4742 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4743 #ifdef S_ISLNK
4744 if(!S_ISLNK(psbuf->st_ex_mode)) {
4745 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4747 #else
4748 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4749 #endif
4750 len = SMB_VFS_READLINK(conn,
4751 smb_fname->base_name,
4752 buffer, PATH_MAX);
4753 if (len == -1) {
4754 return map_nt_error_from_unix(errno);
4756 buffer[len] = 0;
4757 len = srvstr_push(dstart, flags2,
4758 pdata, buffer,
4759 PTR_DIFF(dend, pdata),
4760 STR_TERMINATE);
4761 pdata += len;
4762 data_size = PTR_DIFF(pdata,(*ppdata));
4764 break;
4767 #if defined(HAVE_POSIX_ACLS)
4768 case SMB_QUERY_POSIX_ACL:
4770 SMB_ACL_T file_acl = NULL;
4771 SMB_ACL_T def_acl = NULL;
4772 uint16 num_file_acls = 0;
4773 uint16 num_def_acls = 0;
4775 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4776 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4777 } else {
4778 file_acl =
4779 SMB_VFS_SYS_ACL_GET_FILE(conn,
4780 smb_fname->base_name,
4781 SMB_ACL_TYPE_ACCESS);
4784 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4785 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4786 "not implemented on "
4787 "filesystem containing %s\n",
4788 smb_fname->base_name));
4789 return NT_STATUS_NOT_IMPLEMENTED;
4792 if (S_ISDIR(psbuf->st_ex_mode)) {
4793 if (fsp && fsp->is_directory) {
4794 def_acl =
4795 SMB_VFS_SYS_ACL_GET_FILE(
4796 conn,
4797 fsp->fsp_name->base_name,
4798 SMB_ACL_TYPE_DEFAULT);
4799 } else {
4800 def_acl =
4801 SMB_VFS_SYS_ACL_GET_FILE(
4802 conn,
4803 smb_fname->base_name,
4804 SMB_ACL_TYPE_DEFAULT);
4806 def_acl = free_empty_sys_acl(conn, def_acl);
4809 num_file_acls = count_acl_entries(conn, file_acl);
4810 num_def_acls = count_acl_entries(conn, def_acl);
4812 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4813 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4814 data_size,
4815 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4816 SMB_POSIX_ACL_HEADER_SIZE) ));
4817 if (file_acl) {
4818 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4820 if (def_acl) {
4821 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4823 return NT_STATUS_BUFFER_TOO_SMALL;
4826 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4827 SSVAL(pdata,2,num_file_acls);
4828 SSVAL(pdata,4,num_def_acls);
4829 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4830 if (file_acl) {
4831 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4833 if (def_acl) {
4834 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4836 return NT_STATUS_INTERNAL_ERROR;
4838 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4839 if (file_acl) {
4840 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4842 if (def_acl) {
4843 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4845 return NT_STATUS_INTERNAL_ERROR;
4848 if (file_acl) {
4849 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4851 if (def_acl) {
4852 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4854 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4855 break;
4857 #endif
4860 case SMB_QUERY_POSIX_LOCK:
4862 uint64_t count;
4863 uint64_t offset;
4864 uint32 lock_pid;
4865 enum brl_type lock_type;
4867 /* We need an open file with a real fd for this. */
4868 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4869 return NT_STATUS_INVALID_LEVEL;
4872 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4873 return NT_STATUS_INVALID_PARAMETER;
4876 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4877 case POSIX_LOCK_TYPE_READ:
4878 lock_type = READ_LOCK;
4879 break;
4880 case POSIX_LOCK_TYPE_WRITE:
4881 lock_type = WRITE_LOCK;
4882 break;
4883 case POSIX_LOCK_TYPE_UNLOCK:
4884 default:
4885 /* There's no point in asking for an unlock... */
4886 return NT_STATUS_INVALID_PARAMETER;
4889 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4890 #if defined(HAVE_LONGLONG)
4891 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4892 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4893 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4894 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4895 #else /* HAVE_LONGLONG */
4896 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4897 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4898 #endif /* HAVE_LONGLONG */
4900 status = query_lock(fsp,
4901 &lock_pid,
4902 &count,
4903 &offset,
4904 &lock_type,
4905 POSIX_LOCK);
4907 if (ERROR_WAS_LOCK_DENIED(status)) {
4908 /* Here we need to report who has it locked... */
4909 data_size = POSIX_LOCK_DATA_SIZE;
4911 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4912 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4913 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4914 #if defined(HAVE_LONGLONG)
4915 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4916 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4917 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4918 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4919 #else /* HAVE_LONGLONG */
4920 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4921 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4922 #endif /* HAVE_LONGLONG */
4924 } else if (NT_STATUS_IS_OK(status)) {
4925 /* For success we just return a copy of what we sent
4926 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4927 data_size = POSIX_LOCK_DATA_SIZE;
4928 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4929 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4930 } else {
4931 return status;
4933 break;
4936 default:
4937 return NT_STATUS_INVALID_LEVEL;
4940 *pdata_size = data_size;
4941 return NT_STATUS_OK;
4944 /****************************************************************************
4945 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4946 file name or file id).
4947 ****************************************************************************/
4949 static void call_trans2qfilepathinfo(connection_struct *conn,
4950 struct smb_request *req,
4951 unsigned int tran_call,
4952 char **pparams, int total_params,
4953 char **ppdata, int total_data,
4954 unsigned int max_data_bytes)
4956 char *params = *pparams;
4957 char *pdata = *ppdata;
4958 uint16 info_level;
4959 unsigned int data_size = 0;
4960 unsigned int param_size = 2;
4961 struct smb_filename *smb_fname = NULL;
4962 bool delete_pending = False;
4963 struct timespec write_time_ts;
4964 files_struct *fsp = NULL;
4965 struct file_id fileid;
4966 struct ea_list *ea_list = NULL;
4967 int lock_data_count = 0;
4968 char *lock_data = NULL;
4969 bool ms_dfs_link = false;
4970 NTSTATUS status = NT_STATUS_OK;
4972 if (!params) {
4973 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4974 return;
4977 ZERO_STRUCT(write_time_ts);
4979 if (tran_call == TRANSACT2_QFILEINFO) {
4980 if (total_params < 4) {
4981 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4982 return;
4985 if (IS_IPC(conn)) {
4986 call_trans2qpipeinfo(conn, req, tran_call,
4987 pparams, total_params,
4988 ppdata, total_data,
4989 max_data_bytes);
4990 return;
4993 fsp = file_fsp(req, SVAL(params,0));
4994 info_level = SVAL(params,2);
4996 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4998 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4999 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5000 return;
5003 /* Initial check for valid fsp ptr. */
5004 if (!check_fsp_open(conn, req, fsp)) {
5005 return;
5008 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5009 &smb_fname);
5010 if (!NT_STATUS_IS_OK(status)) {
5011 reply_nterror(req, status);
5012 return;
5015 if(fsp->fake_file_handle) {
5017 * This is actually for the QUOTA_FAKE_FILE --metze
5020 /* We know this name is ok, it's already passed the checks. */
5022 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5024 * This is actually a QFILEINFO on a directory
5025 * handle (returned from an NT SMB). NT5.0 seems
5026 * to do this call. JRA.
5029 if (INFO_LEVEL_IS_UNIX(info_level)) {
5030 /* Always do lstat for UNIX calls. */
5031 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5032 DEBUG(3,("call_trans2qfilepathinfo: "
5033 "SMB_VFS_LSTAT of %s failed "
5034 "(%s)\n",
5035 smb_fname_str_dbg(smb_fname),
5036 strerror(errno)));
5037 reply_nterror(req,
5038 map_nt_error_from_unix(errno));
5039 return;
5041 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5042 DEBUG(3,("call_trans2qfilepathinfo: "
5043 "SMB_VFS_STAT of %s failed (%s)\n",
5044 smb_fname_str_dbg(smb_fname),
5045 strerror(errno)));
5046 reply_nterror(req,
5047 map_nt_error_from_unix(errno));
5048 return;
5051 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5052 get_file_infos(fileid, &delete_pending, &write_time_ts);
5053 } else {
5055 * Original code - this is an open file.
5057 if (!check_fsp(conn, req, fsp)) {
5058 return;
5061 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5062 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5063 fsp->fnum, strerror(errno)));
5064 reply_nterror(req,
5065 map_nt_error_from_unix(errno));
5066 return;
5068 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5069 get_file_infos(fileid, &delete_pending, &write_time_ts);
5072 } else {
5073 char *fname = NULL;
5075 /* qpathinfo */
5076 if (total_params < 7) {
5077 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5078 return;
5081 info_level = SVAL(params,0);
5083 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5085 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5086 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5087 return;
5090 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5091 total_params - 6,
5092 STR_TERMINATE, &status);
5093 if (!NT_STATUS_IS_OK(status)) {
5094 reply_nterror(req, status);
5095 return;
5098 status = filename_convert(req,
5099 conn,
5100 req->flags2 & FLAGS2_DFS_PATHNAMES,
5101 fname,
5103 NULL,
5104 &smb_fname);
5105 if (!NT_STATUS_IS_OK(status)) {
5106 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5107 reply_botherror(req,
5108 NT_STATUS_PATH_NOT_COVERED,
5109 ERRSRV, ERRbadpath);
5110 return;
5112 reply_nterror(req, status);
5113 return;
5116 /* If this is a stream, check if there is a delete_pending. */
5117 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5118 && is_ntfs_stream_smb_fname(smb_fname)) {
5119 struct smb_filename *smb_fname_base = NULL;
5121 /* Create an smb_filename with stream_name == NULL. */
5122 status =
5123 create_synthetic_smb_fname(talloc_tos(),
5124 smb_fname->base_name,
5125 NULL, NULL,
5126 &smb_fname_base);
5127 if (!NT_STATUS_IS_OK(status)) {
5128 reply_nterror(req, status);
5129 return;
5132 if (INFO_LEVEL_IS_UNIX(info_level)) {
5133 /* Always do lstat for UNIX calls. */
5134 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5135 DEBUG(3,("call_trans2qfilepathinfo: "
5136 "SMB_VFS_LSTAT of %s failed "
5137 "(%s)\n",
5138 smb_fname_str_dbg(smb_fname_base),
5139 strerror(errno)));
5140 TALLOC_FREE(smb_fname_base);
5141 reply_nterror(req,
5142 map_nt_error_from_unix(errno));
5143 return;
5145 } else {
5146 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5147 DEBUG(3,("call_trans2qfilepathinfo: "
5148 "fileinfo of %s failed "
5149 "(%s)\n",
5150 smb_fname_str_dbg(smb_fname_base),
5151 strerror(errno)));
5152 TALLOC_FREE(smb_fname_base);
5153 reply_nterror(req,
5154 map_nt_error_from_unix(errno));
5155 return;
5159 fileid = vfs_file_id_from_sbuf(conn,
5160 &smb_fname_base->st);
5161 TALLOC_FREE(smb_fname_base);
5162 get_file_infos(fileid, &delete_pending, NULL);
5163 if (delete_pending) {
5164 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5165 return;
5169 if (INFO_LEVEL_IS_UNIX(info_level)) {
5170 /* Always do lstat for UNIX calls. */
5171 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5172 DEBUG(3,("call_trans2qfilepathinfo: "
5173 "SMB_VFS_LSTAT of %s failed (%s)\n",
5174 smb_fname_str_dbg(smb_fname),
5175 strerror(errno)));
5176 reply_nterror(req,
5177 map_nt_error_from_unix(errno));
5178 return;
5181 } else if (!VALID_STAT(smb_fname->st) &&
5182 SMB_VFS_STAT(conn, smb_fname) &&
5183 (info_level != SMB_INFO_IS_NAME_VALID)) {
5184 ms_dfs_link = check_msdfs_link(conn,
5185 smb_fname->base_name,
5186 &smb_fname->st);
5188 if (!ms_dfs_link) {
5189 DEBUG(3,("call_trans2qfilepathinfo: "
5190 "SMB_VFS_STAT of %s failed (%s)\n",
5191 smb_fname_str_dbg(smb_fname),
5192 strerror(errno)));
5193 reply_nterror(req,
5194 map_nt_error_from_unix(errno));
5195 return;
5199 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5200 get_file_infos(fileid, &delete_pending, &write_time_ts);
5201 if (delete_pending) {
5202 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5203 return;
5207 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5208 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5209 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5211 /* Pull out any data sent here before we realloc. */
5212 switch (info_level) {
5213 case SMB_INFO_QUERY_EAS_FROM_LIST:
5215 /* Pull any EA list from the data portion. */
5216 uint32 ea_size;
5218 if (total_data < 4) {
5219 reply_nterror(
5220 req, NT_STATUS_INVALID_PARAMETER);
5221 return;
5223 ea_size = IVAL(pdata,0);
5225 if (total_data > 0 && ea_size != total_data) {
5226 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5227 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5228 reply_nterror(
5229 req, NT_STATUS_INVALID_PARAMETER);
5230 return;
5233 if (!lp_ea_support(SNUM(conn))) {
5234 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5235 return;
5238 /* Pull out the list of names. */
5239 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5240 if (!ea_list) {
5241 reply_nterror(
5242 req, NT_STATUS_INVALID_PARAMETER);
5243 return;
5245 break;
5248 case SMB_QUERY_POSIX_LOCK:
5250 if (fsp == NULL || fsp->fh->fd == -1) {
5251 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5252 return;
5255 if (total_data != POSIX_LOCK_DATA_SIZE) {
5256 reply_nterror(
5257 req, NT_STATUS_INVALID_PARAMETER);
5258 return;
5261 /* Copy the lock range data. */
5262 lock_data = (char *)TALLOC_MEMDUP(
5263 req, pdata, total_data);
5264 if (!lock_data) {
5265 reply_nterror(req, NT_STATUS_NO_MEMORY);
5266 return;
5268 lock_data_count = total_data;
5270 default:
5271 break;
5274 *pparams = (char *)SMB_REALLOC(*pparams,2);
5275 if (*pparams == NULL) {
5276 reply_nterror(req, NT_STATUS_NO_MEMORY);
5277 return;
5279 params = *pparams;
5280 SSVAL(params,0,0);
5283 * draft-leach-cifs-v1-spec-02.txt
5284 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5285 * says:
5287 * The requested information is placed in the Data portion of the
5288 * transaction response. For the information levels greater than 0x100,
5289 * the transaction response has 1 parameter word which should be
5290 * ignored by the client.
5292 * However Windows only follows this rule for the IS_NAME_VALID call.
5294 switch (info_level) {
5295 case SMB_INFO_IS_NAME_VALID:
5296 param_size = 0;
5297 break;
5300 if ((info_level & 0xFF00) == 0xFF00) {
5302 * We use levels that start with 0xFF00
5303 * internally to represent SMB2 specific levels
5305 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5306 return;
5309 status = smbd_do_qfilepathinfo(conn, req, info_level,
5310 fsp, smb_fname,
5311 delete_pending, write_time_ts,
5312 ms_dfs_link, ea_list,
5313 lock_data_count, lock_data,
5314 req->flags2, max_data_bytes,
5315 ppdata, &data_size);
5316 if (!NT_STATUS_IS_OK(status)) {
5317 reply_nterror(req, status);
5318 return;
5321 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5322 max_data_bytes);
5324 return;
5327 /****************************************************************************
5328 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5329 code.
5330 ****************************************************************************/
5332 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5333 connection_struct *conn,
5334 const struct smb_filename *smb_fname_old,
5335 const struct smb_filename *smb_fname_new)
5337 NTSTATUS status = NT_STATUS_OK;
5339 /* source must already exist. */
5340 if (!VALID_STAT(smb_fname_old->st)) {
5341 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5344 /* Disallow if newname already exists. */
5345 if (VALID_STAT(smb_fname_new->st)) {
5346 return NT_STATUS_OBJECT_NAME_COLLISION;
5349 /* No links from a directory. */
5350 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5351 return NT_STATUS_FILE_IS_A_DIRECTORY;
5354 /* Setting a hardlink to/from a stream isn't currently supported. */
5355 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5356 is_ntfs_stream_smb_fname(smb_fname_new)) {
5357 return NT_STATUS_INVALID_PARAMETER;
5360 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5361 smb_fname_old->base_name, smb_fname_new->base_name));
5363 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5364 smb_fname_new->base_name) != 0) {
5365 status = map_nt_error_from_unix(errno);
5366 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5367 nt_errstr(status), smb_fname_old->base_name,
5368 smb_fname_new->base_name));
5370 return status;
5373 /****************************************************************************
5374 Deal with setting the time from any of the setfilepathinfo functions.
5375 ****************************************************************************/
5377 NTSTATUS smb_set_file_time(connection_struct *conn,
5378 files_struct *fsp,
5379 const struct smb_filename *smb_fname,
5380 struct smb_file_time *ft,
5381 bool setting_write_time)
5383 struct smb_filename smb_fname_base;
5384 uint32 action =
5385 FILE_NOTIFY_CHANGE_LAST_ACCESS
5386 |FILE_NOTIFY_CHANGE_LAST_WRITE
5387 |FILE_NOTIFY_CHANGE_CREATION;
5389 if (!VALID_STAT(smb_fname->st)) {
5390 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5393 /* get some defaults (no modifications) if any info is zero or -1. */
5394 if (null_timespec(ft->create_time)) {
5395 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5398 if (null_timespec(ft->atime)) {
5399 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5402 if (null_timespec(ft->mtime)) {
5403 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5406 if (!setting_write_time) {
5407 /* ft->mtime comes from change time, not write time. */
5408 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5411 /* Ensure the resolution is the correct for
5412 * what we can store on this filesystem. */
5414 round_timespec(conn->ts_res, &ft->create_time);
5415 round_timespec(conn->ts_res, &ft->ctime);
5416 round_timespec(conn->ts_res, &ft->atime);
5417 round_timespec(conn->ts_res, &ft->mtime);
5419 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5420 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5421 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5422 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5423 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5424 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5425 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5426 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5428 if (setting_write_time) {
5430 * This was a Windows setfileinfo on an open file.
5431 * NT does this a lot. We also need to
5432 * set the time here, as it can be read by
5433 * FindFirst/FindNext and with the patch for bug #2045
5434 * in smbd/fileio.c it ensures that this timestamp is
5435 * kept sticky even after a write. We save the request
5436 * away and will set it on file close and after a write. JRA.
5439 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5440 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5442 if (fsp != NULL) {
5443 if (fsp->base_fsp) {
5444 set_sticky_write_time_fsp(fsp->base_fsp,
5445 ft->mtime);
5446 } else {
5447 set_sticky_write_time_fsp(fsp, ft->mtime);
5449 } else {
5450 set_sticky_write_time_path(
5451 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5452 ft->mtime);
5456 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5458 /* Always call ntimes on the base, even if a stream was passed in. */
5459 smb_fname_base = *smb_fname;
5460 smb_fname_base.stream_name = NULL;
5462 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5463 return map_nt_error_from_unix(errno);
5466 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5467 smb_fname->base_name);
5468 return NT_STATUS_OK;
5471 /****************************************************************************
5472 Deal with setting the dosmode from any of the setfilepathinfo functions.
5473 ****************************************************************************/
5475 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5476 const struct smb_filename *smb_fname,
5477 uint32 dosmode)
5479 struct smb_filename *smb_fname_base = NULL;
5480 NTSTATUS status;
5482 if (!VALID_STAT(smb_fname->st)) {
5483 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5486 /* Always operate on the base_name, even if a stream was passed in. */
5487 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5488 NULL, &smb_fname->st,
5489 &smb_fname_base);
5490 if (!NT_STATUS_IS_OK(status)) {
5491 return status;
5494 if (dosmode) {
5495 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5496 dosmode |= aDIR;
5497 } else {
5498 dosmode &= ~aDIR;
5502 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5504 /* check the mode isn't different, before changing it */
5505 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5506 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5507 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5508 (unsigned int)dosmode));
5510 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5511 false)) {
5512 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5513 "%s failed (%s)\n",
5514 smb_fname_str_dbg(smb_fname_base),
5515 strerror(errno)));
5516 status = map_nt_error_from_unix(errno);
5517 goto out;
5520 status = NT_STATUS_OK;
5521 out:
5522 TALLOC_FREE(smb_fname_base);
5523 return status;
5526 /****************************************************************************
5527 Deal with setting the size from any of the setfilepathinfo functions.
5528 ****************************************************************************/
5530 static NTSTATUS smb_set_file_size(connection_struct *conn,
5531 struct smb_request *req,
5532 files_struct *fsp,
5533 const struct smb_filename *smb_fname,
5534 const SMB_STRUCT_STAT *psbuf,
5535 SMB_OFF_T size,
5536 bool fail_after_createfile)
5538 NTSTATUS status = NT_STATUS_OK;
5539 struct smb_filename *smb_fname_tmp = NULL;
5540 files_struct *new_fsp = NULL;
5542 if (!VALID_STAT(*psbuf)) {
5543 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5546 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5548 if (size == get_file_size_stat(psbuf)) {
5549 return NT_STATUS_OK;
5552 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5553 smb_fname_str_dbg(smb_fname), (double)size));
5555 if (fsp && fsp->fh->fd != -1) {
5556 /* Handle based call. */
5557 if (vfs_set_filelen(fsp, size) == -1) {
5558 return map_nt_error_from_unix(errno);
5560 trigger_write_time_update_immediate(fsp);
5561 return NT_STATUS_OK;
5564 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5565 if (!NT_STATUS_IS_OK(status)) {
5566 return status;
5569 smb_fname_tmp->st = *psbuf;
5571 status = SMB_VFS_CREATE_FILE(
5572 conn, /* conn */
5573 req, /* req */
5574 0, /* root_dir_fid */
5575 smb_fname_tmp, /* fname */
5576 FILE_WRITE_DATA, /* access_mask */
5577 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5578 FILE_SHARE_DELETE),
5579 FILE_OPEN, /* create_disposition*/
5580 0, /* create_options */
5581 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5582 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5583 0, /* allocation_size */
5584 NULL, /* sd */
5585 NULL, /* ea_list */
5586 &new_fsp, /* result */
5587 NULL); /* pinfo */
5589 TALLOC_FREE(smb_fname_tmp);
5591 if (!NT_STATUS_IS_OK(status)) {
5592 /* NB. We check for open_was_deferred in the caller. */
5593 return status;
5596 /* See RAW-SFILEINFO-END-OF-FILE */
5597 if (fail_after_createfile) {
5598 close_file(req, new_fsp,NORMAL_CLOSE);
5599 return NT_STATUS_INVALID_LEVEL;
5602 if (vfs_set_filelen(new_fsp, size) == -1) {
5603 status = map_nt_error_from_unix(errno);
5604 close_file(req, new_fsp,NORMAL_CLOSE);
5605 return status;
5608 trigger_write_time_update_immediate(new_fsp);
5609 close_file(req, new_fsp,NORMAL_CLOSE);
5610 return NT_STATUS_OK;
5613 /****************************************************************************
5614 Deal with SMB_INFO_SET_EA.
5615 ****************************************************************************/
5617 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5618 const char *pdata,
5619 int total_data,
5620 files_struct *fsp,
5621 const struct smb_filename *smb_fname)
5623 struct ea_list *ea_list = NULL;
5624 TALLOC_CTX *ctx = NULL;
5625 NTSTATUS status = NT_STATUS_OK;
5627 if (total_data < 10) {
5629 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5630 length. They seem to have no effect. Bug #3212. JRA */
5632 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5633 /* We're done. We only get EA info in this call. */
5634 return NT_STATUS_OK;
5637 return NT_STATUS_INVALID_PARAMETER;
5640 if (IVAL(pdata,0) > total_data) {
5641 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5642 IVAL(pdata,0), (unsigned int)total_data));
5643 return NT_STATUS_INVALID_PARAMETER;
5646 ctx = talloc_tos();
5647 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5648 if (!ea_list) {
5649 return NT_STATUS_INVALID_PARAMETER;
5651 status = set_ea(conn, fsp, smb_fname, ea_list);
5653 return status;
5656 /****************************************************************************
5657 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5658 ****************************************************************************/
5660 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5661 const char *pdata,
5662 int total_data,
5663 files_struct *fsp)
5665 struct ea_list *ea_list = NULL;
5666 NTSTATUS status;
5668 if (!fsp) {
5669 return NT_STATUS_INVALID_HANDLE;
5672 if (!lp_ea_support(SNUM(conn))) {
5673 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5674 "EA's not supported.\n",
5675 (unsigned int)total_data));
5676 return NT_STATUS_EAS_NOT_SUPPORTED;
5679 if (total_data < 10) {
5680 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5681 "too small.\n",
5682 (unsigned int)total_data));
5683 return NT_STATUS_INVALID_PARAMETER;
5686 ea_list = read_nttrans_ea_list(talloc_tos(),
5687 pdata,
5688 total_data);
5690 if (!ea_list) {
5691 return NT_STATUS_INVALID_PARAMETER;
5693 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5695 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5696 smb_fname_str_dbg(fsp->fsp_name),
5697 nt_errstr(status) ));
5699 return status;
5703 /****************************************************************************
5704 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5705 ****************************************************************************/
5707 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5708 const char *pdata,
5709 int total_data,
5710 files_struct *fsp,
5711 struct smb_filename *smb_fname)
5713 NTSTATUS status = NT_STATUS_OK;
5714 bool delete_on_close;
5715 uint32 dosmode = 0;
5717 if (total_data < 1) {
5718 return NT_STATUS_INVALID_PARAMETER;
5721 if (fsp == NULL) {
5722 return NT_STATUS_INVALID_HANDLE;
5725 delete_on_close = (CVAL(pdata,0) ? True : False);
5726 dosmode = dos_mode(conn, smb_fname);
5728 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5729 "delete_on_close = %u\n",
5730 smb_fname_str_dbg(smb_fname),
5731 (unsigned int)dosmode,
5732 (unsigned int)delete_on_close ));
5734 if (delete_on_close) {
5735 status = can_set_delete_on_close(fsp, dosmode);
5736 if (!NT_STATUS_IS_OK(status)) {
5737 return status;
5741 /* The set is across all open files on this dev/inode pair. */
5742 if (!set_delete_on_close(fsp, delete_on_close,
5743 &conn->server_info->utok)) {
5744 return NT_STATUS_ACCESS_DENIED;
5746 return NT_STATUS_OK;
5749 /****************************************************************************
5750 Deal with SMB_FILE_POSITION_INFORMATION.
5751 ****************************************************************************/
5753 static NTSTATUS smb_file_position_information(connection_struct *conn,
5754 const char *pdata,
5755 int total_data,
5756 files_struct *fsp)
5758 uint64_t position_information;
5760 if (total_data < 8) {
5761 return NT_STATUS_INVALID_PARAMETER;
5764 if (fsp == NULL) {
5765 /* Ignore on pathname based set. */
5766 return NT_STATUS_OK;
5769 position_information = (uint64_t)IVAL(pdata,0);
5770 #ifdef LARGE_SMB_OFF_T
5771 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5772 #else /* LARGE_SMB_OFF_T */
5773 if (IVAL(pdata,4) != 0) {
5774 /* more than 32 bits? */
5775 return NT_STATUS_INVALID_PARAMETER;
5777 #endif /* LARGE_SMB_OFF_T */
5779 DEBUG(10,("smb_file_position_information: Set file position "
5780 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5781 (double)position_information));
5782 fsp->fh->position_information = position_information;
5783 return NT_STATUS_OK;
5786 /****************************************************************************
5787 Deal with SMB_FILE_MODE_INFORMATION.
5788 ****************************************************************************/
5790 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5791 const char *pdata,
5792 int total_data)
5794 uint32 mode;
5796 if (total_data < 4) {
5797 return NT_STATUS_INVALID_PARAMETER;
5799 mode = IVAL(pdata,0);
5800 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5801 return NT_STATUS_INVALID_PARAMETER;
5803 return NT_STATUS_OK;
5806 /****************************************************************************
5807 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5808 ****************************************************************************/
5810 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5811 struct smb_request *req,
5812 const char *pdata,
5813 int total_data,
5814 const struct smb_filename *smb_fname)
5816 char *link_target = NULL;
5817 const char *newname = smb_fname->base_name;
5818 TALLOC_CTX *ctx = talloc_tos();
5820 /* Set a symbolic link. */
5821 /* Don't allow this if follow links is false. */
5823 if (total_data == 0) {
5824 return NT_STATUS_INVALID_PARAMETER;
5827 if (!lp_symlinks(SNUM(conn))) {
5828 return NT_STATUS_ACCESS_DENIED;
5831 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5832 total_data, STR_TERMINATE);
5834 if (!link_target) {
5835 return NT_STATUS_INVALID_PARAMETER;
5838 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5839 newname, link_target ));
5841 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5842 return map_nt_error_from_unix(errno);
5845 return NT_STATUS_OK;
5848 /****************************************************************************
5849 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5850 ****************************************************************************/
5852 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5853 struct smb_request *req,
5854 const char *pdata, int total_data,
5855 const struct smb_filename *smb_fname_new)
5857 char *oldname = NULL;
5858 struct smb_filename *smb_fname_old = NULL;
5859 TALLOC_CTX *ctx = talloc_tos();
5860 NTSTATUS status = NT_STATUS_OK;
5862 /* Set a hard link. */
5863 if (total_data == 0) {
5864 return NT_STATUS_INVALID_PARAMETER;
5867 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5868 total_data, STR_TERMINATE, &status);
5869 if (!NT_STATUS_IS_OK(status)) {
5870 return status;
5873 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5874 smb_fname_str_dbg(smb_fname_new), oldname));
5876 status = filename_convert(ctx,
5877 conn,
5878 req->flags2 & FLAGS2_DFS_PATHNAMES,
5879 oldname,
5881 NULL,
5882 &smb_fname_old);
5883 if (!NT_STATUS_IS_OK(status)) {
5884 return status;
5887 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5890 /****************************************************************************
5891 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5892 ****************************************************************************/
5894 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5895 struct smb_request *req,
5896 const char *pdata,
5897 int total_data,
5898 files_struct *fsp,
5899 struct smb_filename *smb_fname_src)
5901 bool overwrite;
5902 uint32_t len;
5903 char *newname = NULL;
5904 struct smb_filename *smb_fname_dst = NULL;
5905 NTSTATUS status = NT_STATUS_OK;
5906 TALLOC_CTX *ctx = talloc_tos();
5908 if (!fsp) {
5909 return NT_STATUS_INVALID_HANDLE;
5912 if (total_data < 20) {
5913 return NT_STATUS_INVALID_PARAMETER;
5916 overwrite = (CVAL(pdata,0) ? True : False);
5917 len = IVAL(pdata,16);
5919 if (len > (total_data - 20) || (len == 0)) {
5920 return NT_STATUS_INVALID_PARAMETER;
5923 srvstr_get_path(ctx, pdata, req->flags2, &newname,
5924 &pdata[20], len, STR_TERMINATE,
5925 &status);
5926 if (!NT_STATUS_IS_OK(status)) {
5927 return status;
5930 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5931 newname));
5933 #if 0
5934 /* Check the new name has no '/' characters. */
5935 if (strchr_m(newname, '/')) {
5936 return NT_STATUS_NOT_SUPPORTED;
5938 #endif
5940 status = filename_convert(ctx,
5941 conn,
5942 req->flags2 & FLAGS2_DFS_PATHNAMES,
5943 newname,
5945 NULL,
5946 &smb_fname_dst);
5947 if (!NT_STATUS_IS_OK(status)) {
5948 return status;
5951 if (fsp && fsp->base_fsp) {
5952 /* newname must be a stream name. */
5953 if (newname[0] != ':') {
5954 return NT_STATUS_NOT_SUPPORTED;
5957 /* Create an smb_fname to call rename_internals_fsp() with. */
5958 status = create_synthetic_smb_fname(talloc_tos(),
5959 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5960 &smb_fname_dst);
5961 if (!NT_STATUS_IS_OK(status)) {
5962 goto out;
5966 * Set the original last component, since
5967 * rename_internals_fsp() requires it.
5969 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5970 newname);
5971 if (smb_fname_dst->original_lcomp == NULL) {
5972 status = NT_STATUS_NO_MEMORY;
5973 goto out;
5978 DEBUG(10,("smb_file_rename_information: "
5979 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5980 fsp->fnum, fsp_str_dbg(fsp),
5981 smb_fname_str_dbg(smb_fname_dst)));
5982 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
5983 overwrite);
5985 out:
5986 TALLOC_FREE(smb_fname_dst);
5987 return status;
5991 /****************************************************************************
5992 Deal with SMB_FILE_RENAME_INFORMATION.
5993 ****************************************************************************/
5995 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5996 struct smb_request *req,
5997 const char *pdata,
5998 int total_data,
5999 files_struct *fsp,
6000 struct smb_filename *smb_fname_src)
6002 bool overwrite;
6003 uint32 root_fid;
6004 uint32 len;
6005 char *newname = NULL;
6006 struct smb_filename *smb_fname_dst = NULL;
6007 bool dest_has_wcard = False;
6008 NTSTATUS status = NT_STATUS_OK;
6009 char *p;
6010 TALLOC_CTX *ctx = talloc_tos();
6012 if (total_data < 13) {
6013 return NT_STATUS_INVALID_PARAMETER;
6016 overwrite = (CVAL(pdata,0) ? True : False);
6017 root_fid = IVAL(pdata,4);
6018 len = IVAL(pdata,8);
6020 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6021 return NT_STATUS_INVALID_PARAMETER;
6024 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6025 len, 0, &status,
6026 &dest_has_wcard);
6027 if (!NT_STATUS_IS_OK(status)) {
6028 return status;
6031 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6032 newname));
6034 status = resolve_dfspath_wcard(ctx, conn,
6035 req->flags2 & FLAGS2_DFS_PATHNAMES,
6036 newname,
6037 &newname,
6038 &dest_has_wcard);
6039 if (!NT_STATUS_IS_OK(status)) {
6040 return status;
6043 /* Check the new name has no '/' characters. */
6044 if (strchr_m(newname, '/')) {
6045 return NT_STATUS_NOT_SUPPORTED;
6048 if (fsp && fsp->base_fsp) {
6049 /* newname must be a stream name. */
6050 if (newname[0] != ':') {
6051 return NT_STATUS_NOT_SUPPORTED;
6054 /* Create an smb_fname to call rename_internals_fsp() with. */
6055 status = create_synthetic_smb_fname(talloc_tos(),
6056 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6057 &smb_fname_dst);
6058 if (!NT_STATUS_IS_OK(status)) {
6059 goto out;
6063 * Set the original last component, since
6064 * rename_internals_fsp() requires it.
6066 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6067 newname);
6068 if (smb_fname_dst->original_lcomp == NULL) {
6069 status = NT_STATUS_NO_MEMORY;
6070 goto out;
6073 } else {
6075 * Build up an smb_fname_dst based on the filename passed in.
6076 * We basically just strip off the last component, and put on
6077 * the newname instead.
6079 char *base_name = NULL;
6081 /* newname must *not* be a stream name. */
6082 if (newname[0] == ':') {
6083 return NT_STATUS_NOT_SUPPORTED;
6087 * Strip off the last component (filename) of the path passed
6088 * in.
6090 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6091 if (!base_name) {
6092 return NT_STATUS_NO_MEMORY;
6094 p = strrchr_m(base_name, '/');
6095 if (p) {
6096 p[1] = '\0';
6097 } else {
6098 base_name = talloc_strdup(ctx, "./");
6099 if (!base_name) {
6100 return NT_STATUS_NO_MEMORY;
6103 /* Append the new name. */
6104 base_name = talloc_asprintf_append(base_name,
6105 "%s",
6106 newname);
6107 if (!base_name) {
6108 return NT_STATUS_NO_MEMORY;
6111 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6112 (UCF_SAVE_LCOMP |
6113 (dest_has_wcard ?
6114 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6115 0)));
6117 /* If an error we expect this to be
6118 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6120 if (!NT_STATUS_IS_OK(status)) {
6121 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6122 status)) {
6123 goto out;
6125 /* Create an smb_fname to call rename_internals_fsp() */
6126 status = create_synthetic_smb_fname(ctx,
6127 base_name, NULL,
6128 NULL,
6129 &smb_fname_dst);
6130 if (!NT_STATUS_IS_OK(status)) {
6131 goto out;
6136 if (fsp) {
6137 DEBUG(10,("smb_file_rename_information: "
6138 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6139 fsp->fnum, fsp_str_dbg(fsp),
6140 smb_fname_str_dbg(smb_fname_dst)));
6141 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6142 overwrite);
6143 } else {
6144 DEBUG(10,("smb_file_rename_information: "
6145 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6146 smb_fname_str_dbg(smb_fname_src),
6147 smb_fname_str_dbg(smb_fname_dst)));
6148 status = rename_internals(ctx, conn, req, smb_fname_src,
6149 smb_fname_dst, 0, overwrite, false,
6150 dest_has_wcard,
6151 FILE_WRITE_ATTRIBUTES);
6153 out:
6154 TALLOC_FREE(smb_fname_dst);
6155 return status;
6158 /****************************************************************************
6159 Deal with SMB_SET_POSIX_ACL.
6160 ****************************************************************************/
6162 #if defined(HAVE_POSIX_ACLS)
6163 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6164 const char *pdata,
6165 int total_data,
6166 files_struct *fsp,
6167 const struct smb_filename *smb_fname)
6169 uint16 posix_acl_version;
6170 uint16 num_file_acls;
6171 uint16 num_def_acls;
6172 bool valid_file_acls = True;
6173 bool valid_def_acls = True;
6175 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6176 return NT_STATUS_INVALID_PARAMETER;
6178 posix_acl_version = SVAL(pdata,0);
6179 num_file_acls = SVAL(pdata,2);
6180 num_def_acls = SVAL(pdata,4);
6182 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6183 valid_file_acls = False;
6184 num_file_acls = 0;
6187 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6188 valid_def_acls = False;
6189 num_def_acls = 0;
6192 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6193 return NT_STATUS_INVALID_PARAMETER;
6196 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6197 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6198 return NT_STATUS_INVALID_PARAMETER;
6201 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6202 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6203 (unsigned int)num_file_acls,
6204 (unsigned int)num_def_acls));
6206 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6207 smb_fname->base_name, num_file_acls,
6208 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6209 return map_nt_error_from_unix(errno);
6212 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6213 smb_fname->base_name, &smb_fname->st, num_def_acls,
6214 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6215 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6216 return map_nt_error_from_unix(errno);
6218 return NT_STATUS_OK;
6220 #endif
6222 /****************************************************************************
6223 Deal with SMB_SET_POSIX_LOCK.
6224 ****************************************************************************/
6226 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6227 struct smb_request *req,
6228 const char *pdata,
6229 int total_data,
6230 files_struct *fsp)
6232 uint64_t count;
6233 uint64_t offset;
6234 uint32 lock_pid;
6235 bool blocking_lock = False;
6236 enum brl_type lock_type;
6238 NTSTATUS status = NT_STATUS_OK;
6240 if (fsp == NULL || fsp->fh->fd == -1) {
6241 return NT_STATUS_INVALID_HANDLE;
6244 if (total_data != POSIX_LOCK_DATA_SIZE) {
6245 return NT_STATUS_INVALID_PARAMETER;
6248 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6249 case POSIX_LOCK_TYPE_READ:
6250 lock_type = READ_LOCK;
6251 break;
6252 case POSIX_LOCK_TYPE_WRITE:
6253 /* Return the right POSIX-mappable error code for files opened read-only. */
6254 if (!fsp->can_write) {
6255 return NT_STATUS_INVALID_HANDLE;
6257 lock_type = WRITE_LOCK;
6258 break;
6259 case POSIX_LOCK_TYPE_UNLOCK:
6260 lock_type = UNLOCK_LOCK;
6261 break;
6262 default:
6263 return NT_STATUS_INVALID_PARAMETER;
6266 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6267 blocking_lock = False;
6268 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6269 blocking_lock = True;
6270 } else {
6271 return NT_STATUS_INVALID_PARAMETER;
6274 if (!lp_blocking_locks(SNUM(conn))) {
6275 blocking_lock = False;
6278 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6279 #if defined(HAVE_LONGLONG)
6280 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6281 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6282 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6283 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6284 #else /* HAVE_LONGLONG */
6285 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6286 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6287 #endif /* HAVE_LONGLONG */
6289 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6290 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6291 fsp_str_dbg(fsp),
6292 (unsigned int)lock_type,
6293 (unsigned int)lock_pid,
6294 (double)count,
6295 (double)offset ));
6297 if (lock_type == UNLOCK_LOCK) {
6298 status = do_unlock(smbd_messaging_context(),
6299 fsp,
6300 lock_pid,
6301 count,
6302 offset,
6303 POSIX_LOCK);
6304 } else {
6305 uint32 block_smbpid;
6307 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6308 fsp,
6309 lock_pid,
6310 count,
6311 offset,
6312 lock_type,
6313 POSIX_LOCK,
6314 blocking_lock,
6315 &status,
6316 &block_smbpid,
6317 NULL);
6319 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6321 * A blocking lock was requested. Package up
6322 * this smb into a queued request and push it
6323 * onto the blocking lock queue.
6325 if(push_blocking_lock_request(br_lck,
6326 req,
6327 fsp,
6328 -1, /* infinite timeout. */
6330 lock_pid,
6331 lock_type,
6332 POSIX_LOCK,
6333 offset,
6334 count,
6335 block_smbpid)) {
6336 TALLOC_FREE(br_lck);
6337 return status;
6340 TALLOC_FREE(br_lck);
6343 return status;
6346 /****************************************************************************
6347 Deal with SMB_SET_FILE_BASIC_INFO.
6348 ****************************************************************************/
6350 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6351 const char *pdata,
6352 int total_data,
6353 files_struct *fsp,
6354 const struct smb_filename *smb_fname)
6356 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6357 struct smb_file_time ft;
6358 uint32 dosmode = 0;
6359 NTSTATUS status = NT_STATUS_OK;
6361 ZERO_STRUCT(ft);
6363 if (total_data < 36) {
6364 return NT_STATUS_INVALID_PARAMETER;
6367 /* Set the attributes */
6368 dosmode = IVAL(pdata,32);
6369 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6370 if (!NT_STATUS_IS_OK(status)) {
6371 return status;
6374 /* create time */
6375 ft.create_time = interpret_long_date(pdata);
6377 /* access time */
6378 ft.atime = interpret_long_date(pdata+8);
6380 /* write time. */
6381 ft.mtime = interpret_long_date(pdata+16);
6383 /* change time. */
6384 ft.ctime = interpret_long_date(pdata+24);
6386 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6387 smb_fname_str_dbg(smb_fname)));
6389 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6390 true);
6393 /****************************************************************************
6394 Deal with SMB_INFO_STANDARD.
6395 ****************************************************************************/
6397 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6398 const char *pdata,
6399 int total_data,
6400 files_struct *fsp,
6401 const struct smb_filename *smb_fname)
6403 struct smb_file_time ft;
6405 ZERO_STRUCT(ft);
6407 if (total_data < 12) {
6408 return NT_STATUS_INVALID_PARAMETER;
6411 /* create time */
6412 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6413 /* access time */
6414 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6415 /* write time */
6416 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6418 DEBUG(10,("smb_set_info_standard: file %s\n",
6419 smb_fname_str_dbg(smb_fname)));
6421 return smb_set_file_time(conn,
6422 fsp,
6423 smb_fname,
6424 &ft,
6425 true);
6428 /****************************************************************************
6429 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6430 ****************************************************************************/
6432 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6433 struct smb_request *req,
6434 const char *pdata,
6435 int total_data,
6436 files_struct *fsp,
6437 struct smb_filename *smb_fname)
6439 uint64_t allocation_size = 0;
6440 NTSTATUS status = NT_STATUS_OK;
6441 files_struct *new_fsp = NULL;
6443 if (!VALID_STAT(smb_fname->st)) {
6444 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6447 if (total_data < 8) {
6448 return NT_STATUS_INVALID_PARAMETER;
6451 allocation_size = (uint64_t)IVAL(pdata,0);
6452 #ifdef LARGE_SMB_OFF_T
6453 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6454 #else /* LARGE_SMB_OFF_T */
6455 if (IVAL(pdata,4) != 0) {
6456 /* more than 32 bits? */
6457 return NT_STATUS_INVALID_PARAMETER;
6459 #endif /* LARGE_SMB_OFF_T */
6461 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6462 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6463 (double)allocation_size));
6465 if (allocation_size) {
6466 allocation_size = smb_roundup(conn, allocation_size);
6469 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6470 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6471 (double)allocation_size));
6473 if (fsp && fsp->fh->fd != -1) {
6474 /* Open file handle. */
6475 /* Only change if needed. */
6476 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6477 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6478 return map_nt_error_from_unix(errno);
6481 /* But always update the time. */
6483 * This is equivalent to a write. Ensure it's seen immediately
6484 * if there are no pending writes.
6486 trigger_write_time_update_immediate(fsp);
6487 return NT_STATUS_OK;
6490 /* Pathname or stat or directory file. */
6491 status = SMB_VFS_CREATE_FILE(
6492 conn, /* conn */
6493 req, /* req */
6494 0, /* root_dir_fid */
6495 smb_fname, /* fname */
6496 FILE_WRITE_DATA, /* access_mask */
6497 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6498 FILE_SHARE_DELETE),
6499 FILE_OPEN, /* create_disposition*/
6500 0, /* create_options */
6501 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6502 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6503 0, /* allocation_size */
6504 NULL, /* sd */
6505 NULL, /* ea_list */
6506 &new_fsp, /* result */
6507 NULL); /* pinfo */
6509 if (!NT_STATUS_IS_OK(status)) {
6510 /* NB. We check for open_was_deferred in the caller. */
6511 return status;
6514 /* Only change if needed. */
6515 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6516 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6517 status = map_nt_error_from_unix(errno);
6518 close_file(req, new_fsp, NORMAL_CLOSE);
6519 return status;
6523 /* Changing the allocation size should set the last mod time. */
6525 * This is equivalent to a write. Ensure it's seen immediately
6526 * if there are no pending writes.
6528 trigger_write_time_update_immediate(new_fsp);
6530 close_file(req, new_fsp, NORMAL_CLOSE);
6531 return NT_STATUS_OK;
6534 /****************************************************************************
6535 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6536 ****************************************************************************/
6538 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6539 struct smb_request *req,
6540 const char *pdata,
6541 int total_data,
6542 files_struct *fsp,
6543 const struct smb_filename *smb_fname,
6544 bool fail_after_createfile)
6546 SMB_OFF_T size;
6548 if (total_data < 8) {
6549 return NT_STATUS_INVALID_PARAMETER;
6552 size = IVAL(pdata,0);
6553 #ifdef LARGE_SMB_OFF_T
6554 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6555 #else /* LARGE_SMB_OFF_T */
6556 if (IVAL(pdata,4) != 0) {
6557 /* more than 32 bits? */
6558 return NT_STATUS_INVALID_PARAMETER;
6560 #endif /* LARGE_SMB_OFF_T */
6561 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6562 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6563 (double)size));
6565 return smb_set_file_size(conn, req,
6566 fsp,
6567 smb_fname,
6568 &smb_fname->st,
6569 size,
6570 fail_after_createfile);
6573 /****************************************************************************
6574 Allow a UNIX info mknod.
6575 ****************************************************************************/
6577 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6578 const char *pdata,
6579 int total_data,
6580 const struct smb_filename *smb_fname)
6582 uint32 file_type = IVAL(pdata,56);
6583 #if defined(HAVE_MAKEDEV)
6584 uint32 dev_major = IVAL(pdata,60);
6585 uint32 dev_minor = IVAL(pdata,68);
6586 #endif
6587 SMB_DEV_T dev = (SMB_DEV_T)0;
6588 uint32 raw_unixmode = IVAL(pdata,84);
6589 NTSTATUS status;
6590 mode_t unixmode;
6592 if (total_data < 100) {
6593 return NT_STATUS_INVALID_PARAMETER;
6596 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6597 PERM_NEW_FILE, &unixmode);
6598 if (!NT_STATUS_IS_OK(status)) {
6599 return status;
6602 #if defined(HAVE_MAKEDEV)
6603 dev = makedev(dev_major, dev_minor);
6604 #endif
6606 switch (file_type) {
6607 #if defined(S_IFIFO)
6608 case UNIX_TYPE_FIFO:
6609 unixmode |= S_IFIFO;
6610 break;
6611 #endif
6612 #if defined(S_IFSOCK)
6613 case UNIX_TYPE_SOCKET:
6614 unixmode |= S_IFSOCK;
6615 break;
6616 #endif
6617 #if defined(S_IFCHR)
6618 case UNIX_TYPE_CHARDEV:
6619 unixmode |= S_IFCHR;
6620 break;
6621 #endif
6622 #if defined(S_IFBLK)
6623 case UNIX_TYPE_BLKDEV:
6624 unixmode |= S_IFBLK;
6625 break;
6626 #endif
6627 default:
6628 return NT_STATUS_INVALID_PARAMETER;
6631 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6632 "%.0f mode 0%o for file %s\n", (double)dev,
6633 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6635 /* Ok - do the mknod. */
6636 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6637 return map_nt_error_from_unix(errno);
6640 /* If any of the other "set" calls fail we
6641 * don't want to end up with a half-constructed mknod.
6644 if (lp_inherit_perms(SNUM(conn))) {
6645 char *parent;
6646 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6647 &parent, NULL)) {
6648 return NT_STATUS_NO_MEMORY;
6650 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6651 unixmode);
6652 TALLOC_FREE(parent);
6655 return NT_STATUS_OK;
6658 /****************************************************************************
6659 Deal with SMB_SET_FILE_UNIX_BASIC.
6660 ****************************************************************************/
6662 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6663 struct smb_request *req,
6664 const char *pdata,
6665 int total_data,
6666 files_struct *fsp,
6667 const struct smb_filename *smb_fname)
6669 struct smb_file_time ft;
6670 uint32 raw_unixmode;
6671 mode_t unixmode;
6672 SMB_OFF_T size = 0;
6673 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6674 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6675 NTSTATUS status = NT_STATUS_OK;
6676 bool delete_on_fail = False;
6677 enum perm_type ptype;
6678 files_struct *all_fsps = NULL;
6679 bool modify_mtime = true;
6680 struct file_id id;
6681 SMB_STRUCT_STAT sbuf;
6683 ZERO_STRUCT(ft);
6685 if (total_data < 100) {
6686 return NT_STATUS_INVALID_PARAMETER;
6689 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6690 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6691 size=IVAL(pdata,0); /* first 8 Bytes are size */
6692 #ifdef LARGE_SMB_OFF_T
6693 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6694 #else /* LARGE_SMB_OFF_T */
6695 if (IVAL(pdata,4) != 0) {
6696 /* more than 32 bits? */
6697 return NT_STATUS_INVALID_PARAMETER;
6699 #endif /* LARGE_SMB_OFF_T */
6702 ft.atime = interpret_long_date(pdata+24); /* access_time */
6703 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6704 set_owner = (uid_t)IVAL(pdata,40);
6705 set_grp = (gid_t)IVAL(pdata,48);
6706 raw_unixmode = IVAL(pdata,84);
6708 if (VALID_STAT(smb_fname->st)) {
6709 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6710 ptype = PERM_EXISTING_DIR;
6711 } else {
6712 ptype = PERM_EXISTING_FILE;
6714 } else {
6715 ptype = PERM_NEW_FILE;
6718 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6719 ptype, &unixmode);
6720 if (!NT_STATUS_IS_OK(status)) {
6721 return status;
6724 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6725 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6726 smb_fname_str_dbg(smb_fname), (double)size,
6727 (unsigned int)set_owner, (unsigned int)set_grp,
6728 (int)raw_unixmode));
6730 sbuf = smb_fname->st;
6732 if (!VALID_STAT(sbuf)) {
6733 struct smb_filename *smb_fname_tmp = NULL;
6735 * The only valid use of this is to create character and block
6736 * devices, and named pipes. This is deprecated (IMHO) and
6737 * a new info level should be used for mknod. JRA.
6740 status = smb_unix_mknod(conn,
6741 pdata,
6742 total_data,
6743 smb_fname);
6744 if (!NT_STATUS_IS_OK(status)) {
6745 return status;
6748 status = copy_smb_filename(talloc_tos(), smb_fname,
6749 &smb_fname_tmp);
6750 if (!NT_STATUS_IS_OK(status)) {
6751 return status;
6754 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6755 status = map_nt_error_from_unix(errno);
6756 TALLOC_FREE(smb_fname_tmp);
6757 SMB_VFS_UNLINK(conn, smb_fname);
6758 return status;
6761 sbuf = smb_fname_tmp->st;
6762 TALLOC_FREE(smb_fname_tmp);
6764 /* Ensure we don't try and change anything else. */
6765 raw_unixmode = SMB_MODE_NO_CHANGE;
6766 size = get_file_size_stat(&sbuf);
6767 ft.atime = sbuf.st_ex_atime;
6768 ft.mtime = sbuf.st_ex_mtime;
6770 * We continue here as we might want to change the
6771 * owner uid/gid.
6773 delete_on_fail = True;
6776 #if 1
6777 /* Horrible backwards compatibility hack as an old server bug
6778 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6779 * */
6781 if (!size) {
6782 size = get_file_size_stat(&sbuf);
6784 #endif
6787 * Deal with the UNIX specific mode set.
6790 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6791 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6792 "setting mode 0%o for file %s\n",
6793 (unsigned int)unixmode,
6794 smb_fname_str_dbg(smb_fname)));
6795 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6796 return map_nt_error_from_unix(errno);
6801 * Deal with the UNIX specific uid set.
6804 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6805 (sbuf.st_ex_uid != set_owner)) {
6806 int ret;
6808 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6809 "changing owner %u for path %s\n",
6810 (unsigned int)set_owner,
6811 smb_fname_str_dbg(smb_fname)));
6813 if (S_ISLNK(sbuf.st_ex_mode)) {
6814 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6815 set_owner, (gid_t)-1);
6816 } else {
6817 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6818 set_owner, (gid_t)-1);
6821 if (ret != 0) {
6822 status = map_nt_error_from_unix(errno);
6823 if (delete_on_fail) {
6824 SMB_VFS_UNLINK(conn, smb_fname);
6826 return status;
6831 * Deal with the UNIX specific gid set.
6834 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6835 (sbuf.st_ex_gid != set_grp)) {
6836 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6837 "changing group %u for file %s\n",
6838 (unsigned int)set_owner,
6839 smb_fname_str_dbg(smb_fname)));
6840 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6841 set_grp) != 0) {
6842 status = map_nt_error_from_unix(errno);
6843 if (delete_on_fail) {
6844 SMB_VFS_UNLINK(conn, smb_fname);
6846 return status;
6850 /* Deal with any size changes. */
6852 status = smb_set_file_size(conn, req,
6853 fsp,
6854 smb_fname,
6855 &sbuf,
6856 size,
6857 false);
6858 if (!NT_STATUS_IS_OK(status)) {
6859 return status;
6862 /* Deal with any time changes. */
6863 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6864 /* No change, don't cancel anything. */
6865 return status;
6868 id = vfs_file_id_from_sbuf(conn, &sbuf);
6869 for(all_fsps = file_find_di_first(id); all_fsps;
6870 all_fsps = file_find_di_next(all_fsps)) {
6872 * We're setting the time explicitly for UNIX.
6873 * Cancel any pending changes over all handles.
6875 all_fsps->update_write_time_on_close = false;
6876 TALLOC_FREE(all_fsps->update_write_time_event);
6880 * Override the "setting_write_time"
6881 * parameter here as it almost does what
6882 * we need. Just remember if we modified
6883 * mtime and send the notify ourselves.
6885 if (null_timespec(ft.mtime)) {
6886 modify_mtime = false;
6889 status = smb_set_file_time(conn,
6890 fsp,
6891 smb_fname,
6892 &ft,
6893 false);
6894 if (modify_mtime) {
6895 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6896 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6898 return status;
6901 /****************************************************************************
6902 Deal with SMB_SET_FILE_UNIX_INFO2.
6903 ****************************************************************************/
6905 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6906 struct smb_request *req,
6907 const char *pdata,
6908 int total_data,
6909 files_struct *fsp,
6910 const struct smb_filename *smb_fname)
6912 NTSTATUS status;
6913 uint32 smb_fflags;
6914 uint32 smb_fmask;
6916 if (total_data < 116) {
6917 return NT_STATUS_INVALID_PARAMETER;
6920 /* Start by setting all the fields that are common between UNIX_BASIC
6921 * and UNIX_INFO2.
6923 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6924 fsp, smb_fname);
6925 if (!NT_STATUS_IS_OK(status)) {
6926 return status;
6929 smb_fflags = IVAL(pdata, 108);
6930 smb_fmask = IVAL(pdata, 112);
6932 /* NB: We should only attempt to alter the file flags if the client
6933 * sends a non-zero mask.
6935 if (smb_fmask != 0) {
6936 int stat_fflags = 0;
6938 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6939 smb_fmask, &stat_fflags)) {
6940 /* Client asked to alter a flag we don't understand. */
6941 return NT_STATUS_INVALID_PARAMETER;
6944 if (fsp && fsp->fh->fd != -1) {
6945 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6946 return NT_STATUS_NOT_SUPPORTED;
6947 } else {
6948 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6949 stat_fflags) != 0) {
6950 return map_nt_error_from_unix(errno);
6955 /* XXX: need to add support for changing the create_time here. You
6956 * can do this for paths on Darwin with setattrlist(2). The right way
6957 * to hook this up is probably by extending the VFS utimes interface.
6960 return NT_STATUS_OK;
6963 /****************************************************************************
6964 Create a directory with POSIX semantics.
6965 ****************************************************************************/
6967 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6968 struct smb_request *req,
6969 char **ppdata,
6970 int total_data,
6971 struct smb_filename *smb_fname,
6972 int *pdata_return_size)
6974 NTSTATUS status = NT_STATUS_OK;
6975 uint32 raw_unixmode = 0;
6976 uint32 mod_unixmode = 0;
6977 mode_t unixmode = (mode_t)0;
6978 files_struct *fsp = NULL;
6979 uint16 info_level_return = 0;
6980 int info;
6981 char *pdata = *ppdata;
6983 if (total_data < 18) {
6984 return NT_STATUS_INVALID_PARAMETER;
6987 raw_unixmode = IVAL(pdata,8);
6988 /* Next 4 bytes are not yet defined. */
6990 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6991 PERM_NEW_DIR, &unixmode);
6992 if (!NT_STATUS_IS_OK(status)) {
6993 return status;
6996 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6998 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6999 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7001 status = SMB_VFS_CREATE_FILE(
7002 conn, /* conn */
7003 req, /* req */
7004 0, /* root_dir_fid */
7005 smb_fname, /* fname */
7006 FILE_READ_ATTRIBUTES, /* access_mask */
7007 FILE_SHARE_NONE, /* share_access */
7008 FILE_CREATE, /* create_disposition*/
7009 FILE_DIRECTORY_FILE, /* create_options */
7010 mod_unixmode, /* file_attributes */
7011 0, /* oplock_request */
7012 0, /* allocation_size */
7013 NULL, /* sd */
7014 NULL, /* ea_list */
7015 &fsp, /* result */
7016 &info); /* pinfo */
7018 if (NT_STATUS_IS_OK(status)) {
7019 close_file(req, fsp, NORMAL_CLOSE);
7022 info_level_return = SVAL(pdata,16);
7024 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7025 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7026 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7027 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7028 } else {
7029 *pdata_return_size = 12;
7032 /* Realloc the data size */
7033 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7034 if (*ppdata == NULL) {
7035 *pdata_return_size = 0;
7036 return NT_STATUS_NO_MEMORY;
7038 pdata = *ppdata;
7040 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7041 SSVAL(pdata,2,0); /* No fnum. */
7042 SIVAL(pdata,4,info); /* Was directory created. */
7044 switch (info_level_return) {
7045 case SMB_QUERY_FILE_UNIX_BASIC:
7046 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7047 SSVAL(pdata,10,0); /* Padding. */
7048 store_file_unix_basic(conn, pdata + 12, fsp,
7049 &smb_fname->st);
7050 break;
7051 case SMB_QUERY_FILE_UNIX_INFO2:
7052 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7053 SSVAL(pdata,10,0); /* Padding. */
7054 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7055 &smb_fname->st);
7056 break;
7057 default:
7058 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7059 SSVAL(pdata,10,0); /* Padding. */
7060 break;
7063 return status;
7066 /****************************************************************************
7067 Open/Create a file with POSIX semantics.
7068 ****************************************************************************/
7070 static NTSTATUS smb_posix_open(connection_struct *conn,
7071 struct smb_request *req,
7072 char **ppdata,
7073 int total_data,
7074 struct smb_filename *smb_fname,
7075 int *pdata_return_size)
7077 bool extended_oplock_granted = False;
7078 char *pdata = *ppdata;
7079 uint32 flags = 0;
7080 uint32 wire_open_mode = 0;
7081 uint32 raw_unixmode = 0;
7082 uint32 mod_unixmode = 0;
7083 uint32 create_disp = 0;
7084 uint32 access_mask = 0;
7085 uint32 create_options = 0;
7086 NTSTATUS status = NT_STATUS_OK;
7087 mode_t unixmode = (mode_t)0;
7088 files_struct *fsp = NULL;
7089 int oplock_request = 0;
7090 int info = 0;
7091 uint16 info_level_return = 0;
7093 if (total_data < 18) {
7094 return NT_STATUS_INVALID_PARAMETER;
7097 flags = IVAL(pdata,0);
7098 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7099 if (oplock_request) {
7100 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7103 wire_open_mode = IVAL(pdata,4);
7105 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7106 return smb_posix_mkdir(conn, req,
7107 ppdata,
7108 total_data,
7109 smb_fname,
7110 pdata_return_size);
7113 switch (wire_open_mode & SMB_ACCMODE) {
7114 case SMB_O_RDONLY:
7115 access_mask = FILE_READ_DATA;
7116 break;
7117 case SMB_O_WRONLY:
7118 access_mask = FILE_WRITE_DATA;
7119 break;
7120 case SMB_O_RDWR:
7121 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7122 break;
7123 default:
7124 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7125 (unsigned int)wire_open_mode ));
7126 return NT_STATUS_INVALID_PARAMETER;
7129 wire_open_mode &= ~SMB_ACCMODE;
7131 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7132 create_disp = FILE_CREATE;
7133 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7134 create_disp = FILE_OVERWRITE_IF;
7135 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7136 create_disp = FILE_OPEN_IF;
7137 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7138 create_disp = FILE_OPEN;
7139 } else {
7140 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7141 (unsigned int)wire_open_mode ));
7142 return NT_STATUS_INVALID_PARAMETER;
7145 raw_unixmode = IVAL(pdata,8);
7146 /* Next 4 bytes are not yet defined. */
7148 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7149 (VALID_STAT(smb_fname->st) ?
7150 PERM_EXISTING_FILE : PERM_NEW_FILE),
7151 &unixmode);
7153 if (!NT_STATUS_IS_OK(status)) {
7154 return status;
7157 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7159 if (wire_open_mode & SMB_O_SYNC) {
7160 create_options |= FILE_WRITE_THROUGH;
7162 if (wire_open_mode & SMB_O_APPEND) {
7163 access_mask |= FILE_APPEND_DATA;
7165 if (wire_open_mode & SMB_O_DIRECT) {
7166 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7169 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7170 smb_fname_str_dbg(smb_fname),
7171 (unsigned int)wire_open_mode,
7172 (unsigned int)unixmode ));
7174 status = SMB_VFS_CREATE_FILE(
7175 conn, /* conn */
7176 req, /* req */
7177 0, /* root_dir_fid */
7178 smb_fname, /* fname */
7179 access_mask, /* access_mask */
7180 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7181 FILE_SHARE_DELETE),
7182 create_disp, /* create_disposition*/
7183 FILE_NON_DIRECTORY_FILE, /* create_options */
7184 mod_unixmode, /* file_attributes */
7185 oplock_request, /* oplock_request */
7186 0, /* allocation_size */
7187 NULL, /* sd */
7188 NULL, /* ea_list */
7189 &fsp, /* result */
7190 &info); /* pinfo */
7192 if (!NT_STATUS_IS_OK(status)) {
7193 return status;
7196 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7197 extended_oplock_granted = True;
7200 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7201 extended_oplock_granted = True;
7204 info_level_return = SVAL(pdata,16);
7206 /* Allocate the correct return size. */
7208 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7209 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7210 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7211 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7212 } else {
7213 *pdata_return_size = 12;
7216 /* Realloc the data size */
7217 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7218 if (*ppdata == NULL) {
7219 close_file(req, fsp, ERROR_CLOSE);
7220 *pdata_return_size = 0;
7221 return NT_STATUS_NO_MEMORY;
7223 pdata = *ppdata;
7225 if (extended_oplock_granted) {
7226 if (flags & REQUEST_BATCH_OPLOCK) {
7227 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7228 } else {
7229 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7231 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7232 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7233 } else {
7234 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7237 SSVAL(pdata,2,fsp->fnum);
7238 SIVAL(pdata,4,info); /* Was file created etc. */
7240 switch (info_level_return) {
7241 case SMB_QUERY_FILE_UNIX_BASIC:
7242 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7243 SSVAL(pdata,10,0); /* padding. */
7244 store_file_unix_basic(conn, pdata + 12, fsp,
7245 &smb_fname->st);
7246 break;
7247 case SMB_QUERY_FILE_UNIX_INFO2:
7248 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7249 SSVAL(pdata,10,0); /* padding. */
7250 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7251 &smb_fname->st);
7252 break;
7253 default:
7254 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7255 SSVAL(pdata,10,0); /* padding. */
7256 break;
7258 return NT_STATUS_OK;
7261 /****************************************************************************
7262 Delete a file with POSIX semantics.
7263 ****************************************************************************/
7265 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7266 struct smb_request *req,
7267 const char *pdata,
7268 int total_data,
7269 struct smb_filename *smb_fname)
7271 NTSTATUS status = NT_STATUS_OK;
7272 files_struct *fsp = NULL;
7273 uint16 flags = 0;
7274 char del = 1;
7275 int info = 0;
7276 int create_options = 0;
7277 int i;
7278 struct share_mode_lock *lck = NULL;
7280 if (total_data < 2) {
7281 return NT_STATUS_INVALID_PARAMETER;
7284 flags = SVAL(pdata,0);
7286 if (!VALID_STAT(smb_fname->st)) {
7287 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7290 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7291 !VALID_STAT_OF_DIR(smb_fname->st)) {
7292 return NT_STATUS_NOT_A_DIRECTORY;
7295 DEBUG(10,("smb_posix_unlink: %s %s\n",
7296 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7297 smb_fname_str_dbg(smb_fname)));
7299 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7300 create_options |= FILE_DIRECTORY_FILE;
7303 status = SMB_VFS_CREATE_FILE(
7304 conn, /* conn */
7305 req, /* req */
7306 0, /* root_dir_fid */
7307 smb_fname, /* fname */
7308 DELETE_ACCESS, /* access_mask */
7309 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7310 FILE_SHARE_DELETE),
7311 FILE_OPEN, /* create_disposition*/
7312 create_options, /* create_options */
7313 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7314 0, /* oplock_request */
7315 0, /* allocation_size */
7316 NULL, /* sd */
7317 NULL, /* ea_list */
7318 &fsp, /* result */
7319 &info); /* pinfo */
7321 if (!NT_STATUS_IS_OK(status)) {
7322 return status;
7326 * Don't lie to client. If we can't really delete due to
7327 * non-POSIX opens return SHARING_VIOLATION.
7330 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7331 NULL);
7332 if (lck == NULL) {
7333 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7334 "lock for file %s\n", fsp_str_dbg(fsp)));
7335 close_file(req, fsp, NORMAL_CLOSE);
7336 return NT_STATUS_INVALID_PARAMETER;
7340 * See if others still have the file open. If this is the case, then
7341 * don't delete. If all opens are POSIX delete we can set the delete
7342 * on close disposition.
7344 for (i=0; i<lck->num_share_modes; i++) {
7345 struct share_mode_entry *e = &lck->share_modes[i];
7346 if (is_valid_share_mode_entry(e)) {
7347 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7348 continue;
7350 /* Fail with sharing violation. */
7351 close_file(req, fsp, NORMAL_CLOSE);
7352 TALLOC_FREE(lck);
7353 return NT_STATUS_SHARING_VIOLATION;
7358 * Set the delete on close.
7360 status = smb_set_file_disposition_info(conn,
7361 &del,
7363 fsp,
7364 smb_fname);
7366 if (!NT_STATUS_IS_OK(status)) {
7367 close_file(req, fsp, NORMAL_CLOSE);
7368 TALLOC_FREE(lck);
7369 return status;
7371 TALLOC_FREE(lck);
7372 return close_file(req, fsp, NORMAL_CLOSE);
7375 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7376 struct smb_request *req,
7377 TALLOC_CTX *mem_ctx,
7378 uint16_t info_level,
7379 files_struct *fsp,
7380 struct smb_filename *smb_fname,
7381 char **ppdata, int total_data,
7382 int *ret_data_size)
7384 char *pdata = *ppdata;
7385 NTSTATUS status = NT_STATUS_OK;
7386 int data_return_size = 0;
7388 *ret_data_size = 0;
7390 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7391 return NT_STATUS_INVALID_LEVEL;
7394 if (!CAN_WRITE(conn)) {
7395 /* Allow POSIX opens. The open path will deny
7396 * any non-readonly opens. */
7397 if (info_level != SMB_POSIX_PATH_OPEN) {
7398 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7402 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7403 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7404 fsp ? fsp->fnum : -1, info_level, total_data));
7406 switch (info_level) {
7408 case SMB_INFO_STANDARD:
7410 status = smb_set_info_standard(conn,
7411 pdata,
7412 total_data,
7413 fsp,
7414 smb_fname);
7415 break;
7418 case SMB_INFO_SET_EA:
7420 status = smb_info_set_ea(conn,
7421 pdata,
7422 total_data,
7423 fsp,
7424 smb_fname);
7425 break;
7428 case SMB_SET_FILE_BASIC_INFO:
7429 case SMB_FILE_BASIC_INFORMATION:
7431 status = smb_set_file_basic_info(conn,
7432 pdata,
7433 total_data,
7434 fsp,
7435 smb_fname);
7436 break;
7439 case SMB_FILE_ALLOCATION_INFORMATION:
7440 case SMB_SET_FILE_ALLOCATION_INFO:
7442 status = smb_set_file_allocation_info(conn, req,
7443 pdata,
7444 total_data,
7445 fsp,
7446 smb_fname);
7447 break;
7450 case SMB_FILE_END_OF_FILE_INFORMATION:
7451 case SMB_SET_FILE_END_OF_FILE_INFO:
7454 * XP/Win7 both fail after the createfile with
7455 * SMB_SET_FILE_END_OF_FILE_INFO but not
7456 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7457 * The level is known here, so pass it down
7458 * appropriately.
7460 bool should_fail =
7461 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7463 status = smb_set_file_end_of_file_info(conn, req,
7464 pdata,
7465 total_data,
7466 fsp,
7467 smb_fname,
7468 should_fail);
7469 break;
7472 case SMB_FILE_DISPOSITION_INFORMATION:
7473 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7475 #if 0
7476 /* JRA - We used to just ignore this on a path ?
7477 * Shouldn't this be invalid level on a pathname
7478 * based call ?
7480 if (tran_call != TRANSACT2_SETFILEINFO) {
7481 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7483 #endif
7484 status = smb_set_file_disposition_info(conn,
7485 pdata,
7486 total_data,
7487 fsp,
7488 smb_fname);
7489 break;
7492 case SMB_FILE_POSITION_INFORMATION:
7494 status = smb_file_position_information(conn,
7495 pdata,
7496 total_data,
7497 fsp);
7498 break;
7501 case SMB_FILE_FULL_EA_INFORMATION:
7503 status = smb_set_file_full_ea_info(conn,
7504 pdata,
7505 total_data,
7506 fsp);
7507 break;
7510 /* From tridge Samba4 :
7511 * MODE_INFORMATION in setfileinfo (I have no
7512 * idea what "mode information" on a file is - it takes a value of 0,
7513 * 2, 4 or 6. What could it be?).
7516 case SMB_FILE_MODE_INFORMATION:
7518 status = smb_file_mode_information(conn,
7519 pdata,
7520 total_data);
7521 break;
7525 * CIFS UNIX extensions.
7528 case SMB_SET_FILE_UNIX_BASIC:
7530 status = smb_set_file_unix_basic(conn, req,
7531 pdata,
7532 total_data,
7533 fsp,
7534 smb_fname);
7535 break;
7538 case SMB_SET_FILE_UNIX_INFO2:
7540 status = smb_set_file_unix_info2(conn, req,
7541 pdata,
7542 total_data,
7543 fsp,
7544 smb_fname);
7545 break;
7548 case SMB_SET_FILE_UNIX_LINK:
7550 if (fsp) {
7551 /* We must have a pathname for this. */
7552 return NT_STATUS_INVALID_LEVEL;
7554 status = smb_set_file_unix_link(conn, req, pdata,
7555 total_data, smb_fname);
7556 break;
7559 case SMB_SET_FILE_UNIX_HLINK:
7561 if (fsp) {
7562 /* We must have a pathname for this. */
7563 return NT_STATUS_INVALID_LEVEL;
7565 status = smb_set_file_unix_hlink(conn, req,
7566 pdata, total_data,
7567 smb_fname);
7568 break;
7571 case SMB_FILE_RENAME_INFORMATION:
7573 status = smb_file_rename_information(conn, req,
7574 pdata, total_data,
7575 fsp, smb_fname);
7576 break;
7579 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7581 /* SMB2 rename information. */
7582 status = smb2_file_rename_information(conn, req,
7583 pdata, total_data,
7584 fsp, smb_fname);
7585 break;
7587 #if defined(HAVE_POSIX_ACLS)
7588 case SMB_SET_POSIX_ACL:
7590 status = smb_set_posix_acl(conn,
7591 pdata,
7592 total_data,
7593 fsp,
7594 smb_fname);
7595 break;
7597 #endif
7599 case SMB_SET_POSIX_LOCK:
7601 if (!fsp) {
7602 return NT_STATUS_INVALID_LEVEL;
7604 status = smb_set_posix_lock(conn, req,
7605 pdata, total_data, fsp);
7606 break;
7609 case SMB_POSIX_PATH_OPEN:
7611 if (fsp) {
7612 /* We must have a pathname for this. */
7613 return NT_STATUS_INVALID_LEVEL;
7616 status = smb_posix_open(conn, req,
7617 ppdata,
7618 total_data,
7619 smb_fname,
7620 &data_return_size);
7621 break;
7624 case SMB_POSIX_PATH_UNLINK:
7626 if (fsp) {
7627 /* We must have a pathname for this. */
7628 return NT_STATUS_INVALID_LEVEL;
7631 status = smb_posix_unlink(conn, req,
7632 pdata,
7633 total_data,
7634 smb_fname);
7635 break;
7638 default:
7639 return NT_STATUS_INVALID_LEVEL;
7642 if (!NT_STATUS_IS_OK(status)) {
7643 return status;
7646 *ret_data_size = data_return_size;
7647 return NT_STATUS_OK;
7650 /****************************************************************************
7651 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7652 ****************************************************************************/
7654 static void call_trans2setfilepathinfo(connection_struct *conn,
7655 struct smb_request *req,
7656 unsigned int tran_call,
7657 char **pparams, int total_params,
7658 char **ppdata, int total_data,
7659 unsigned int max_data_bytes)
7661 char *params = *pparams;
7662 char *pdata = *ppdata;
7663 uint16 info_level;
7664 struct smb_filename *smb_fname = NULL;
7665 files_struct *fsp = NULL;
7666 NTSTATUS status = NT_STATUS_OK;
7667 int data_return_size = 0;
7669 if (!params) {
7670 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7671 return;
7674 if (tran_call == TRANSACT2_SETFILEINFO) {
7675 if (total_params < 4) {
7676 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7677 return;
7680 fsp = file_fsp(req, SVAL(params,0));
7681 /* Basic check for non-null fsp. */
7682 if (!check_fsp_open(conn, req, fsp)) {
7683 return;
7685 info_level = SVAL(params,2);
7687 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7688 &smb_fname);
7689 if (!NT_STATUS_IS_OK(status)) {
7690 reply_nterror(req, status);
7691 return;
7694 if(fsp->is_directory || fsp->fh->fd == -1) {
7696 * This is actually a SETFILEINFO on a directory
7697 * handle (returned from an NT SMB). NT5.0 seems
7698 * to do this call. JRA.
7700 if (INFO_LEVEL_IS_UNIX(info_level)) {
7701 /* Always do lstat for UNIX calls. */
7702 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7703 DEBUG(3,("call_trans2setfilepathinfo: "
7704 "SMB_VFS_LSTAT of %s failed "
7705 "(%s)\n",
7706 smb_fname_str_dbg(smb_fname),
7707 strerror(errno)));
7708 reply_nterror(req, map_nt_error_from_unix(errno));
7709 return;
7711 } else {
7712 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7713 DEBUG(3,("call_trans2setfilepathinfo: "
7714 "fileinfo of %s failed (%s)\n",
7715 smb_fname_str_dbg(smb_fname),
7716 strerror(errno)));
7717 reply_nterror(req, map_nt_error_from_unix(errno));
7718 return;
7721 } else if (fsp->print_file) {
7723 * Doing a DELETE_ON_CLOSE should cancel a print job.
7725 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7726 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7728 DEBUG(3,("call_trans2setfilepathinfo: "
7729 "Cancelling print job (%s)\n",
7730 fsp_str_dbg(fsp)));
7732 SSVAL(params,0,0);
7733 send_trans2_replies(conn, req, params, 2,
7734 *ppdata, 0,
7735 max_data_bytes);
7736 return;
7737 } else {
7738 reply_nterror(req,
7739 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7740 return;
7742 } else {
7744 * Original code - this is an open file.
7746 if (!check_fsp(conn, req, fsp)) {
7747 return;
7750 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7751 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7752 "of fnum %d failed (%s)\n", fsp->fnum,
7753 strerror(errno)));
7754 reply_nterror(req, map_nt_error_from_unix(errno));
7755 return;
7758 } else {
7759 char *fname = NULL;
7761 /* set path info */
7762 if (total_params < 7) {
7763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7764 return;
7767 info_level = SVAL(params,0);
7768 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7769 total_params - 6, STR_TERMINATE,
7770 &status);
7771 if (!NT_STATUS_IS_OK(status)) {
7772 reply_nterror(req, status);
7773 return;
7776 status = filename_convert(req, conn,
7777 req->flags2 & FLAGS2_DFS_PATHNAMES,
7778 fname,
7780 NULL,
7781 &smb_fname);
7782 if (!NT_STATUS_IS_OK(status)) {
7783 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7784 reply_botherror(req,
7785 NT_STATUS_PATH_NOT_COVERED,
7786 ERRSRV, ERRbadpath);
7787 return;
7789 reply_nterror(req, status);
7790 return;
7793 if (INFO_LEVEL_IS_UNIX(info_level)) {
7795 * For CIFS UNIX extensions the target name may not exist.
7798 /* Always do lstat for UNIX calls. */
7799 SMB_VFS_LSTAT(conn, smb_fname);
7801 } else if (!VALID_STAT(smb_fname->st) &&
7802 SMB_VFS_STAT(conn, smb_fname)) {
7803 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7804 "%s failed (%s)\n",
7805 smb_fname_str_dbg(smb_fname),
7806 strerror(errno)));
7807 reply_nterror(req, map_nt_error_from_unix(errno));
7808 return;
7812 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7813 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7814 fsp ? fsp->fnum : -1, info_level,total_data));
7816 /* Realloc the parameter size */
7817 *pparams = (char *)SMB_REALLOC(*pparams,2);
7818 if (*pparams == NULL) {
7819 reply_nterror(req, NT_STATUS_NO_MEMORY);
7820 return;
7822 params = *pparams;
7824 SSVAL(params,0,0);
7826 status = smbd_do_setfilepathinfo(conn, req, req,
7827 info_level,
7828 fsp,
7829 smb_fname,
7830 ppdata, total_data,
7831 &data_return_size);
7832 if (!NT_STATUS_IS_OK(status)) {
7833 if (open_was_deferred(req->mid)) {
7834 /* We have re-scheduled this call. */
7835 return;
7837 if (blocking_lock_was_deferred(req->mid)) {
7838 /* We have re-scheduled this call. */
7839 return;
7841 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7842 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7843 ERRSRV, ERRbadpath);
7844 return;
7846 if (info_level == SMB_POSIX_PATH_OPEN) {
7847 reply_openerror(req, status);
7848 return;
7851 reply_nterror(req, status);
7852 return;
7855 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7856 max_data_bytes);
7858 return;
7861 /****************************************************************************
7862 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7863 ****************************************************************************/
7865 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7866 char **pparams, int total_params,
7867 char **ppdata, int total_data,
7868 unsigned int max_data_bytes)
7870 struct smb_filename *smb_dname = NULL;
7871 char *params = *pparams;
7872 char *pdata = *ppdata;
7873 char *directory = NULL;
7874 NTSTATUS status = NT_STATUS_OK;
7875 struct ea_list *ea_list = NULL;
7876 TALLOC_CTX *ctx = talloc_tos();
7878 if (!CAN_WRITE(conn)) {
7879 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7880 return;
7883 if (total_params < 5) {
7884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7885 return;
7888 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7889 total_params - 4, STR_TERMINATE,
7890 &status);
7891 if (!NT_STATUS_IS_OK(status)) {
7892 reply_nterror(req, status);
7893 return;
7896 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7898 status = filename_convert(ctx,
7899 conn,
7900 req->flags2 & FLAGS2_DFS_PATHNAMES,
7901 directory,
7903 NULL,
7904 &smb_dname);
7906 if (!NT_STATUS_IS_OK(status)) {
7907 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7908 reply_botherror(req,
7909 NT_STATUS_PATH_NOT_COVERED,
7910 ERRSRV, ERRbadpath);
7911 return;
7913 reply_nterror(req, status);
7914 return;
7917 /* Any data in this call is an EA list. */
7918 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7919 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7920 goto out;
7924 * OS/2 workplace shell seems to send SET_EA requests of "null"
7925 * length (4 bytes containing IVAL 4).
7926 * They seem to have no effect. Bug #3212. JRA.
7929 if (total_data != 4) {
7930 if (total_data < 10) {
7931 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7932 goto out;
7935 if (IVAL(pdata,0) > total_data) {
7936 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7937 IVAL(pdata,0), (unsigned int)total_data));
7938 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7939 goto out;
7942 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7943 total_data - 4);
7944 if (!ea_list) {
7945 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7946 goto out;
7949 /* If total_data == 4 Windows doesn't care what values
7950 * are placed in that field, it just ignores them.
7951 * The System i QNTC IBM SMB client puts bad values here,
7952 * so ignore them. */
7954 status = create_directory(conn, req, smb_dname);
7956 if (!NT_STATUS_IS_OK(status)) {
7957 reply_nterror(req, status);
7958 goto out;
7961 /* Try and set any given EA. */
7962 if (ea_list) {
7963 status = set_ea(conn, NULL, smb_dname, ea_list);
7964 if (!NT_STATUS_IS_OK(status)) {
7965 reply_nterror(req, status);
7966 goto out;
7970 /* Realloc the parameter and data sizes */
7971 *pparams = (char *)SMB_REALLOC(*pparams,2);
7972 if(*pparams == NULL) {
7973 reply_nterror(req, NT_STATUS_NO_MEMORY);
7974 goto out;
7976 params = *pparams;
7978 SSVAL(params,0,0);
7980 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7982 out:
7983 TALLOC_FREE(smb_dname);
7984 return;
7987 /****************************************************************************
7988 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7989 We don't actually do this - we just send a null response.
7990 ****************************************************************************/
7992 static void call_trans2findnotifyfirst(connection_struct *conn,
7993 struct smb_request *req,
7994 char **pparams, int total_params,
7995 char **ppdata, int total_data,
7996 unsigned int max_data_bytes)
7998 char *params = *pparams;
7999 uint16 info_level;
8001 if (total_params < 6) {
8002 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8003 return;
8006 info_level = SVAL(params,4);
8007 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8009 switch (info_level) {
8010 case 1:
8011 case 2:
8012 break;
8013 default:
8014 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8015 return;
8018 /* Realloc the parameter and data sizes */
8019 *pparams = (char *)SMB_REALLOC(*pparams,6);
8020 if (*pparams == NULL) {
8021 reply_nterror(req, NT_STATUS_NO_MEMORY);
8022 return;
8024 params = *pparams;
8026 SSVAL(params,0,fnf_handle);
8027 SSVAL(params,2,0); /* No changes */
8028 SSVAL(params,4,0); /* No EA errors */
8030 fnf_handle++;
8032 if(fnf_handle == 0)
8033 fnf_handle = 257;
8035 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8037 return;
8040 /****************************************************************************
8041 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8042 changes). Currently this does nothing.
8043 ****************************************************************************/
8045 static void call_trans2findnotifynext(connection_struct *conn,
8046 struct smb_request *req,
8047 char **pparams, int total_params,
8048 char **ppdata, int total_data,
8049 unsigned int max_data_bytes)
8051 char *params = *pparams;
8053 DEBUG(3,("call_trans2findnotifynext\n"));
8055 /* Realloc the parameter and data sizes */
8056 *pparams = (char *)SMB_REALLOC(*pparams,4);
8057 if (*pparams == NULL) {
8058 reply_nterror(req, NT_STATUS_NO_MEMORY);
8059 return;
8061 params = *pparams;
8063 SSVAL(params,0,0); /* No changes */
8064 SSVAL(params,2,0); /* No EA errors */
8066 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8068 return;
8071 /****************************************************************************
8072 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8073 ****************************************************************************/
8075 static void call_trans2getdfsreferral(connection_struct *conn,
8076 struct smb_request *req,
8077 char **pparams, int total_params,
8078 char **ppdata, int total_data,
8079 unsigned int max_data_bytes)
8081 char *params = *pparams;
8082 char *pathname = NULL;
8083 int reply_size = 0;
8084 int max_referral_level;
8085 NTSTATUS status = NT_STATUS_OK;
8086 TALLOC_CTX *ctx = talloc_tos();
8088 DEBUG(10,("call_trans2getdfsreferral\n"));
8090 if (total_params < 3) {
8091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8092 return;
8095 max_referral_level = SVAL(params,0);
8097 if(!lp_host_msdfs()) {
8098 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8099 return;
8102 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8103 total_params - 2, STR_TERMINATE);
8104 if (!pathname) {
8105 reply_nterror(req, NT_STATUS_NOT_FOUND);
8106 return;
8108 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8109 ppdata,&status)) < 0) {
8110 reply_nterror(req, status);
8111 return;
8114 SSVAL(req->inbuf, smb_flg2,
8115 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8116 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8118 return;
8121 #define LMCAT_SPL 0x53
8122 #define LMFUNC_GETJOBID 0x60
8124 /****************************************************************************
8125 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8126 ****************************************************************************/
8128 static void call_trans2ioctl(connection_struct *conn,
8129 struct smb_request *req,
8130 char **pparams, int total_params,
8131 char **ppdata, int total_data,
8132 unsigned int max_data_bytes)
8134 char *pdata = *ppdata;
8135 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8137 /* check for an invalid fid before proceeding */
8139 if (!fsp) {
8140 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8141 return;
8144 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8145 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8146 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8147 if (*ppdata == NULL) {
8148 reply_nterror(req, NT_STATUS_NO_MEMORY);
8149 return;
8151 pdata = *ppdata;
8153 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8154 CAN ACCEPT THIS IN UNICODE. JRA. */
8156 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8157 srvstr_push(pdata, req->flags2, pdata + 2,
8158 global_myname(), 15,
8159 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8160 srvstr_push(pdata, req->flags2, pdata+18,
8161 lp_servicename(SNUM(conn)), 13,
8162 STR_ASCII|STR_TERMINATE); /* Service name */
8163 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8164 max_data_bytes);
8165 return;
8168 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8169 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8172 /****************************************************************************
8173 Reply to a SMBfindclose (stop trans2 directory search).
8174 ****************************************************************************/
8176 void reply_findclose(struct smb_request *req)
8178 int dptr_num;
8179 struct smbd_server_connection *sconn = smbd_server_conn;
8181 START_PROFILE(SMBfindclose);
8183 if (req->wct < 1) {
8184 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8185 END_PROFILE(SMBfindclose);
8186 return;
8189 dptr_num = SVALS(req->vwv+0, 0);
8191 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8193 dptr_close(sconn, &dptr_num);
8195 reply_outbuf(req, 0, 0);
8197 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8199 END_PROFILE(SMBfindclose);
8200 return;
8203 /****************************************************************************
8204 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8205 ****************************************************************************/
8207 void reply_findnclose(struct smb_request *req)
8209 int dptr_num;
8211 START_PROFILE(SMBfindnclose);
8213 if (req->wct < 1) {
8214 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8215 END_PROFILE(SMBfindnclose);
8216 return;
8219 dptr_num = SVAL(req->vwv+0, 0);
8221 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8223 /* We never give out valid handles for a
8224 findnotifyfirst - so any dptr_num is ok here.
8225 Just ignore it. */
8227 reply_outbuf(req, 0, 0);
8229 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8231 END_PROFILE(SMBfindnclose);
8232 return;
8235 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8236 struct trans_state *state)
8238 if (get_Protocol() >= PROTOCOL_NT1) {
8239 req->flags2 |= 0x40; /* IS_LONG_NAME */
8240 SSVAL(req->inbuf,smb_flg2,req->flags2);
8243 if (conn->encrypt_level == Required && !req->encrypted) {
8244 if (state->call != TRANSACT2_QFSINFO &&
8245 state->call != TRANSACT2_SETFSINFO) {
8246 DEBUG(0,("handle_trans2: encryption required "
8247 "with call 0x%x\n",
8248 (unsigned int)state->call));
8249 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8250 return;
8254 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8256 /* Now we must call the relevant TRANS2 function */
8257 switch(state->call) {
8258 case TRANSACT2_OPEN:
8260 START_PROFILE(Trans2_open);
8261 call_trans2open(conn, req,
8262 &state->param, state->total_param,
8263 &state->data, state->total_data,
8264 state->max_data_return);
8265 END_PROFILE(Trans2_open);
8266 break;
8269 case TRANSACT2_FINDFIRST:
8271 START_PROFILE(Trans2_findfirst);
8272 call_trans2findfirst(conn, req,
8273 &state->param, state->total_param,
8274 &state->data, state->total_data,
8275 state->max_data_return);
8276 END_PROFILE(Trans2_findfirst);
8277 break;
8280 case TRANSACT2_FINDNEXT:
8282 START_PROFILE(Trans2_findnext);
8283 call_trans2findnext(conn, req,
8284 &state->param, state->total_param,
8285 &state->data, state->total_data,
8286 state->max_data_return);
8287 END_PROFILE(Trans2_findnext);
8288 break;
8291 case TRANSACT2_QFSINFO:
8293 START_PROFILE(Trans2_qfsinfo);
8294 call_trans2qfsinfo(conn, req,
8295 &state->param, state->total_param,
8296 &state->data, state->total_data,
8297 state->max_data_return);
8298 END_PROFILE(Trans2_qfsinfo);
8299 break;
8302 case TRANSACT2_SETFSINFO:
8304 START_PROFILE(Trans2_setfsinfo);
8305 call_trans2setfsinfo(conn, req,
8306 &state->param, state->total_param,
8307 &state->data, state->total_data,
8308 state->max_data_return);
8309 END_PROFILE(Trans2_setfsinfo);
8310 break;
8313 case TRANSACT2_QPATHINFO:
8314 case TRANSACT2_QFILEINFO:
8316 START_PROFILE(Trans2_qpathinfo);
8317 call_trans2qfilepathinfo(conn, req, state->call,
8318 &state->param, state->total_param,
8319 &state->data, state->total_data,
8320 state->max_data_return);
8321 END_PROFILE(Trans2_qpathinfo);
8322 break;
8325 case TRANSACT2_SETPATHINFO:
8326 case TRANSACT2_SETFILEINFO:
8328 START_PROFILE(Trans2_setpathinfo);
8329 call_trans2setfilepathinfo(conn, req, state->call,
8330 &state->param, state->total_param,
8331 &state->data, state->total_data,
8332 state->max_data_return);
8333 END_PROFILE(Trans2_setpathinfo);
8334 break;
8337 case TRANSACT2_FINDNOTIFYFIRST:
8339 START_PROFILE(Trans2_findnotifyfirst);
8340 call_trans2findnotifyfirst(conn, req,
8341 &state->param, state->total_param,
8342 &state->data, state->total_data,
8343 state->max_data_return);
8344 END_PROFILE(Trans2_findnotifyfirst);
8345 break;
8348 case TRANSACT2_FINDNOTIFYNEXT:
8350 START_PROFILE(Trans2_findnotifynext);
8351 call_trans2findnotifynext(conn, req,
8352 &state->param, state->total_param,
8353 &state->data, state->total_data,
8354 state->max_data_return);
8355 END_PROFILE(Trans2_findnotifynext);
8356 break;
8359 case TRANSACT2_MKDIR:
8361 START_PROFILE(Trans2_mkdir);
8362 call_trans2mkdir(conn, req,
8363 &state->param, state->total_param,
8364 &state->data, state->total_data,
8365 state->max_data_return);
8366 END_PROFILE(Trans2_mkdir);
8367 break;
8370 case TRANSACT2_GET_DFS_REFERRAL:
8372 START_PROFILE(Trans2_get_dfs_referral);
8373 call_trans2getdfsreferral(conn, req,
8374 &state->param, state->total_param,
8375 &state->data, state->total_data,
8376 state->max_data_return);
8377 END_PROFILE(Trans2_get_dfs_referral);
8378 break;
8381 case TRANSACT2_IOCTL:
8383 START_PROFILE(Trans2_ioctl);
8384 call_trans2ioctl(conn, req,
8385 &state->param, state->total_param,
8386 &state->data, state->total_data,
8387 state->max_data_return);
8388 END_PROFILE(Trans2_ioctl);
8389 break;
8392 default:
8393 /* Error in request */
8394 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8395 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8399 /****************************************************************************
8400 Reply to a SMBtrans2.
8401 ****************************************************************************/
8403 void reply_trans2(struct smb_request *req)
8405 connection_struct *conn = req->conn;
8406 unsigned int dsoff;
8407 unsigned int dscnt;
8408 unsigned int psoff;
8409 unsigned int pscnt;
8410 unsigned int tran_call;
8411 struct trans_state *state;
8412 NTSTATUS result;
8414 START_PROFILE(SMBtrans2);
8416 if (req->wct < 14) {
8417 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8418 END_PROFILE(SMBtrans2);
8419 return;
8422 dsoff = SVAL(req->vwv+12, 0);
8423 dscnt = SVAL(req->vwv+11, 0);
8424 psoff = SVAL(req->vwv+10, 0);
8425 pscnt = SVAL(req->vwv+9, 0);
8426 tran_call = SVAL(req->vwv+14, 0);
8428 result = allow_new_trans(conn->pending_trans, req->mid);
8429 if (!NT_STATUS_IS_OK(result)) {
8430 DEBUG(2, ("Got invalid trans2 request: %s\n",
8431 nt_errstr(result)));
8432 reply_nterror(req, result);
8433 END_PROFILE(SMBtrans2);
8434 return;
8437 if (IS_IPC(conn)) {
8438 switch (tran_call) {
8439 /* List the allowed trans2 calls on IPC$ */
8440 case TRANSACT2_OPEN:
8441 case TRANSACT2_GET_DFS_REFERRAL:
8442 case TRANSACT2_QFILEINFO:
8443 case TRANSACT2_QFSINFO:
8444 case TRANSACT2_SETFSINFO:
8445 break;
8446 default:
8447 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8448 END_PROFILE(SMBtrans2);
8449 return;
8453 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8454 DEBUG(0, ("talloc failed\n"));
8455 reply_nterror(req, NT_STATUS_NO_MEMORY);
8456 END_PROFILE(SMBtrans2);
8457 return;
8460 state->cmd = SMBtrans2;
8462 state->mid = req->mid;
8463 state->vuid = req->vuid;
8464 state->setup_count = SVAL(req->vwv+13, 0);
8465 state->setup = NULL;
8466 state->total_param = SVAL(req->vwv+0, 0);
8467 state->param = NULL;
8468 state->total_data = SVAL(req->vwv+1, 0);
8469 state->data = NULL;
8470 state->max_param_return = SVAL(req->vwv+2, 0);
8471 state->max_data_return = SVAL(req->vwv+3, 0);
8472 state->max_setup_return = SVAL(req->vwv+4, 0);
8473 state->close_on_completion = BITSETW(req->vwv+5, 0);
8474 state->one_way = BITSETW(req->vwv+5, 1);
8476 state->call = tran_call;
8478 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8479 is so as a sanity check */
8480 if (state->setup_count != 1) {
8482 * Need to have rc=0 for ioctl to get job id for OS/2.
8483 * Network printing will fail if function is not successful.
8484 * Similar function in reply.c will be used if protocol
8485 * is LANMAN1.0 instead of LM1.2X002.
8486 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8487 * outbuf doesn't have to be set(only job id is used).
8489 if ( (state->setup_count == 4)
8490 && (tran_call == TRANSACT2_IOCTL)
8491 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8492 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8493 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8494 } else {
8495 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8496 DEBUG(2,("Transaction is %d\n",tran_call));
8497 TALLOC_FREE(state);
8498 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8499 END_PROFILE(SMBtrans2);
8500 return;
8504 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8505 goto bad_param;
8507 if (state->total_data) {
8509 if (trans_oob(state->total_data, 0, dscnt)
8510 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8511 goto bad_param;
8514 /* Can't use talloc here, the core routines do realloc on the
8515 * params and data. */
8516 state->data = (char *)SMB_MALLOC(state->total_data);
8517 if (state->data == NULL) {
8518 DEBUG(0,("reply_trans2: data malloc fail for %u "
8519 "bytes !\n", (unsigned int)state->total_data));
8520 TALLOC_FREE(state);
8521 reply_nterror(req, NT_STATUS_NO_MEMORY);
8522 END_PROFILE(SMBtrans2);
8523 return;
8526 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8529 if (state->total_param) {
8531 if (trans_oob(state->total_param, 0, pscnt)
8532 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8533 goto bad_param;
8536 /* Can't use talloc here, the core routines do realloc on the
8537 * params and data. */
8538 state->param = (char *)SMB_MALLOC(state->total_param);
8539 if (state->param == NULL) {
8540 DEBUG(0,("reply_trans: param malloc fail for %u "
8541 "bytes !\n", (unsigned int)state->total_param));
8542 SAFE_FREE(state->data);
8543 TALLOC_FREE(state);
8544 reply_nterror(req, NT_STATUS_NO_MEMORY);
8545 END_PROFILE(SMBtrans2);
8546 return;
8549 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8552 state->received_data = dscnt;
8553 state->received_param = pscnt;
8555 if ((state->received_param == state->total_param) &&
8556 (state->received_data == state->total_data)) {
8558 handle_trans2(conn, req, state);
8560 SAFE_FREE(state->data);
8561 SAFE_FREE(state->param);
8562 TALLOC_FREE(state);
8563 END_PROFILE(SMBtrans2);
8564 return;
8567 DLIST_ADD(conn->pending_trans, state);
8569 /* We need to send an interim response then receive the rest
8570 of the parameter/data bytes */
8571 reply_outbuf(req, 0, 0);
8572 show_msg((char *)req->outbuf);
8573 END_PROFILE(SMBtrans2);
8574 return;
8576 bad_param:
8578 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8579 SAFE_FREE(state->data);
8580 SAFE_FREE(state->param);
8581 TALLOC_FREE(state);
8582 END_PROFILE(SMBtrans2);
8583 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8587 /****************************************************************************
8588 Reply to a SMBtranss2
8589 ****************************************************************************/
8591 void reply_transs2(struct smb_request *req)
8593 connection_struct *conn = req->conn;
8594 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8595 struct trans_state *state;
8597 START_PROFILE(SMBtranss2);
8599 show_msg((char *)req->inbuf);
8601 if (req->wct < 8) {
8602 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8603 END_PROFILE(SMBtranss2);
8604 return;
8607 for (state = conn->pending_trans; state != NULL;
8608 state = state->next) {
8609 if (state->mid == req->mid) {
8610 break;
8614 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8615 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8616 END_PROFILE(SMBtranss2);
8617 return;
8620 /* Revise state->total_param and state->total_data in case they have
8621 changed downwards */
8623 if (SVAL(req->vwv+0, 0) < state->total_param)
8624 state->total_param = SVAL(req->vwv+0, 0);
8625 if (SVAL(req->vwv+1, 0) < state->total_data)
8626 state->total_data = SVAL(req->vwv+1, 0);
8628 pcnt = SVAL(req->vwv+2, 0);
8629 poff = SVAL(req->vwv+3, 0);
8630 pdisp = SVAL(req->vwv+4, 0);
8632 dcnt = SVAL(req->vwv+5, 0);
8633 doff = SVAL(req->vwv+6, 0);
8634 ddisp = SVAL(req->vwv+7, 0);
8636 state->received_param += pcnt;
8637 state->received_data += dcnt;
8639 if ((state->received_data > state->total_data) ||
8640 (state->received_param > state->total_param))
8641 goto bad_param;
8643 if (pcnt) {
8644 if (trans_oob(state->total_param, pdisp, pcnt)
8645 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8646 goto bad_param;
8648 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8651 if (dcnt) {
8652 if (trans_oob(state->total_data, ddisp, dcnt)
8653 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8654 goto bad_param;
8656 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8659 if ((state->received_param < state->total_param) ||
8660 (state->received_data < state->total_data)) {
8661 END_PROFILE(SMBtranss2);
8662 return;
8665 handle_trans2(conn, req, state);
8667 DLIST_REMOVE(conn->pending_trans, state);
8668 SAFE_FREE(state->data);
8669 SAFE_FREE(state->param);
8670 TALLOC_FREE(state);
8672 END_PROFILE(SMBtranss2);
8673 return;
8675 bad_param:
8677 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8678 DLIST_REMOVE(conn->pending_trans, state);
8679 SAFE_FREE(state->data);
8680 SAFE_FREE(state->param);
8681 TALLOC_FREE(state);
8682 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8683 END_PROFILE(SMBtranss2);
8684 return;