Ensure we don't see the xattr used to store NT security (visible when xattr_tdb
[Samba/gbeck.git] / source3 / smbd / trans2.c
blob9c69b3bf2cb9699dcf0e9c0daa9534970b60b901
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_doserror(req, ERRSRV, ERRaccess);
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_doserror(req, ERRDOS, ERRbadaccess);
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_doserror(req, ERRDOS,ERRnoaccess);
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 uint32_t nt_extmode; /* Used for NT connections instead of mode */
1488 off_t off;
1489 off_t pad = 0;
1491 *out_of_space = false;
1493 ZERO_STRUCT(mdate_ts);
1494 ZERO_STRUCT(adate_ts);
1495 ZERO_STRUCT(create_date_ts);
1496 ZERO_STRUCT(cdate_ts);
1498 if (!(mode & aDIR)) {
1499 file_size = get_file_size_stat(&smb_fname->st);
1501 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1503 mdate_ts = smb_fname->st.st_ex_mtime;
1504 adate_ts = smb_fname->st.st_ex_atime;
1505 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1506 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1508 if (lp_dos_filetime_resolution(SNUM(conn))) {
1509 dos_filetime_timespec(&create_date_ts);
1510 dos_filetime_timespec(&mdate_ts);
1511 dos_filetime_timespec(&adate_ts);
1512 dos_filetime_timespec(&cdate_ts);
1515 create_date = convert_timespec_to_time_t(create_date_ts);
1516 mdate = convert_timespec_to_time_t(mdate_ts);
1517 adate = convert_timespec_to_time_t(adate_ts);
1518 c_date = convert_timespec_to_time_t(cdate_ts);
1520 /* align the record */
1521 off = PTR_DIFF(pdata, base_data);
1522 pad = (off + (align-1)) & ~(align-1);
1523 pad -= off;
1524 off += pad;
1525 /* initialize padding to 0 */
1526 if (pad) {
1527 memset(pdata, 0, pad);
1529 space_remaining -= pad;
1531 pdata += pad;
1532 p = pdata;
1533 last_entry_ptr = p;
1535 pad = 0;
1536 off = 0;
1538 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1540 switch (info_level) {
1541 case SMB_FIND_INFO_STANDARD:
1542 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1543 if(requires_resume_key) {
1544 SIVAL(p,0,reskey);
1545 p += 4;
1547 srv_put_dos_date2(p,0,create_date);
1548 srv_put_dos_date2(p,4,adate);
1549 srv_put_dos_date2(p,8,mdate);
1550 SIVAL(p,12,(uint32)file_size);
1551 SIVAL(p,16,(uint32)allocation_size);
1552 SSVAL(p,20,mode);
1553 p += 23;
1554 nameptr = p;
1555 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1556 p += ucs2_align(base_data, p, 0);
1558 len = srvstr_push(base_data, flags2, p,
1559 fname, PTR_DIFF(end_data, p),
1560 STR_TERMINATE);
1561 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1562 if (len > 2) {
1563 SCVAL(nameptr, -1, len - 2);
1564 } else {
1565 SCVAL(nameptr, -1, 0);
1567 } else {
1568 if (len > 1) {
1569 SCVAL(nameptr, -1, len - 1);
1570 } else {
1571 SCVAL(nameptr, -1, 0);
1574 p += len;
1575 break;
1577 case SMB_FIND_EA_SIZE:
1578 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1579 if (requires_resume_key) {
1580 SIVAL(p,0,reskey);
1581 p += 4;
1583 srv_put_dos_date2(p,0,create_date);
1584 srv_put_dos_date2(p,4,adate);
1585 srv_put_dos_date2(p,8,mdate);
1586 SIVAL(p,12,(uint32)file_size);
1587 SIVAL(p,16,(uint32)allocation_size);
1588 SSVAL(p,20,mode);
1590 unsigned int ea_size = estimate_ea_size(conn, NULL,
1591 smb_fname->base_name);
1592 SIVAL(p,22,ea_size); /* Extended attributes */
1594 p += 27;
1595 nameptr = p - 1;
1596 len = srvstr_push(base_data, flags2,
1597 p, fname, PTR_DIFF(end_data, p),
1598 STR_TERMINATE | STR_NOALIGN);
1599 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1600 if (len > 2) {
1601 len -= 2;
1602 } else {
1603 len = 0;
1605 } else {
1606 if (len > 1) {
1607 len -= 1;
1608 } else {
1609 len = 0;
1612 SCVAL(nameptr,0,len);
1613 p += len;
1614 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1615 break;
1617 case SMB_FIND_EA_LIST:
1619 struct ea_list *file_list = NULL;
1620 size_t ea_len = 0;
1622 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1623 if (!name_list) {
1624 return false;
1626 if (requires_resume_key) {
1627 SIVAL(p,0,reskey);
1628 p += 4;
1630 srv_put_dos_date2(p,0,create_date);
1631 srv_put_dos_date2(p,4,adate);
1632 srv_put_dos_date2(p,8,mdate);
1633 SIVAL(p,12,(uint32)file_size);
1634 SIVAL(p,16,(uint32)allocation_size);
1635 SSVAL(p,20,mode);
1636 p += 22; /* p now points to the EA area. */
1638 file_list = get_ea_list_from_file(ctx, conn, NULL,
1639 smb_fname->base_name,
1640 &ea_len);
1641 name_list = ea_list_union(name_list, file_list, &ea_len);
1643 /* We need to determine if this entry will fit in the space available. */
1644 /* Max string size is 255 bytes. */
1645 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1646 *out_of_space = true;
1647 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1648 return False; /* Not finished - just out of space */
1651 /* Push the ea_data followed by the name. */
1652 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1653 nameptr = p;
1654 len = srvstr_push(base_data, flags2,
1655 p + 1, fname, PTR_DIFF(end_data, p+1),
1656 STR_TERMINATE | STR_NOALIGN);
1657 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1658 if (len > 2) {
1659 len -= 2;
1660 } else {
1661 len = 0;
1663 } else {
1664 if (len > 1) {
1665 len -= 1;
1666 } else {
1667 len = 0;
1670 SCVAL(nameptr,0,len);
1671 p += len + 1;
1672 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1673 break;
1676 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1677 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1678 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1679 p += 4;
1680 SIVAL(p,0,reskey); p += 4;
1681 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1682 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1683 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1684 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1685 SOFF_T(p,0,file_size); p += 8;
1686 SOFF_T(p,0,allocation_size); p += 8;
1687 SIVAL(p,0,nt_extmode); p += 4;
1688 q = p; p += 4; /* q is placeholder for name length. */
1690 unsigned int ea_size = estimate_ea_size(conn, NULL,
1691 smb_fname->base_name);
1692 SIVAL(p,0,ea_size); /* Extended attributes */
1693 p += 4;
1695 /* Clear the short name buffer. This is
1696 * IMPORTANT as not doing so will trigger
1697 * a Win2k client bug. JRA.
1699 if (!was_8_3 && check_mangled_names) {
1700 char mangled_name[13]; /* mangled 8.3 name. */
1701 if (!name_to_8_3(fname,mangled_name,True,
1702 conn->params)) {
1703 /* Error - mangle failed ! */
1704 memset(mangled_name,'\0',12);
1706 mangled_name[12] = 0;
1707 len = srvstr_push(base_data, flags2,
1708 p+2, mangled_name, 24,
1709 STR_UPPER|STR_UNICODE);
1710 if (len < 24) {
1711 memset(p + 2 + len,'\0',24 - len);
1713 SSVAL(p, 0, len);
1714 } else {
1715 memset(p,'\0',26);
1717 p += 2 + 24;
1718 len = srvstr_push(base_data, flags2, p,
1719 fname, PTR_DIFF(end_data, p),
1720 STR_TERMINATE_ASCII);
1721 SIVAL(q,0,len);
1722 p += len;
1724 len = PTR_DIFF(p, pdata);
1725 pad = (len + (align-1)) & ~(align-1);
1727 * offset to the next entry, the caller
1728 * will overwrite it for the last entry
1729 * that's why we always include the padding
1731 SIVAL(pdata,0,pad);
1733 * set padding to zero
1735 if (do_pad) {
1736 memset(p, 0, pad - len);
1737 p = pdata + pad;
1738 } else {
1739 p = pdata + len;
1741 break;
1743 case SMB_FIND_FILE_DIRECTORY_INFO:
1744 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1745 p += 4;
1746 SIVAL(p,0,reskey); p += 4;
1747 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1748 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1749 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1750 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1751 SOFF_T(p,0,file_size); p += 8;
1752 SOFF_T(p,0,allocation_size); p += 8;
1753 SIVAL(p,0,nt_extmode); p += 4;
1754 len = srvstr_push(base_data, flags2,
1755 p + 4, fname, PTR_DIFF(end_data, p+4),
1756 STR_TERMINATE_ASCII);
1757 SIVAL(p,0,len);
1758 p += 4 + len;
1760 len = PTR_DIFF(p, pdata);
1761 pad = (len + (align-1)) & ~(align-1);
1763 * offset to the next entry, the caller
1764 * will overwrite it for the last entry
1765 * that's why we always include the padding
1767 SIVAL(pdata,0,pad);
1769 * set padding to zero
1771 if (do_pad) {
1772 memset(p, 0, pad - len);
1773 p = pdata + pad;
1774 } else {
1775 p = pdata + len;
1777 break;
1779 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1780 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1781 p += 4;
1782 SIVAL(p,0,reskey); p += 4;
1783 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1784 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1785 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1786 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1787 SOFF_T(p,0,file_size); p += 8;
1788 SOFF_T(p,0,allocation_size); p += 8;
1789 SIVAL(p,0,nt_extmode); p += 4;
1790 q = p; p += 4; /* q is placeholder for name length. */
1792 unsigned int ea_size = estimate_ea_size(conn, NULL,
1793 smb_fname->base_name);
1794 SIVAL(p,0,ea_size); /* Extended attributes */
1795 p +=4;
1797 len = srvstr_push(base_data, flags2, p,
1798 fname, PTR_DIFF(end_data, p),
1799 STR_TERMINATE_ASCII);
1800 SIVAL(q, 0, len);
1801 p += len;
1803 len = PTR_DIFF(p, pdata);
1804 pad = (len + (align-1)) & ~(align-1);
1806 * offset to the next entry, the caller
1807 * will overwrite it for the last entry
1808 * that's why we always include the padding
1810 SIVAL(pdata,0,pad);
1812 * set padding to zero
1814 if (do_pad) {
1815 memset(p, 0, pad - len);
1816 p = pdata + pad;
1817 } else {
1818 p = pdata + len;
1820 break;
1822 case SMB_FIND_FILE_NAMES_INFO:
1823 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1824 p += 4;
1825 SIVAL(p,0,reskey); p += 4;
1826 p += 4;
1827 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1828 acl on a dir (tridge) */
1829 len = srvstr_push(base_data, flags2, p,
1830 fname, PTR_DIFF(end_data, p),
1831 STR_TERMINATE_ASCII);
1832 SIVAL(p, -4, len);
1833 p += len;
1835 len = PTR_DIFF(p, pdata);
1836 pad = (len + (align-1)) & ~(align-1);
1838 * offset to the next entry, the caller
1839 * will overwrite it for the last entry
1840 * that's why we always include the padding
1842 SIVAL(pdata,0,pad);
1844 * set padding to zero
1846 if (do_pad) {
1847 memset(p, 0, pad - len);
1848 p = pdata + pad;
1849 } else {
1850 p = pdata + len;
1852 break;
1854 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1855 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1856 p += 4;
1857 SIVAL(p,0,reskey); p += 4;
1858 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1859 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1860 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1861 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1862 SOFF_T(p,0,file_size); p += 8;
1863 SOFF_T(p,0,allocation_size); p += 8;
1864 SIVAL(p,0,nt_extmode); p += 4;
1865 q = p; p += 4; /* q is placeholder for name length. */
1867 unsigned int ea_size = estimate_ea_size(conn, NULL,
1868 smb_fname->base_name);
1869 SIVAL(p,0,ea_size); /* Extended attributes */
1870 p +=4;
1872 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1873 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1874 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1875 len = srvstr_push(base_data, flags2, p,
1876 fname, PTR_DIFF(end_data, p),
1877 STR_TERMINATE_ASCII);
1878 SIVAL(q, 0, len);
1879 p += len;
1881 len = PTR_DIFF(p, pdata);
1882 pad = (len + (align-1)) & ~(align-1);
1884 * offset to the next entry, the caller
1885 * will overwrite it for the last entry
1886 * that's why we always include the padding
1888 SIVAL(pdata,0,pad);
1890 * set padding to zero
1892 if (do_pad) {
1893 memset(p, 0, pad - len);
1894 p = pdata + pad;
1895 } else {
1896 p = pdata + len;
1898 break;
1900 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1901 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1902 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1903 p += 4;
1904 SIVAL(p,0,reskey); p += 4;
1905 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1906 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1907 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1908 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1909 SOFF_T(p,0,file_size); p += 8;
1910 SOFF_T(p,0,allocation_size); p += 8;
1911 SIVAL(p,0,nt_extmode); p += 4;
1912 q = p; p += 4; /* q is placeholder for name length */
1914 unsigned int ea_size = estimate_ea_size(conn, NULL,
1915 smb_fname->base_name);
1916 SIVAL(p,0,ea_size); /* Extended attributes */
1917 p +=4;
1919 /* Clear the short name buffer. This is
1920 * IMPORTANT as not doing so will trigger
1921 * a Win2k client bug. JRA.
1923 if (!was_8_3 && check_mangled_names) {
1924 char mangled_name[13]; /* mangled 8.3 name. */
1925 if (!name_to_8_3(fname,mangled_name,True,
1926 conn->params)) {
1927 /* Error - mangle failed ! */
1928 memset(mangled_name,'\0',12);
1930 mangled_name[12] = 0;
1931 len = srvstr_push(base_data, flags2,
1932 p+2, mangled_name, 24,
1933 STR_UPPER|STR_UNICODE);
1934 SSVAL(p, 0, len);
1935 if (len < 24) {
1936 memset(p + 2 + len,'\0',24 - len);
1938 SSVAL(p, 0, len);
1939 } else {
1940 memset(p,'\0',26);
1942 p += 26;
1943 SSVAL(p,0,0); p += 2; /* Reserved ? */
1944 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1945 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1946 len = srvstr_push(base_data, flags2, p,
1947 fname, PTR_DIFF(end_data, p),
1948 STR_TERMINATE_ASCII);
1949 SIVAL(q,0,len);
1950 p += len;
1952 len = PTR_DIFF(p, pdata);
1953 pad = (len + (align-1)) & ~(align-1);
1955 * offset to the next entry, the caller
1956 * will overwrite it for the last entry
1957 * that's why we always include the padding
1959 SIVAL(pdata,0,pad);
1961 * set padding to zero
1963 if (do_pad) {
1964 memset(p, 0, pad - len);
1965 p = pdata + pad;
1966 } else {
1967 p = pdata + len;
1969 break;
1971 /* CIFS UNIX Extension. */
1973 case SMB_FIND_FILE_UNIX:
1974 case SMB_FIND_FILE_UNIX_INFO2:
1975 p+= 4;
1976 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1978 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1980 if (info_level == SMB_FIND_FILE_UNIX) {
1981 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1982 p = store_file_unix_basic(conn, p,
1983 NULL, &smb_fname->st);
1984 len = srvstr_push(base_data, flags2, p,
1985 fname, PTR_DIFF(end_data, p),
1986 STR_TERMINATE);
1987 } else {
1988 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1989 p = store_file_unix_basic_info2(conn, p,
1990 NULL, &smb_fname->st);
1991 nameptr = p;
1992 p += 4;
1993 len = srvstr_push(base_data, flags2, p, fname,
1994 PTR_DIFF(end_data, p), 0);
1995 SIVAL(nameptr, 0, len);
1998 p += len;
2000 len = PTR_DIFF(p, pdata);
2001 pad = (len + (align-1)) & ~(align-1);
2003 * offset to the next entry, the caller
2004 * will overwrite it for the last entry
2005 * that's why we always include the padding
2007 SIVAL(pdata,0,pad);
2009 * set padding to zero
2011 if (do_pad) {
2012 memset(p, 0, pad - len);
2013 p = pdata + pad;
2014 } else {
2015 p = pdata + len;
2017 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2019 break;
2021 default:
2022 return false;
2025 if (PTR_DIFF(p,pdata) > space_remaining) {
2026 *out_of_space = true;
2027 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2028 return false; /* Not finished - just out of space */
2031 /* Setup the last entry pointer, as an offset from base_data */
2032 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2033 /* Advance the data pointer to the next slot */
2034 *ppdata = p;
2036 return true;
2039 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2040 connection_struct *conn,
2041 struct dptr_struct *dirptr,
2042 uint16 flags2,
2043 const char *path_mask,
2044 uint32 dirtype,
2045 int info_level,
2046 int requires_resume_key,
2047 bool dont_descend,
2048 bool ask_sharemode,
2049 uint8_t align,
2050 bool do_pad,
2051 char **ppdata,
2052 char *base_data,
2053 char *end_data,
2054 int space_remaining,
2055 bool *out_of_space,
2056 bool *got_exact_match,
2057 int *_last_entry_off,
2058 struct ea_list *name_list)
2060 const char *p;
2061 const char *mask = NULL;
2062 long prev_dirpos = 0;
2063 uint32_t mode = 0;
2064 char *fname = NULL;
2065 struct smb_filename *smb_fname = NULL;
2066 struct smbd_dirptr_lanman2_state state;
2067 bool ok;
2068 uint64_t last_entry_off = 0;
2070 ZERO_STRUCT(state);
2071 state.conn = conn;
2072 state.info_level = info_level;
2073 state.check_mangled_names = lp_manglednames(conn->params);
2074 state.has_wild = dptr_has_wild(dirptr);
2075 state.got_exact_match = false;
2077 *out_of_space = false;
2078 *got_exact_match = false;
2080 p = strrchr_m(path_mask,'/');
2081 if(p != NULL) {
2082 if(p[1] == '\0') {
2083 mask = "*.*";
2084 } else {
2085 mask = p+1;
2087 } else {
2088 mask = path_mask;
2091 ok = smbd_dirptr_get_entry(ctx,
2092 dirptr,
2093 mask,
2094 dirtype,
2095 dont_descend,
2096 ask_sharemode,
2097 smbd_dirptr_lanman2_match_fn,
2098 smbd_dirptr_lanman2_mode_fn,
2099 &state,
2100 &fname,
2101 &smb_fname,
2102 &mode,
2103 &prev_dirpos);
2104 if (!ok) {
2105 return false;
2108 *got_exact_match = state.got_exact_match;
2110 ok = smbd_marshall_dir_entry(ctx,
2111 conn,
2112 flags2,
2113 info_level,
2114 name_list,
2115 state.check_mangled_names,
2116 requires_resume_key,
2117 mode,
2118 fname,
2119 smb_fname,
2120 space_remaining,
2121 align,
2122 do_pad,
2123 base_data,
2124 ppdata,
2125 end_data,
2126 out_of_space,
2127 &last_entry_off);
2128 TALLOC_FREE(fname);
2129 TALLOC_FREE(smb_fname);
2130 if (*out_of_space) {
2131 dptr_SeekDir(dirptr, prev_dirpos);
2132 return false;
2134 if (!ok) {
2135 return false;
2138 *_last_entry_off = last_entry_off;
2139 return true;
2142 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2143 connection_struct *conn,
2144 struct dptr_struct *dirptr,
2145 uint16 flags2,
2146 const char *path_mask,
2147 uint32 dirtype,
2148 int info_level,
2149 bool requires_resume_key,
2150 bool dont_descend,
2151 bool ask_sharemode,
2152 char **ppdata,
2153 char *base_data,
2154 char *end_data,
2155 int space_remaining,
2156 bool *out_of_space,
2157 bool *got_exact_match,
2158 int *last_entry_off,
2159 struct ea_list *name_list)
2161 uint8_t align = 4;
2162 const bool do_pad = true;
2164 if (info_level >= 1 && info_level <= 3) {
2165 /* No alignment on earlier info levels. */
2166 align = 1;
2169 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2170 path_mask, dirtype, info_level,
2171 requires_resume_key, dont_descend, ask_sharemode,
2172 align, do_pad,
2173 ppdata, base_data, end_data,
2174 space_remaining,
2175 out_of_space, got_exact_match,
2176 last_entry_off, name_list);
2179 /****************************************************************************
2180 Reply to a TRANS2_FINDFIRST.
2181 ****************************************************************************/
2183 static void call_trans2findfirst(connection_struct *conn,
2184 struct smb_request *req,
2185 char **pparams, int total_params,
2186 char **ppdata, int total_data,
2187 unsigned int max_data_bytes)
2189 /* We must be careful here that we don't return more than the
2190 allowed number of data bytes. If this means returning fewer than
2191 maxentries then so be it. We assume that the redirector has
2192 enough room for the fixed number of parameter bytes it has
2193 requested. */
2194 struct smb_filename *smb_dname = NULL;
2195 char *params = *pparams;
2196 char *pdata = *ppdata;
2197 char *data_end;
2198 uint32 dirtype;
2199 int maxentries;
2200 uint16 findfirst_flags;
2201 bool close_after_first;
2202 bool close_if_end;
2203 bool requires_resume_key;
2204 int info_level;
2205 char *directory = NULL;
2206 char *mask = NULL;
2207 char *p;
2208 int last_entry_off=0;
2209 int dptr_num = -1;
2210 int numentries = 0;
2211 int i;
2212 bool finished = False;
2213 bool dont_descend = False;
2214 bool out_of_space = False;
2215 int space_remaining;
2216 bool mask_contains_wcard = False;
2217 struct ea_list *ea_list = NULL;
2218 NTSTATUS ntstatus = NT_STATUS_OK;
2219 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2220 TALLOC_CTX *ctx = talloc_tos();
2221 struct dptr_struct *dirptr = NULL;
2222 struct smbd_server_connection *sconn = smbd_server_conn;
2224 if (total_params < 13) {
2225 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2226 goto out;
2229 dirtype = SVAL(params,0);
2230 maxentries = SVAL(params,2);
2231 findfirst_flags = SVAL(params,4);
2232 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2233 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2234 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2235 info_level = SVAL(params,6);
2237 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2238 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2239 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2240 info_level, max_data_bytes));
2242 if (!maxentries) {
2243 /* W2K3 seems to treat zero as 1. */
2244 maxentries = 1;
2247 switch (info_level) {
2248 case SMB_FIND_INFO_STANDARD:
2249 case SMB_FIND_EA_SIZE:
2250 case SMB_FIND_EA_LIST:
2251 case SMB_FIND_FILE_DIRECTORY_INFO:
2252 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2253 case SMB_FIND_FILE_NAMES_INFO:
2254 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2255 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2256 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2257 break;
2258 case SMB_FIND_FILE_UNIX:
2259 case SMB_FIND_FILE_UNIX_INFO2:
2260 /* Always use filesystem for UNIX mtime query. */
2261 ask_sharemode = false;
2262 if (!lp_unix_extensions()) {
2263 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2264 goto out;
2266 break;
2267 default:
2268 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2269 goto out;
2272 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2273 params+12, total_params - 12,
2274 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2275 if (!NT_STATUS_IS_OK(ntstatus)) {
2276 reply_nterror(req, ntstatus);
2277 goto out;
2280 ntstatus = filename_convert(ctx, conn,
2281 req->flags2 & FLAGS2_DFS_PATHNAMES,
2282 directory,
2283 (UCF_SAVE_LCOMP |
2284 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2285 &mask_contains_wcard,
2286 &smb_dname);
2287 if (!NT_STATUS_IS_OK(ntstatus)) {
2288 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2289 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2290 ERRSRV, ERRbadpath);
2291 goto out;
2293 reply_nterror(req, ntstatus);
2294 goto out;
2297 mask = smb_dname->original_lcomp;
2299 directory = smb_dname->base_name;
2301 p = strrchr_m(directory,'/');
2302 if(p == NULL) {
2303 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2304 if((directory[0] == '.') && (directory[1] == '\0')) {
2305 mask = talloc_strdup(ctx,"*");
2306 if (!mask) {
2307 reply_nterror(req, NT_STATUS_NO_MEMORY);
2308 goto out;
2310 mask_contains_wcard = True;
2312 directory = talloc_strdup(talloc_tos(), "./");
2313 if (!directory) {
2314 reply_nterror(req, NT_STATUS_NO_MEMORY);
2315 goto out;
2317 } else {
2318 *p = 0;
2321 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2323 if (info_level == SMB_FIND_EA_LIST) {
2324 uint32 ea_size;
2326 if (total_data < 4) {
2327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2328 goto out;
2331 ea_size = IVAL(pdata,0);
2332 if (ea_size != total_data) {
2333 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2334 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2336 goto out;
2339 if (!lp_ea_support(SNUM(conn))) {
2340 reply_doserror(req, ERRDOS, ERReasnotsupported);
2341 goto out;
2344 /* Pull out the list of names. */
2345 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2346 if (!ea_list) {
2347 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2348 goto out;
2352 *ppdata = (char *)SMB_REALLOC(
2353 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2354 if(*ppdata == NULL ) {
2355 reply_nterror(req, NT_STATUS_NO_MEMORY);
2356 goto out;
2358 pdata = *ppdata;
2359 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2361 /* Realloc the params space */
2362 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2363 if (*pparams == NULL) {
2364 reply_nterror(req, NT_STATUS_NO_MEMORY);
2365 goto out;
2367 params = *pparams;
2369 /* Save the wildcard match and attribs we are using on this directory -
2370 needed as lanman2 assumes these are being saved between calls */
2372 ntstatus = dptr_create(conn,
2373 directory,
2374 False,
2375 True,
2376 req->smbpid,
2377 mask,
2378 mask_contains_wcard,
2379 dirtype,
2380 &dirptr);
2382 if (!NT_STATUS_IS_OK(ntstatus)) {
2383 reply_nterror(req, ntstatus);
2384 goto out;
2387 dptr_num = dptr_dnum(dirptr);
2388 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2390 /* Initialize per TRANS2_FIND_FIRST operation data */
2391 dptr_init_search_op(dirptr);
2393 /* We don't need to check for VOL here as this is returned by
2394 a different TRANS2 call. */
2396 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2397 directory,lp_dontdescend(SNUM(conn))));
2398 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2399 dont_descend = True;
2401 p = pdata;
2402 space_remaining = max_data_bytes;
2403 out_of_space = False;
2405 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2406 bool got_exact_match = False;
2408 /* this is a heuristic to avoid seeking the dirptr except when
2409 absolutely necessary. It allows for a filename of about 40 chars */
2410 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2411 out_of_space = True;
2412 finished = False;
2413 } else {
2414 finished = !get_lanman2_dir_entry(ctx,
2415 conn,
2416 dirptr,
2417 req->flags2,
2418 mask,dirtype,info_level,
2419 requires_resume_key,dont_descend,
2420 ask_sharemode,
2421 &p,pdata,data_end,
2422 space_remaining, &out_of_space,
2423 &got_exact_match,
2424 &last_entry_off, ea_list);
2427 if (finished && out_of_space)
2428 finished = False;
2430 if (!finished && !out_of_space)
2431 numentries++;
2434 * As an optimisation if we know we aren't looking
2435 * for a wildcard name (ie. the name matches the wildcard exactly)
2436 * then we can finish on any (first) match.
2437 * This speeds up large directory searches. JRA.
2440 if(got_exact_match)
2441 finished = True;
2443 /* Ensure space_remaining never goes -ve. */
2444 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2445 space_remaining = 0;
2446 out_of_space = true;
2447 } else {
2448 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2452 /* Check if we can close the dirptr */
2453 if(close_after_first || (finished && close_if_end)) {
2454 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2455 dptr_close(sconn, &dptr_num);
2459 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2460 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2461 * the protocol level is less than NT1. Tested with smbclient. JRA.
2462 * This should fix the OS/2 client bug #2335.
2465 if(numentries == 0) {
2466 dptr_close(sconn, &dptr_num);
2467 if (get_Protocol() < PROTOCOL_NT1) {
2468 reply_doserror(req, ERRDOS, ERRnofiles);
2469 goto out;
2470 } else {
2471 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2472 ERRDOS, ERRbadfile);
2473 goto out;
2477 /* At this point pdata points to numentries directory entries. */
2479 /* Set up the return parameter block */
2480 SSVAL(params,0,dptr_num);
2481 SSVAL(params,2,numentries);
2482 SSVAL(params,4,finished);
2483 SSVAL(params,6,0); /* Never an EA error */
2484 SSVAL(params,8,last_entry_off);
2486 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2487 max_data_bytes);
2489 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2490 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2491 if (!directory) {
2492 reply_nterror(req, NT_STATUS_NO_MEMORY);
2496 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2497 smb_fn_name(req->cmd),
2498 mask, directory, dirtype, numentries ) );
2501 * Force a name mangle here to ensure that the
2502 * mask as an 8.3 name is top of the mangled cache.
2503 * The reasons for this are subtle. Don't remove
2504 * this code unless you know what you are doing
2505 * (see PR#13758). JRA.
2508 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2509 char mangled_name[13];
2510 name_to_8_3(mask, mangled_name, True, conn->params);
2512 out:
2513 TALLOC_FREE(smb_dname);
2514 return;
2517 /****************************************************************************
2518 Reply to a TRANS2_FINDNEXT.
2519 ****************************************************************************/
2521 static void call_trans2findnext(connection_struct *conn,
2522 struct smb_request *req,
2523 char **pparams, int total_params,
2524 char **ppdata, int total_data,
2525 unsigned int max_data_bytes)
2527 /* We must be careful here that we don't return more than the
2528 allowed number of data bytes. If this means returning fewer than
2529 maxentries then so be it. We assume that the redirector has
2530 enough room for the fixed number of parameter bytes it has
2531 requested. */
2532 char *params = *pparams;
2533 char *pdata = *ppdata;
2534 char *data_end;
2535 int dptr_num;
2536 int maxentries;
2537 uint16 info_level;
2538 uint32 resume_key;
2539 uint16 findnext_flags;
2540 bool close_after_request;
2541 bool close_if_end;
2542 bool requires_resume_key;
2543 bool continue_bit;
2544 bool mask_contains_wcard = False;
2545 char *resume_name = NULL;
2546 const char *mask = NULL;
2547 const char *directory = NULL;
2548 char *p = NULL;
2549 uint16 dirtype;
2550 int numentries = 0;
2551 int i, last_entry_off=0;
2552 bool finished = False;
2553 bool dont_descend = False;
2554 bool out_of_space = False;
2555 int space_remaining;
2556 struct ea_list *ea_list = NULL;
2557 NTSTATUS ntstatus = NT_STATUS_OK;
2558 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2559 TALLOC_CTX *ctx = talloc_tos();
2560 struct dptr_struct *dirptr;
2561 struct smbd_server_connection *sconn = smbd_server_conn;
2563 if (total_params < 13) {
2564 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2565 return;
2568 dptr_num = SVAL(params,0);
2569 maxentries = SVAL(params,2);
2570 info_level = SVAL(params,4);
2571 resume_key = IVAL(params,6);
2572 findnext_flags = SVAL(params,10);
2573 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2574 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2575 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2576 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2578 if (!continue_bit) {
2579 /* We only need resume_name if continue_bit is zero. */
2580 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2581 params+12,
2582 total_params - 12, STR_TERMINATE, &ntstatus,
2583 &mask_contains_wcard);
2584 if (!NT_STATUS_IS_OK(ntstatus)) {
2585 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2586 complain (it thinks we're asking for the directory above the shared
2587 path or an invalid name). Catch this as the resume name is only compared, never used in
2588 a file access. JRA. */
2589 srvstr_pull_talloc(ctx, params, req->flags2,
2590 &resume_name, params+12,
2591 total_params - 12,
2592 STR_TERMINATE);
2594 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2595 reply_nterror(req, ntstatus);
2596 return;
2601 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2602 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2603 resume_key = %d resume name = %s continue=%d level = %d\n",
2604 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2605 requires_resume_key, resume_key,
2606 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2608 if (!maxentries) {
2609 /* W2K3 seems to treat zero as 1. */
2610 maxentries = 1;
2613 switch (info_level) {
2614 case SMB_FIND_INFO_STANDARD:
2615 case SMB_FIND_EA_SIZE:
2616 case SMB_FIND_EA_LIST:
2617 case SMB_FIND_FILE_DIRECTORY_INFO:
2618 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2619 case SMB_FIND_FILE_NAMES_INFO:
2620 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2621 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2622 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2623 break;
2624 case SMB_FIND_FILE_UNIX:
2625 case SMB_FIND_FILE_UNIX_INFO2:
2626 /* Always use filesystem for UNIX mtime query. */
2627 ask_sharemode = false;
2628 if (!lp_unix_extensions()) {
2629 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2630 return;
2632 break;
2633 default:
2634 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2635 return;
2638 if (info_level == SMB_FIND_EA_LIST) {
2639 uint32 ea_size;
2641 if (total_data < 4) {
2642 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2643 return;
2646 ea_size = IVAL(pdata,0);
2647 if (ea_size != total_data) {
2648 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2649 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2650 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2651 return;
2654 if (!lp_ea_support(SNUM(conn))) {
2655 reply_doserror(req, ERRDOS, ERReasnotsupported);
2656 return;
2659 /* Pull out the list of names. */
2660 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2661 if (!ea_list) {
2662 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2663 return;
2667 *ppdata = (char *)SMB_REALLOC(
2668 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2669 if(*ppdata == NULL) {
2670 reply_nterror(req, NT_STATUS_NO_MEMORY);
2671 return;
2674 pdata = *ppdata;
2675 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2677 /* Realloc the params space */
2678 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2679 if(*pparams == NULL ) {
2680 reply_nterror(req, NT_STATUS_NO_MEMORY);
2681 return;
2684 params = *pparams;
2686 /* Check that the dptr is valid */
2687 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2688 reply_doserror(req, ERRDOS, ERRnofiles);
2689 return;
2692 directory = dptr_path(sconn, dptr_num);
2694 /* Get the wildcard mask from the dptr */
2695 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2696 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2697 reply_doserror(req, ERRDOS, ERRnofiles);
2698 return;
2701 mask = p;
2703 /* Get the attr mask from the dptr */
2704 dirtype = dptr_attr(sconn, dptr_num);
2706 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2707 dptr_num, mask, dirtype,
2708 (long)dirptr,
2709 dptr_TellDir(dirptr)));
2711 /* Initialize per TRANS2_FIND_NEXT operation data */
2712 dptr_init_search_op(dirptr);
2714 /* We don't need to check for VOL here as this is returned by
2715 a different TRANS2 call. */
2717 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2718 directory,lp_dontdescend(SNUM(conn))));
2719 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2720 dont_descend = True;
2722 p = pdata;
2723 space_remaining = max_data_bytes;
2724 out_of_space = False;
2727 * Seek to the correct position. We no longer use the resume key but
2728 * depend on the last file name instead.
2731 if(!continue_bit && resume_name && *resume_name) {
2732 SMB_STRUCT_STAT st;
2734 long current_pos = 0;
2736 * Remember, name_to_8_3 is called by
2737 * get_lanman2_dir_entry(), so the resume name
2738 * could be mangled. Ensure we check the unmangled name.
2741 if (mangle_is_mangled(resume_name, conn->params)) {
2742 char *new_resume_name = NULL;
2743 mangle_lookup_name_from_8_3(ctx,
2744 resume_name,
2745 &new_resume_name,
2746 conn->params);
2747 if (new_resume_name) {
2748 resume_name = new_resume_name;
2753 * Fix for NT redirector problem triggered by resume key indexes
2754 * changing between directory scans. We now return a resume key of 0
2755 * and instead look for the filename to continue from (also given
2756 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2757 * findfirst/findnext (as is usual) then the directory pointer
2758 * should already be at the correct place.
2761 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2762 } /* end if resume_name && !continue_bit */
2764 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2765 bool got_exact_match = False;
2767 /* this is a heuristic to avoid seeking the dirptr except when
2768 absolutely necessary. It allows for a filename of about 40 chars */
2769 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2770 out_of_space = True;
2771 finished = False;
2772 } else {
2773 finished = !get_lanman2_dir_entry(ctx,
2774 conn,
2775 dirptr,
2776 req->flags2,
2777 mask,dirtype,info_level,
2778 requires_resume_key,dont_descend,
2779 ask_sharemode,
2780 &p,pdata,data_end,
2781 space_remaining, &out_of_space,
2782 &got_exact_match,
2783 &last_entry_off, ea_list);
2786 if (finished && out_of_space)
2787 finished = False;
2789 if (!finished && !out_of_space)
2790 numentries++;
2793 * As an optimisation if we know we aren't looking
2794 * for a wildcard name (ie. the name matches the wildcard exactly)
2795 * then we can finish on any (first) match.
2796 * This speeds up large directory searches. JRA.
2799 if(got_exact_match)
2800 finished = True;
2802 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2805 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2806 smb_fn_name(req->cmd),
2807 mask, directory, dirtype, numentries ) );
2809 /* Check if we can close the dirptr */
2810 if(close_after_request || (finished && close_if_end)) {
2811 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2812 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2815 /* Set up the return parameter block */
2816 SSVAL(params,0,numentries);
2817 SSVAL(params,2,finished);
2818 SSVAL(params,4,0); /* Never an EA error */
2819 SSVAL(params,6,last_entry_off);
2821 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2822 max_data_bytes);
2824 return;
2827 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2829 E_md4hash(lp_servicename(SNUM(conn)),objid);
2830 return objid;
2833 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2835 SMB_ASSERT(extended_info != NULL);
2837 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2838 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2839 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2840 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2841 #ifdef SAMBA_VERSION_REVISION
2842 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2843 #endif
2844 extended_info->samba_subversion = 0;
2845 #ifdef SAMBA_VERSION_RC_RELEASE
2846 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2847 #else
2848 #ifdef SAMBA_VERSION_PRE_RELEASE
2849 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2850 #endif
2851 #endif
2852 #ifdef SAMBA_VERSION_VENDOR_PATCH
2853 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2854 #endif
2855 extended_info->samba_gitcommitdate = 0;
2856 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2857 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2858 #endif
2860 memset(extended_info->samba_version_string, 0,
2861 sizeof(extended_info->samba_version_string));
2863 snprintf (extended_info->samba_version_string,
2864 sizeof(extended_info->samba_version_string),
2865 "%s", samba_version_string());
2868 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2869 TALLOC_CTX *mem_ctx,
2870 uint16_t info_level,
2871 uint16_t flags2,
2872 unsigned int max_data_bytes,
2873 char **ppdata,
2874 int *ret_data_len)
2876 char *pdata, *end_data;
2877 int data_len = 0, len;
2878 const char *vname = volume_label(SNUM(conn));
2879 int snum = SNUM(conn);
2880 char *fstype = lp_fstype(SNUM(conn));
2881 uint32 additional_flags = 0;
2882 struct smb_filename smb_fname_dot;
2883 SMB_STRUCT_STAT st;
2885 if (IS_IPC(conn)) {
2886 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2887 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2888 "info level (0x%x) on IPC$.\n",
2889 (unsigned int)info_level));
2890 return NT_STATUS_ACCESS_DENIED;
2894 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2896 ZERO_STRUCT(smb_fname_dot);
2897 smb_fname_dot.base_name = discard_const_p(char, ".");
2899 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2900 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2901 return map_nt_error_from_unix(errno);
2904 st = smb_fname_dot.st;
2906 *ppdata = (char *)SMB_REALLOC(
2907 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2908 if (*ppdata == NULL) {
2909 return NT_STATUS_NO_MEMORY;
2912 pdata = *ppdata;
2913 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2914 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2916 switch (info_level) {
2917 case SMB_INFO_ALLOCATION:
2919 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2920 data_len = 18;
2921 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2922 return map_nt_error_from_unix(errno);
2925 block_size = lp_block_size(snum);
2926 if (bsize < block_size) {
2927 uint64_t factor = block_size/bsize;
2928 bsize = block_size;
2929 dsize /= factor;
2930 dfree /= factor;
2932 if (bsize > block_size) {
2933 uint64_t factor = bsize/block_size;
2934 bsize = block_size;
2935 dsize *= factor;
2936 dfree *= factor;
2938 bytes_per_sector = 512;
2939 sectors_per_unit = bsize/bytes_per_sector;
2941 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2942 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2943 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2945 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2946 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2947 SIVAL(pdata,l1_cUnit,dsize);
2948 SIVAL(pdata,l1_cUnitAvail,dfree);
2949 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2950 break;
2953 case SMB_INFO_VOLUME:
2954 /* Return volume name */
2956 * Add volume serial number - hash of a combination of
2957 * the called hostname and the service name.
2959 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2961 * Win2k3 and previous mess this up by sending a name length
2962 * one byte short. I believe only older clients (OS/2 Win9x) use
2963 * this call so try fixing this by adding a terminating null to
2964 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2966 len = srvstr_push(
2967 pdata, flags2,
2968 pdata+l2_vol_szVolLabel, vname,
2969 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2970 STR_NOALIGN|STR_TERMINATE);
2971 SCVAL(pdata,l2_vol_cch,len);
2972 data_len = l2_vol_szVolLabel + len;
2973 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2974 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2975 len, vname));
2976 break;
2978 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2979 case SMB_FS_ATTRIBUTE_INFORMATION:
2981 additional_flags = 0;
2982 #if defined(HAVE_SYS_QUOTAS)
2983 additional_flags |= FILE_VOLUME_QUOTAS;
2984 #endif
2986 if(lp_nt_acl_support(SNUM(conn))) {
2987 additional_flags |= FILE_PERSISTENT_ACLS;
2990 /* Capabilities are filled in at connection time through STATVFS call */
2991 additional_flags |= conn->fs_capabilities;
2992 additional_flags |= lp_parm_int(conn->params->service,
2993 "share", "fake_fscaps",
2996 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2997 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2998 additional_flags); /* FS ATTRIBUTES */
3000 SIVAL(pdata,4,255); /* Max filename component length */
3001 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3002 and will think we can't do long filenames */
3003 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3004 PTR_DIFF(end_data, pdata+12),
3005 STR_UNICODE);
3006 SIVAL(pdata,8,len);
3007 data_len = 12 + len;
3008 break;
3010 case SMB_QUERY_FS_LABEL_INFO:
3011 case SMB_FS_LABEL_INFORMATION:
3012 len = srvstr_push(pdata, flags2, pdata+4, vname,
3013 PTR_DIFF(end_data, pdata+4), 0);
3014 data_len = 4 + len;
3015 SIVAL(pdata,0,len);
3016 break;
3018 case SMB_QUERY_FS_VOLUME_INFO:
3019 case SMB_FS_VOLUME_INFORMATION:
3022 * Add volume serial number - hash of a combination of
3023 * the called hostname and the service name.
3025 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3026 (str_checksum(get_local_machine_name())<<16));
3028 /* Max label len is 32 characters. */
3029 len = srvstr_push(pdata, flags2, pdata+18, vname,
3030 PTR_DIFF(end_data, pdata+18),
3031 STR_UNICODE);
3032 SIVAL(pdata,12,len);
3033 data_len = 18+len;
3035 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3036 (int)strlen(vname),vname, lp_servicename(snum)));
3037 break;
3039 case SMB_QUERY_FS_SIZE_INFO:
3040 case SMB_FS_SIZE_INFORMATION:
3042 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3043 data_len = 24;
3044 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3045 return map_nt_error_from_unix(errno);
3047 block_size = lp_block_size(snum);
3048 if (bsize < block_size) {
3049 uint64_t factor = block_size/bsize;
3050 bsize = block_size;
3051 dsize /= factor;
3052 dfree /= factor;
3054 if (bsize > block_size) {
3055 uint64_t factor = bsize/block_size;
3056 bsize = block_size;
3057 dsize *= factor;
3058 dfree *= factor;
3060 bytes_per_sector = 512;
3061 sectors_per_unit = bsize/bytes_per_sector;
3062 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3063 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3064 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3065 SBIG_UINT(pdata,0,dsize);
3066 SBIG_UINT(pdata,8,dfree);
3067 SIVAL(pdata,16,sectors_per_unit);
3068 SIVAL(pdata,20,bytes_per_sector);
3069 break;
3072 case SMB_FS_FULL_SIZE_INFORMATION:
3074 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3075 data_len = 32;
3076 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3077 return map_nt_error_from_unix(errno);
3079 block_size = lp_block_size(snum);
3080 if (bsize < block_size) {
3081 uint64_t factor = block_size/bsize;
3082 bsize = block_size;
3083 dsize /= factor;
3084 dfree /= factor;
3086 if (bsize > block_size) {
3087 uint64_t factor = bsize/block_size;
3088 bsize = block_size;
3089 dsize *= factor;
3090 dfree *= factor;
3092 bytes_per_sector = 512;
3093 sectors_per_unit = bsize/bytes_per_sector;
3094 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3095 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3096 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3097 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3098 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3099 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3100 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3101 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3102 break;
3105 case SMB_QUERY_FS_DEVICE_INFO:
3106 case SMB_FS_DEVICE_INFORMATION:
3107 data_len = 8;
3108 SIVAL(pdata,0,0); /* dev type */
3109 SIVAL(pdata,4,0); /* characteristics */
3110 break;
3112 #ifdef HAVE_SYS_QUOTAS
3113 case SMB_FS_QUOTA_INFORMATION:
3115 * what we have to send --metze:
3117 * Unknown1: 24 NULL bytes
3118 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3119 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3120 * Quota Flags: 2 byte :
3121 * Unknown3: 6 NULL bytes
3123 * 48 bytes total
3125 * details for Quota Flags:
3127 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3128 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3129 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3130 * 0x0001 Enable Quotas: enable quota for this fs
3134 /* we need to fake up a fsp here,
3135 * because its not send in this call
3137 files_struct fsp;
3138 SMB_NTQUOTA_STRUCT quotas;
3140 ZERO_STRUCT(fsp);
3141 ZERO_STRUCT(quotas);
3143 fsp.conn = conn;
3144 fsp.fnum = -1;
3146 /* access check */
3147 if (conn->server_info->utok.uid != sec_initial_uid()) {
3148 DEBUG(0,("set_user_quota: access_denied "
3149 "service [%s] user [%s]\n",
3150 lp_servicename(SNUM(conn)),
3151 conn->server_info->unix_name));
3152 return NT_STATUS_ACCESS_DENIED;
3155 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3156 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3157 return map_nt_error_from_unix(errno);
3160 data_len = 48;
3162 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3163 lp_servicename(SNUM(conn))));
3165 /* Unknown1 24 NULL bytes*/
3166 SBIG_UINT(pdata,0,(uint64_t)0);
3167 SBIG_UINT(pdata,8,(uint64_t)0);
3168 SBIG_UINT(pdata,16,(uint64_t)0);
3170 /* Default Soft Quota 8 bytes */
3171 SBIG_UINT(pdata,24,quotas.softlim);
3173 /* Default Hard Quota 8 bytes */
3174 SBIG_UINT(pdata,32,quotas.hardlim);
3176 /* Quota flag 2 bytes */
3177 SSVAL(pdata,40,quotas.qflags);
3179 /* Unknown3 6 NULL bytes */
3180 SSVAL(pdata,42,0);
3181 SIVAL(pdata,44,0);
3183 break;
3185 #endif /* HAVE_SYS_QUOTAS */
3186 case SMB_FS_OBJECTID_INFORMATION:
3188 unsigned char objid[16];
3189 struct smb_extended_info extended_info;
3190 memcpy(pdata,create_volume_objectid(conn, objid),16);
3191 samba_extended_info_version (&extended_info);
3192 SIVAL(pdata,16,extended_info.samba_magic);
3193 SIVAL(pdata,20,extended_info.samba_version);
3194 SIVAL(pdata,24,extended_info.samba_subversion);
3195 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3196 memcpy(pdata+36,extended_info.samba_version_string,28);
3197 data_len = 64;
3198 break;
3202 * Query the version and capabilities of the CIFS UNIX extensions
3203 * in use.
3206 case SMB_QUERY_CIFS_UNIX_INFO:
3208 bool large_write = lp_min_receive_file_size() &&
3209 !srv_is_signing_active(smbd_server_conn);
3210 bool large_read = !srv_is_signing_active(smbd_server_conn);
3211 int encrypt_caps = 0;
3213 if (!lp_unix_extensions()) {
3214 return NT_STATUS_INVALID_LEVEL;
3217 switch (conn->encrypt_level) {
3218 case 0:
3219 encrypt_caps = 0;
3220 break;
3221 case 1:
3222 case Auto:
3223 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3224 break;
3225 case Required:
3226 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3227 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3228 large_write = false;
3229 large_read = false;
3230 break;
3233 data_len = 12;
3234 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3235 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3237 /* We have POSIX ACLs, pathname, encryption,
3238 * large read/write, and locking capability. */
3240 SBIG_UINT(pdata,4,((uint64_t)(
3241 CIFS_UNIX_POSIX_ACLS_CAP|
3242 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3243 CIFS_UNIX_FCNTL_LOCKS_CAP|
3244 CIFS_UNIX_EXTATTR_CAP|
3245 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3246 encrypt_caps|
3247 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3248 (large_write ?
3249 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3250 break;
3253 case SMB_QUERY_POSIX_FS_INFO:
3255 int rc;
3256 vfs_statvfs_struct svfs;
3258 if (!lp_unix_extensions()) {
3259 return NT_STATUS_INVALID_LEVEL;
3262 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3264 if (!rc) {
3265 data_len = 56;
3266 SIVAL(pdata,0,svfs.OptimalTransferSize);
3267 SIVAL(pdata,4,svfs.BlockSize);
3268 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3269 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3270 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3271 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3272 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3273 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3274 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3275 #ifdef EOPNOTSUPP
3276 } else if (rc == EOPNOTSUPP) {
3277 return NT_STATUS_INVALID_LEVEL;
3278 #endif /* EOPNOTSUPP */
3279 } else {
3280 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3281 return NT_STATUS_DOS(ERRSRV, ERRerror);
3283 break;
3286 case SMB_QUERY_POSIX_WHOAMI:
3288 uint32_t flags = 0;
3289 uint32_t sid_bytes;
3290 int i;
3292 if (!lp_unix_extensions()) {
3293 return NT_STATUS_INVALID_LEVEL;
3296 if (max_data_bytes < 40) {
3297 return NT_STATUS_BUFFER_TOO_SMALL;
3300 /* We ARE guest if global_sid_Builtin_Guests is
3301 * in our list of SIDs.
3303 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3304 conn->server_info->ptok)) {
3305 flags |= SMB_WHOAMI_GUEST;
3308 /* We are NOT guest if global_sid_Authenticated_Users
3309 * is in our list of SIDs.
3311 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3312 conn->server_info->ptok)) {
3313 flags &= ~SMB_WHOAMI_GUEST;
3316 /* NOTE: 8 bytes for UID/GID, irrespective of native
3317 * platform size. This matches
3318 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3320 data_len = 4 /* flags */
3321 + 4 /* flag mask */
3322 + 8 /* uid */
3323 + 8 /* gid */
3324 + 4 /* ngroups */
3325 + 4 /* num_sids */
3326 + 4 /* SID bytes */
3327 + 4 /* pad/reserved */
3328 + (conn->server_info->utok.ngroups * 8)
3329 /* groups list */
3330 + (conn->server_info->ptok->num_sids *
3331 SID_MAX_SIZE)
3332 /* SID list */;
3334 SIVAL(pdata, 0, flags);
3335 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3336 SBIG_UINT(pdata, 8,
3337 (uint64_t)conn->server_info->utok.uid);
3338 SBIG_UINT(pdata, 16,
3339 (uint64_t)conn->server_info->utok.gid);
3342 if (data_len >= max_data_bytes) {
3343 /* Potential overflow, skip the GIDs and SIDs. */
3345 SIVAL(pdata, 24, 0); /* num_groups */
3346 SIVAL(pdata, 28, 0); /* num_sids */
3347 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3348 SIVAL(pdata, 36, 0); /* reserved */
3350 data_len = 40;
3351 break;
3354 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3355 SIVAL(pdata, 28, conn->server_info->num_sids);
3357 /* We walk the SID list twice, but this call is fairly
3358 * infrequent, and I don't expect that it's performance
3359 * sensitive -- jpeach
3361 for (i = 0, sid_bytes = 0;
3362 i < conn->server_info->ptok->num_sids; ++i) {
3363 sid_bytes += ndr_size_dom_sid(
3364 &conn->server_info->ptok->user_sids[i],
3365 NULL,
3369 /* SID list byte count */
3370 SIVAL(pdata, 32, sid_bytes);
3372 /* 4 bytes pad/reserved - must be zero */
3373 SIVAL(pdata, 36, 0);
3374 data_len = 40;
3376 /* GID list */
3377 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3378 SBIG_UINT(pdata, data_len,
3379 (uint64_t)conn->server_info->utok.groups[i]);
3380 data_len += 8;
3383 /* SID list */
3384 for (i = 0;
3385 i < conn->server_info->ptok->num_sids; ++i) {
3386 int sid_len = ndr_size_dom_sid(
3387 &conn->server_info->ptok->user_sids[i],
3388 NULL,
3391 sid_linearize(pdata + data_len, sid_len,
3392 &conn->server_info->ptok->user_sids[i]);
3393 data_len += sid_len;
3396 break;
3399 case SMB_MAC_QUERY_FS_INFO:
3401 * Thursby MAC extension... ONLY on NTFS filesystems
3402 * once we do streams then we don't need this
3404 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3405 data_len = 88;
3406 SIVAL(pdata,84,0x100); /* Don't support mac... */
3407 break;
3409 /* drop through */
3410 default:
3411 return NT_STATUS_INVALID_LEVEL;
3414 *ret_data_len = data_len;
3415 return NT_STATUS_OK;
3418 /****************************************************************************
3419 Reply to a TRANS2_QFSINFO (query filesystem info).
3420 ****************************************************************************/
3422 static void call_trans2qfsinfo(connection_struct *conn,
3423 struct smb_request *req,
3424 char **pparams, int total_params,
3425 char **ppdata, int total_data,
3426 unsigned int max_data_bytes)
3428 char *params = *pparams;
3429 uint16_t info_level;
3430 int data_len = 0;
3431 NTSTATUS status;
3433 if (total_params < 2) {
3434 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3435 return;
3438 info_level = SVAL(params,0);
3440 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3441 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3442 DEBUG(0,("call_trans2qfsinfo: encryption required "
3443 "and info level 0x%x sent.\n",
3444 (unsigned int)info_level));
3445 exit_server_cleanly("encryption required "
3446 "on connection");
3447 return;
3451 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3453 status = smbd_do_qfsinfo(conn, req,
3454 info_level,
3455 req->flags2,
3456 max_data_bytes,
3457 ppdata, &data_len);
3458 if (!NT_STATUS_IS_OK(status)) {
3459 reply_nterror(req, status);
3460 return;
3463 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3464 max_data_bytes);
3466 DEBUG( 4, ( "%s info_level = %d\n",
3467 smb_fn_name(req->cmd), info_level) );
3469 return;
3472 /****************************************************************************
3473 Reply to a TRANS2_SETFSINFO (set filesystem info).
3474 ****************************************************************************/
3476 static void call_trans2setfsinfo(connection_struct *conn,
3477 struct smb_request *req,
3478 char **pparams, int total_params,
3479 char **ppdata, int total_data,
3480 unsigned int max_data_bytes)
3482 char *pdata = *ppdata;
3483 char *params = *pparams;
3484 uint16 info_level;
3486 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3488 /* */
3489 if (total_params < 4) {
3490 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3491 total_params));
3492 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3493 return;
3496 info_level = SVAL(params,2);
3498 if (IS_IPC(conn)) {
3499 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3500 info_level != SMB_SET_CIFS_UNIX_INFO) {
3501 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3502 "info level (0x%x) on IPC$.\n",
3503 (unsigned int)info_level));
3504 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3505 return;
3509 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3510 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3511 DEBUG(0,("call_trans2setfsinfo: encryption required "
3512 "and info level 0x%x sent.\n",
3513 (unsigned int)info_level));
3514 exit_server_cleanly("encryption required "
3515 "on connection");
3516 return;
3520 switch(info_level) {
3521 case SMB_SET_CIFS_UNIX_INFO:
3523 uint16 client_unix_major;
3524 uint16 client_unix_minor;
3525 uint32 client_unix_cap_low;
3526 uint32 client_unix_cap_high;
3528 if (!lp_unix_extensions()) {
3529 reply_nterror(req,
3530 NT_STATUS_INVALID_LEVEL);
3531 return;
3534 /* There should be 12 bytes of capabilities set. */
3535 if (total_data < 8) {
3536 reply_nterror(
3537 req,
3538 NT_STATUS_INVALID_PARAMETER);
3539 return;
3541 client_unix_major = SVAL(pdata,0);
3542 client_unix_minor = SVAL(pdata,2);
3543 client_unix_cap_low = IVAL(pdata,4);
3544 client_unix_cap_high = IVAL(pdata,8);
3545 /* Just print these values for now. */
3546 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3547 cap_low = 0x%x, cap_high = 0x%x\n",
3548 (unsigned int)client_unix_major,
3549 (unsigned int)client_unix_minor,
3550 (unsigned int)client_unix_cap_low,
3551 (unsigned int)client_unix_cap_high ));
3553 /* Here is where we must switch to posix pathname processing... */
3554 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3555 lp_set_posix_pathnames();
3556 mangle_change_to_posix();
3559 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3560 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3561 /* Client that knows how to do posix locks,
3562 * but not posix open/mkdir operations. Set a
3563 * default type for read/write checks. */
3565 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3568 break;
3571 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3573 NTSTATUS status;
3574 size_t param_len = 0;
3575 size_t data_len = total_data;
3577 if (!lp_unix_extensions()) {
3578 reply_nterror(
3579 req,
3580 NT_STATUS_INVALID_LEVEL);
3581 return;
3584 if (lp_smb_encrypt(SNUM(conn)) == false) {
3585 reply_nterror(
3586 req,
3587 NT_STATUS_NOT_SUPPORTED);
3588 return;
3591 DEBUG( 4,("call_trans2setfsinfo: "
3592 "request transport encryption.\n"));
3594 status = srv_request_encryption_setup(conn,
3595 (unsigned char **)ppdata,
3596 &data_len,
3597 (unsigned char **)pparams,
3598 &param_len);
3600 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3601 !NT_STATUS_IS_OK(status)) {
3602 reply_nterror(req, status);
3603 return;
3606 send_trans2_replies(conn, req,
3607 *pparams,
3608 param_len,
3609 *ppdata,
3610 data_len,
3611 max_data_bytes);
3613 if (NT_STATUS_IS_OK(status)) {
3614 /* Server-side transport
3615 * encryption is now *on*. */
3616 status = srv_encryption_start(conn);
3617 if (!NT_STATUS_IS_OK(status)) {
3618 exit_server_cleanly(
3619 "Failure in setting "
3620 "up encrypted transport");
3623 return;
3626 case SMB_FS_QUOTA_INFORMATION:
3628 files_struct *fsp = NULL;
3629 SMB_NTQUOTA_STRUCT quotas;
3631 ZERO_STRUCT(quotas);
3633 /* access check */
3634 if ((conn->server_info->utok.uid != sec_initial_uid())
3635 ||!CAN_WRITE(conn)) {
3636 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3637 lp_servicename(SNUM(conn)),
3638 conn->server_info->unix_name));
3639 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3640 return;
3643 /* note: normaly there're 48 bytes,
3644 * but we didn't use the last 6 bytes for now
3645 * --metze
3647 fsp = file_fsp(req, SVAL(params,0));
3649 if (!check_fsp_ntquota_handle(conn, req,
3650 fsp)) {
3651 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3652 reply_nterror(
3653 req, NT_STATUS_INVALID_HANDLE);
3654 return;
3657 if (total_data < 42) {
3658 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3659 total_data));
3660 reply_nterror(
3661 req,
3662 NT_STATUS_INVALID_PARAMETER);
3663 return;
3666 /* unknown_1 24 NULL bytes in pdata*/
3668 /* the soft quotas 8 bytes (uint64_t)*/
3669 quotas.softlim = (uint64_t)IVAL(pdata,24);
3670 #ifdef LARGE_SMB_OFF_T
3671 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3672 #else /* LARGE_SMB_OFF_T */
3673 if ((IVAL(pdata,28) != 0)&&
3674 ((quotas.softlim != 0xFFFFFFFF)||
3675 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3676 /* more than 32 bits? */
3677 reply_nterror(
3678 req,
3679 NT_STATUS_INVALID_PARAMETER);
3680 return;
3682 #endif /* LARGE_SMB_OFF_T */
3684 /* the hard quotas 8 bytes (uint64_t)*/
3685 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3686 #ifdef LARGE_SMB_OFF_T
3687 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3688 #else /* LARGE_SMB_OFF_T */
3689 if ((IVAL(pdata,36) != 0)&&
3690 ((quotas.hardlim != 0xFFFFFFFF)||
3691 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3692 /* more than 32 bits? */
3693 reply_nterror(
3694 req,
3695 NT_STATUS_INVALID_PARAMETER);
3696 return;
3698 #endif /* LARGE_SMB_OFF_T */
3700 /* quota_flags 2 bytes **/
3701 quotas.qflags = SVAL(pdata,40);
3703 /* unknown_2 6 NULL bytes follow*/
3705 /* now set the quotas */
3706 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3707 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3708 reply_nterror(req, map_nt_error_from_unix(errno));
3709 return;
3712 break;
3714 default:
3715 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3716 info_level));
3717 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3718 return;
3719 break;
3723 * sending this reply works fine,
3724 * but I'm not sure it's the same
3725 * like windows do...
3726 * --metze
3728 reply_outbuf(req, 10, 0);
3731 #if defined(HAVE_POSIX_ACLS)
3732 /****************************************************************************
3733 Utility function to count the number of entries in a POSIX acl.
3734 ****************************************************************************/
3736 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3738 unsigned int ace_count = 0;
3739 int entry_id = SMB_ACL_FIRST_ENTRY;
3740 SMB_ACL_ENTRY_T entry;
3742 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3743 /* get_next... */
3744 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3745 entry_id = SMB_ACL_NEXT_ENTRY;
3747 ace_count++;
3749 return ace_count;
3752 /****************************************************************************
3753 Utility function to marshall a POSIX acl into wire format.
3754 ****************************************************************************/
3756 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3758 int entry_id = SMB_ACL_FIRST_ENTRY;
3759 SMB_ACL_ENTRY_T entry;
3761 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3762 SMB_ACL_TAG_T tagtype;
3763 SMB_ACL_PERMSET_T permset;
3764 unsigned char perms = 0;
3765 unsigned int own_grp;
3767 /* get_next... */
3768 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3769 entry_id = SMB_ACL_NEXT_ENTRY;
3772 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3773 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3774 return False;
3777 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3778 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3779 return False;
3782 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3783 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3784 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3786 SCVAL(pdata,1,perms);
3788 switch (tagtype) {
3789 case SMB_ACL_USER_OBJ:
3790 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3791 own_grp = (unsigned int)pst->st_ex_uid;
3792 SIVAL(pdata,2,own_grp);
3793 SIVAL(pdata,6,0);
3794 break;
3795 case SMB_ACL_USER:
3797 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3798 if (!puid) {
3799 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3800 return False;
3802 own_grp = (unsigned int)*puid;
3803 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3804 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3805 SIVAL(pdata,2,own_grp);
3806 SIVAL(pdata,6,0);
3807 break;
3809 case SMB_ACL_GROUP_OBJ:
3810 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3811 own_grp = (unsigned int)pst->st_ex_gid;
3812 SIVAL(pdata,2,own_grp);
3813 SIVAL(pdata,6,0);
3814 break;
3815 case SMB_ACL_GROUP:
3817 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3818 if (!pgid) {
3819 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3820 return False;
3822 own_grp = (unsigned int)*pgid;
3823 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3824 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3825 SIVAL(pdata,2,own_grp);
3826 SIVAL(pdata,6,0);
3827 break;
3829 case SMB_ACL_MASK:
3830 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3831 SIVAL(pdata,2,0xFFFFFFFF);
3832 SIVAL(pdata,6,0xFFFFFFFF);
3833 break;
3834 case SMB_ACL_OTHER:
3835 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3836 SIVAL(pdata,2,0xFFFFFFFF);
3837 SIVAL(pdata,6,0xFFFFFFFF);
3838 break;
3839 default:
3840 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3841 return False;
3843 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3846 return True;
3848 #endif
3850 /****************************************************************************
3851 Store the FILE_UNIX_BASIC info.
3852 ****************************************************************************/
3854 static char *store_file_unix_basic(connection_struct *conn,
3855 char *pdata,
3856 files_struct *fsp,
3857 const SMB_STRUCT_STAT *psbuf)
3859 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3860 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3862 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3863 pdata += 8;
3865 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3866 pdata += 8;
3868 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3869 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3870 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3871 pdata += 24;
3873 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3874 SIVAL(pdata,4,0);
3875 pdata += 8;
3877 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3878 SIVAL(pdata,4,0);
3879 pdata += 8;
3881 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3882 pdata += 4;
3884 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3885 SIVAL(pdata,4,0);
3886 pdata += 8;
3888 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3889 SIVAL(pdata,4,0);
3890 pdata += 8;
3892 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3893 pdata += 8;
3895 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3896 SIVAL(pdata,4,0);
3897 pdata += 8;
3899 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3900 SIVAL(pdata,4,0);
3901 pdata += 8;
3903 return pdata;
3906 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3907 * the chflags(2) (or equivalent) flags.
3909 * XXX: this really should be behind the VFS interface. To do this, we would
3910 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3911 * Each VFS module could then implement its own mapping as appropriate for the
3912 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3914 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3915 info2_flags_map[] =
3917 #ifdef UF_NODUMP
3918 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3919 #endif
3921 #ifdef UF_IMMUTABLE
3922 { UF_IMMUTABLE, EXT_IMMUTABLE },
3923 #endif
3925 #ifdef UF_APPEND
3926 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3927 #endif
3929 #ifdef UF_HIDDEN
3930 { UF_HIDDEN, EXT_HIDDEN },
3931 #endif
3933 /* Do not remove. We need to guarantee that this array has at least one
3934 * entry to build on HP-UX.
3936 { 0, 0 }
3940 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3941 uint32 *smb_fflags, uint32 *smb_fmask)
3943 int i;
3945 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3946 *smb_fmask |= info2_flags_map[i].smb_fflag;
3947 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3948 *smb_fflags |= info2_flags_map[i].smb_fflag;
3953 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3954 const uint32 smb_fflags,
3955 const uint32 smb_fmask,
3956 int *stat_fflags)
3958 uint32 max_fmask = 0;
3959 int i;
3961 *stat_fflags = psbuf->st_ex_flags;
3963 /* For each flags requested in smb_fmask, check the state of the
3964 * corresponding flag in smb_fflags and set or clear the matching
3965 * stat flag.
3968 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3969 max_fmask |= info2_flags_map[i].smb_fflag;
3970 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3971 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3972 *stat_fflags |= info2_flags_map[i].stat_fflag;
3973 } else {
3974 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3979 /* If smb_fmask is asking to set any bits that are not supported by
3980 * our flag mappings, we should fail.
3982 if ((smb_fmask & max_fmask) != smb_fmask) {
3983 return False;
3986 return True;
3990 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3991 * of file flags and birth (create) time.
3993 static char *store_file_unix_basic_info2(connection_struct *conn,
3994 char *pdata,
3995 files_struct *fsp,
3996 const SMB_STRUCT_STAT *psbuf)
3998 uint32 file_flags = 0;
3999 uint32 flags_mask = 0;
4001 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4003 /* Create (birth) time 64 bit */
4004 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4005 pdata += 8;
4007 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4008 SIVAL(pdata, 0, file_flags); /* flags */
4009 SIVAL(pdata, 4, flags_mask); /* mask */
4010 pdata += 8;
4012 return pdata;
4015 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4016 const struct stream_struct *streams,
4017 char *data,
4018 unsigned int max_data_bytes,
4019 unsigned int *data_size)
4021 unsigned int i;
4022 unsigned int ofs = 0;
4024 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4025 unsigned int next_offset;
4026 size_t namelen;
4027 smb_ucs2_t *namebuf;
4029 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4030 streams[i].name, &namelen) ||
4031 namelen <= 2)
4033 return NT_STATUS_INVALID_PARAMETER;
4037 * name_buf is now null-terminated, we need to marshall as not
4038 * terminated
4041 namelen -= 2;
4043 SIVAL(data, ofs+4, namelen);
4044 SOFF_T(data, ofs+8, streams[i].size);
4045 SOFF_T(data, ofs+16, streams[i].alloc_size);
4046 memcpy(data+ofs+24, namebuf, namelen);
4047 TALLOC_FREE(namebuf);
4049 next_offset = ofs + 24 + namelen;
4051 if (i == num_streams-1) {
4052 SIVAL(data, ofs, 0);
4054 else {
4055 unsigned int align = ndr_align_size(next_offset, 8);
4057 memset(data+next_offset, 0, align);
4058 next_offset += align;
4060 SIVAL(data, ofs, next_offset - ofs);
4061 ofs = next_offset;
4064 ofs = next_offset;
4067 *data_size = ofs;
4069 return NT_STATUS_OK;
4072 /****************************************************************************
4073 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4074 ****************************************************************************/
4076 static void call_trans2qpipeinfo(connection_struct *conn,
4077 struct smb_request *req,
4078 unsigned int tran_call,
4079 char **pparams, int total_params,
4080 char **ppdata, int total_data,
4081 unsigned int max_data_bytes)
4083 char *params = *pparams;
4084 char *pdata = *ppdata;
4085 unsigned int data_size = 0;
4086 unsigned int param_size = 2;
4087 uint16 info_level;
4088 files_struct *fsp;
4090 if (!params) {
4091 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4092 return;
4095 if (total_params < 4) {
4096 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4097 return;
4100 fsp = file_fsp(req, SVAL(params,0));
4101 if (!fsp_is_np(fsp)) {
4102 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4103 return;
4106 info_level = SVAL(params,2);
4108 *pparams = (char *)SMB_REALLOC(*pparams,2);
4109 if (*pparams == NULL) {
4110 reply_nterror(req, NT_STATUS_NO_MEMORY);
4111 return;
4113 params = *pparams;
4114 SSVAL(params,0,0);
4115 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4116 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4117 if (*ppdata == NULL ) {
4118 reply_nterror(req, NT_STATUS_NO_MEMORY);
4119 return;
4121 pdata = *ppdata;
4123 switch (info_level) {
4124 case SMB_FILE_STANDARD_INFORMATION:
4125 memset(pdata,0,24);
4126 SOFF_T(pdata,0,4096LL);
4127 SIVAL(pdata,16,1);
4128 SIVAL(pdata,20,1);
4129 data_size = 24;
4130 break;
4132 default:
4133 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4134 return;
4137 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4138 max_data_bytes);
4140 return;
4143 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4144 TALLOC_CTX *mem_ctx,
4145 uint16_t info_level,
4146 files_struct *fsp,
4147 struct smb_filename *smb_fname,
4148 bool delete_pending,
4149 struct timespec write_time_ts,
4150 bool ms_dfs_link,
4151 struct ea_list *ea_list,
4152 int lock_data_count,
4153 char *lock_data,
4154 uint16_t flags2,
4155 unsigned int max_data_bytes,
4156 char **ppdata,
4157 unsigned int *pdata_size)
4159 char *pdata = *ppdata;
4160 char *dstart, *dend;
4161 unsigned int data_size;
4162 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4163 time_t create_time, mtime, atime, c_time;
4164 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4165 char *p;
4166 char *base_name;
4167 char *dos_fname;
4168 int mode;
4169 int nlink;
4170 NTSTATUS status;
4171 uint64_t file_size = 0;
4172 uint64_t pos = 0;
4173 uint64_t allocation_size = 0;
4174 uint64_t file_index = 0;
4175 uint32_t access_mask = 0;
4177 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4178 return NT_STATUS_INVALID_LEVEL;
4181 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4182 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4183 info_level, max_data_bytes));
4185 if (ms_dfs_link) {
4186 mode = dos_mode_msdfs(conn, smb_fname);
4187 } else {
4188 mode = dos_mode(conn, smb_fname);
4190 if (!mode)
4191 mode = FILE_ATTRIBUTE_NORMAL;
4193 nlink = psbuf->st_ex_nlink;
4195 if (nlink && (mode&aDIR)) {
4196 nlink = 1;
4199 if ((nlink > 0) && delete_pending) {
4200 nlink -= 1;
4203 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4204 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4205 if (*ppdata == NULL) {
4206 return NT_STATUS_NO_MEMORY;
4208 pdata = *ppdata;
4209 dstart = pdata;
4210 dend = dstart + data_size - 1;
4212 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4213 update_stat_ex_mtime(psbuf, write_time_ts);
4216 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4217 mtime_ts = psbuf->st_ex_mtime;
4218 atime_ts = psbuf->st_ex_atime;
4219 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4221 if (lp_dos_filetime_resolution(SNUM(conn))) {
4222 dos_filetime_timespec(&create_time_ts);
4223 dos_filetime_timespec(&mtime_ts);
4224 dos_filetime_timespec(&atime_ts);
4225 dos_filetime_timespec(&ctime_ts);
4228 create_time = convert_timespec_to_time_t(create_time_ts);
4229 mtime = convert_timespec_to_time_t(mtime_ts);
4230 atime = convert_timespec_to_time_t(atime_ts);
4231 c_time = convert_timespec_to_time_t(ctime_ts);
4233 p = strrchr_m(smb_fname->base_name,'/');
4234 if (!p)
4235 base_name = smb_fname->base_name;
4236 else
4237 base_name = p+1;
4239 /* NT expects the name to be in an exact form of the *full*
4240 filename. See the trans2 torture test */
4241 if (ISDOT(base_name)) {
4242 dos_fname = talloc_strdup(mem_ctx, "\\");
4243 if (!dos_fname) {
4244 return NT_STATUS_NO_MEMORY;
4246 } else {
4247 dos_fname = talloc_asprintf(mem_ctx,
4248 "\\%s",
4249 smb_fname->base_name);
4250 if (!dos_fname) {
4251 return NT_STATUS_NO_MEMORY;
4253 if (is_ntfs_stream_smb_fname(smb_fname)) {
4254 dos_fname = talloc_asprintf(dos_fname, "%s",
4255 smb_fname->stream_name);
4256 if (!dos_fname) {
4257 return NT_STATUS_NO_MEMORY;
4261 string_replace(dos_fname, '/', '\\');
4264 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4266 if (!fsp) {
4267 /* Do we have this path open ? */
4268 files_struct *fsp1;
4269 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4270 fsp1 = file_find_di_first(fileid);
4271 if (fsp1 && fsp1->initial_allocation_size) {
4272 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4276 if (!(mode & aDIR)) {
4277 file_size = get_file_size_stat(psbuf);
4280 if (fsp) {
4281 pos = fsp->fh->position_information;
4284 if (fsp) {
4285 access_mask = fsp->access_mask;
4286 } else {
4287 /* GENERIC_EXECUTE mapping from Windows */
4288 access_mask = 0x12019F;
4291 /* This should be an index number - looks like
4292 dev/ino to me :-)
4294 I think this causes us to fail the IFSKIT
4295 BasicFileInformationTest. -tpot */
4296 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4297 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4299 switch (info_level) {
4300 case SMB_INFO_STANDARD:
4301 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4302 data_size = 22;
4303 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4304 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4305 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4306 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4307 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4308 SSVAL(pdata,l1_attrFile,mode);
4309 break;
4311 case SMB_INFO_QUERY_EA_SIZE:
4313 unsigned int ea_size =
4314 estimate_ea_size(conn, fsp,
4315 smb_fname->base_name);
4316 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4317 data_size = 26;
4318 srv_put_dos_date2(pdata,0,create_time);
4319 srv_put_dos_date2(pdata,4,atime);
4320 srv_put_dos_date2(pdata,8,mtime); /* write time */
4321 SIVAL(pdata,12,(uint32)file_size);
4322 SIVAL(pdata,16,(uint32)allocation_size);
4323 SSVAL(pdata,20,mode);
4324 SIVAL(pdata,22,ea_size);
4325 break;
4328 case SMB_INFO_IS_NAME_VALID:
4329 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4330 if (fsp) {
4331 /* os/2 needs this ? really ?*/
4332 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4334 /* This is only reached for qpathinfo */
4335 data_size = 0;
4336 break;
4338 case SMB_INFO_QUERY_EAS_FROM_LIST:
4340 size_t total_ea_len = 0;
4341 struct ea_list *ea_file_list = NULL;
4343 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4345 ea_file_list =
4346 get_ea_list_from_file(mem_ctx, conn, fsp,
4347 smb_fname->base_name,
4348 &total_ea_len);
4349 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4351 if (!ea_list || (total_ea_len > data_size)) {
4352 data_size = 4;
4353 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4354 break;
4357 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4358 break;
4361 case SMB_INFO_QUERY_ALL_EAS:
4363 /* We have data_size bytes to put EA's into. */
4364 size_t total_ea_len = 0;
4366 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4368 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4369 smb_fname->base_name,
4370 &total_ea_len);
4371 if (!ea_list || (total_ea_len > data_size)) {
4372 data_size = 4;
4373 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4374 break;
4377 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4378 break;
4381 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4383 /* This is FileFullEaInformation - 0xF which maps to
4384 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4386 /* We have data_size bytes to put EA's into. */
4387 size_t total_ea_len = 0;
4388 struct ea_list *ea_file_list = NULL;
4390 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4392 /*TODO: add filtering and index handling */
4394 ea_file_list =
4395 get_ea_list_from_file(mem_ctx, conn, fsp,
4396 smb_fname->base_name,
4397 &total_ea_len);
4398 if (!ea_file_list) {
4399 return NT_STATUS_NO_EAS_ON_FILE;
4402 status = fill_ea_chained_buffer(mem_ctx,
4403 pdata,
4404 data_size,
4405 &data_size,
4406 conn, ea_file_list);
4407 if (!NT_STATUS_IS_OK(status)) {
4408 return status;
4410 break;
4413 case SMB_FILE_BASIC_INFORMATION:
4414 case SMB_QUERY_FILE_BASIC_INFO:
4416 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4417 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4418 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4419 } else {
4420 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4421 data_size = 40;
4422 SIVAL(pdata,36,0);
4424 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4425 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4426 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4427 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4428 SIVAL(pdata,32,mode);
4430 DEBUG(5,("SMB_QFBI - "));
4431 DEBUG(5,("create: %s ", ctime(&create_time)));
4432 DEBUG(5,("access: %s ", ctime(&atime)));
4433 DEBUG(5,("write: %s ", ctime(&mtime)));
4434 DEBUG(5,("change: %s ", ctime(&c_time)));
4435 DEBUG(5,("mode: %x\n", mode));
4436 break;
4438 case SMB_FILE_STANDARD_INFORMATION:
4439 case SMB_QUERY_FILE_STANDARD_INFO:
4441 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4442 data_size = 24;
4443 SOFF_T(pdata,0,allocation_size);
4444 SOFF_T(pdata,8,file_size);
4445 SIVAL(pdata,16,nlink);
4446 SCVAL(pdata,20,delete_pending?1:0);
4447 SCVAL(pdata,21,(mode&aDIR)?1:0);
4448 SSVAL(pdata,22,0); /* Padding. */
4449 break;
4451 case SMB_FILE_EA_INFORMATION:
4452 case SMB_QUERY_FILE_EA_INFO:
4454 unsigned int ea_size =
4455 estimate_ea_size(conn, fsp, smb_fname->base_name);
4456 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4457 data_size = 4;
4458 SIVAL(pdata,0,ea_size);
4459 break;
4462 /* Get the 8.3 name - used if NT SMB was negotiated. */
4463 case SMB_QUERY_FILE_ALT_NAME_INFO:
4464 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4466 int len;
4467 char mangled_name[13];
4468 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4469 if (!name_to_8_3(base_name,mangled_name,
4470 True,conn->params)) {
4471 return NT_STATUS_NO_MEMORY;
4473 len = srvstr_push(dstart, flags2,
4474 pdata+4, mangled_name,
4475 PTR_DIFF(dend, pdata+4),
4476 STR_UNICODE);
4477 data_size = 4 + len;
4478 SIVAL(pdata,0,len);
4479 break;
4482 case SMB_QUERY_FILE_NAME_INFO:
4484 int len;
4486 this must be *exactly* right for ACLs on mapped drives to work
4488 len = srvstr_push(dstart, flags2,
4489 pdata+4, dos_fname,
4490 PTR_DIFF(dend, pdata+4),
4491 STR_UNICODE);
4492 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4493 data_size = 4 + len;
4494 SIVAL(pdata,0,len);
4495 break;
4498 case SMB_FILE_ALLOCATION_INFORMATION:
4499 case SMB_QUERY_FILE_ALLOCATION_INFO:
4500 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4501 data_size = 8;
4502 SOFF_T(pdata,0,allocation_size);
4503 break;
4505 case SMB_FILE_END_OF_FILE_INFORMATION:
4506 case SMB_QUERY_FILE_END_OF_FILEINFO:
4507 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4508 data_size = 8;
4509 SOFF_T(pdata,0,file_size);
4510 break;
4512 case SMB_QUERY_FILE_ALL_INFO:
4513 case SMB_FILE_ALL_INFORMATION:
4515 int len;
4516 unsigned int ea_size =
4517 estimate_ea_size(conn, fsp, smb_fname->base_name);
4518 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4519 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4520 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4521 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4522 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4523 SIVAL(pdata,32,mode);
4524 SIVAL(pdata,36,0); /* padding. */
4525 pdata += 40;
4526 SOFF_T(pdata,0,allocation_size);
4527 SOFF_T(pdata,8,file_size);
4528 SIVAL(pdata,16,nlink);
4529 SCVAL(pdata,20,delete_pending);
4530 SCVAL(pdata,21,(mode&aDIR)?1:0);
4531 SSVAL(pdata,22,0);
4532 pdata += 24;
4533 SIVAL(pdata,0,ea_size);
4534 pdata += 4; /* EA info */
4535 len = srvstr_push(dstart, flags2,
4536 pdata+4, dos_fname,
4537 PTR_DIFF(dend, pdata+4),
4538 STR_UNICODE);
4539 SIVAL(pdata,0,len);
4540 pdata += 4 + len;
4541 data_size = PTR_DIFF(pdata,(*ppdata));
4542 break;
4545 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4547 int len;
4548 unsigned int ea_size =
4549 estimate_ea_size(conn, fsp, smb_fname->base_name);
4550 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4551 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4552 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4553 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4554 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4555 SIVAL(pdata, 0x20, mode);
4556 SIVAL(pdata, 0x24, 0); /* padding. */
4557 SBVAL(pdata, 0x28, allocation_size);
4558 SBVAL(pdata, 0x30, file_size);
4559 SIVAL(pdata, 0x38, nlink);
4560 SCVAL(pdata, 0x3C, delete_pending);
4561 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4562 SSVAL(pdata, 0x3E, 0); /* padding */
4563 SBVAL(pdata, 0x40, file_index);
4564 SIVAL(pdata, 0x48, ea_size);
4565 SIVAL(pdata, 0x4C, access_mask);
4566 SBVAL(pdata, 0x50, pos);
4567 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4568 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4570 pdata += 0x60;
4572 len = srvstr_push(dstart, flags2,
4573 pdata+4, dos_fname,
4574 PTR_DIFF(dend, pdata+4),
4575 STR_UNICODE);
4576 SIVAL(pdata,0,len);
4577 pdata += 4 + len;
4578 data_size = PTR_DIFF(pdata,(*ppdata));
4579 break;
4581 case SMB_FILE_INTERNAL_INFORMATION:
4583 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4584 SBVAL(pdata, 0, file_index);
4585 data_size = 8;
4586 break;
4588 case SMB_FILE_ACCESS_INFORMATION:
4589 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4590 SIVAL(pdata, 0, access_mask);
4591 data_size = 4;
4592 break;
4594 case SMB_FILE_NAME_INFORMATION:
4595 /* Pathname with leading '\'. */
4597 size_t byte_len;
4598 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4599 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4600 SIVAL(pdata,0,byte_len);
4601 data_size = 4 + byte_len;
4602 break;
4605 case SMB_FILE_DISPOSITION_INFORMATION:
4606 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4607 data_size = 1;
4608 SCVAL(pdata,0,delete_pending);
4609 break;
4611 case SMB_FILE_POSITION_INFORMATION:
4612 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4613 data_size = 8;
4614 SOFF_T(pdata,0,pos);
4615 break;
4617 case SMB_FILE_MODE_INFORMATION:
4618 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4619 SIVAL(pdata,0,mode);
4620 data_size = 4;
4621 break;
4623 case SMB_FILE_ALIGNMENT_INFORMATION:
4624 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4625 SIVAL(pdata,0,0); /* No alignment needed. */
4626 data_size = 4;
4627 break;
4630 * NT4 server just returns "invalid query" to this - if we try
4631 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4632 * want this. JRA.
4634 /* The first statement above is false - verified using Thursby
4635 * client against NT4 -- gcolley.
4637 case SMB_QUERY_FILE_STREAM_INFO:
4638 case SMB_FILE_STREAM_INFORMATION: {
4639 unsigned int num_streams;
4640 struct stream_struct *streams;
4642 DEBUG(10,("smbd_do_qfilepathinfo: "
4643 "SMB_FILE_STREAM_INFORMATION\n"));
4645 if (is_ntfs_stream_smb_fname(smb_fname)) {
4646 return NT_STATUS_INVALID_PARAMETER;
4649 status = SMB_VFS_STREAMINFO(
4650 conn, fsp, smb_fname->base_name, talloc_tos(),
4651 &num_streams, &streams);
4653 if (!NT_STATUS_IS_OK(status)) {
4654 DEBUG(10, ("could not get stream info: %s\n",
4655 nt_errstr(status)));
4656 return status;
4659 status = marshall_stream_info(num_streams, streams,
4660 pdata, max_data_bytes,
4661 &data_size);
4663 if (!NT_STATUS_IS_OK(status)) {
4664 DEBUG(10, ("marshall_stream_info failed: %s\n",
4665 nt_errstr(status)));
4666 return status;
4669 TALLOC_FREE(streams);
4671 break;
4673 case SMB_QUERY_COMPRESSION_INFO:
4674 case SMB_FILE_COMPRESSION_INFORMATION:
4675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4676 SOFF_T(pdata,0,file_size);
4677 SIVAL(pdata,8,0); /* ??? */
4678 SIVAL(pdata,12,0); /* ??? */
4679 data_size = 16;
4680 break;
4682 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4683 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4684 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4685 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4686 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4687 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4688 SOFF_T(pdata,32,allocation_size);
4689 SOFF_T(pdata,40,file_size);
4690 SIVAL(pdata,48,mode);
4691 SIVAL(pdata,52,0); /* ??? */
4692 data_size = 56;
4693 break;
4695 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4696 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4697 SIVAL(pdata,0,mode);
4698 SIVAL(pdata,4,0);
4699 data_size = 8;
4700 break;
4703 * CIFS UNIX Extensions.
4706 case SMB_QUERY_FILE_UNIX_BASIC:
4708 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4709 data_size = PTR_DIFF(pdata,(*ppdata));
4712 int i;
4713 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4715 for (i=0; i<100; i++)
4716 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4717 DEBUG(4,("\n"));
4720 break;
4722 case SMB_QUERY_FILE_UNIX_INFO2:
4724 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4725 data_size = PTR_DIFF(pdata,(*ppdata));
4728 int i;
4729 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4731 for (i=0; i<100; i++)
4732 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4733 DEBUG(4,("\n"));
4736 break;
4738 case SMB_QUERY_FILE_UNIX_LINK:
4740 int len;
4741 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4743 if (!buffer) {
4744 return NT_STATUS_NO_MEMORY;
4747 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4748 #ifdef S_ISLNK
4749 if(!S_ISLNK(psbuf->st_ex_mode)) {
4750 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4752 #else
4753 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4754 #endif
4755 len = SMB_VFS_READLINK(conn,
4756 smb_fname->base_name,
4757 buffer, PATH_MAX);
4758 if (len == -1) {
4759 return map_nt_error_from_unix(errno);
4761 buffer[len] = 0;
4762 len = srvstr_push(dstart, flags2,
4763 pdata, buffer,
4764 PTR_DIFF(dend, pdata),
4765 STR_TERMINATE);
4766 pdata += len;
4767 data_size = PTR_DIFF(pdata,(*ppdata));
4769 break;
4772 #if defined(HAVE_POSIX_ACLS)
4773 case SMB_QUERY_POSIX_ACL:
4775 SMB_ACL_T file_acl = NULL;
4776 SMB_ACL_T def_acl = NULL;
4777 uint16 num_file_acls = 0;
4778 uint16 num_def_acls = 0;
4780 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4781 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4782 } else {
4783 file_acl =
4784 SMB_VFS_SYS_ACL_GET_FILE(conn,
4785 smb_fname->base_name,
4786 SMB_ACL_TYPE_ACCESS);
4789 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4790 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4791 "not implemented on "
4792 "filesystem containing %s\n",
4793 smb_fname->base_name));
4794 return NT_STATUS_NOT_IMPLEMENTED;
4797 if (S_ISDIR(psbuf->st_ex_mode)) {
4798 if (fsp && fsp->is_directory) {
4799 def_acl =
4800 SMB_VFS_SYS_ACL_GET_FILE(
4801 conn,
4802 fsp->fsp_name->base_name,
4803 SMB_ACL_TYPE_DEFAULT);
4804 } else {
4805 def_acl =
4806 SMB_VFS_SYS_ACL_GET_FILE(
4807 conn,
4808 smb_fname->base_name,
4809 SMB_ACL_TYPE_DEFAULT);
4811 def_acl = free_empty_sys_acl(conn, def_acl);
4814 num_file_acls = count_acl_entries(conn, file_acl);
4815 num_def_acls = count_acl_entries(conn, def_acl);
4817 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4818 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4819 data_size,
4820 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4821 SMB_POSIX_ACL_HEADER_SIZE) ));
4822 if (file_acl) {
4823 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4825 if (def_acl) {
4826 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4828 return NT_STATUS_BUFFER_TOO_SMALL;
4831 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4832 SSVAL(pdata,2,num_file_acls);
4833 SSVAL(pdata,4,num_def_acls);
4834 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4835 if (file_acl) {
4836 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4838 if (def_acl) {
4839 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4841 return NT_STATUS_INTERNAL_ERROR;
4843 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4844 if (file_acl) {
4845 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4847 if (def_acl) {
4848 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4850 return NT_STATUS_INTERNAL_ERROR;
4853 if (file_acl) {
4854 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4856 if (def_acl) {
4857 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4859 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4860 break;
4862 #endif
4865 case SMB_QUERY_POSIX_LOCK:
4867 uint64_t count;
4868 uint64_t offset;
4869 uint32 lock_pid;
4870 enum brl_type lock_type;
4872 /* We need an open file with a real fd for this. */
4873 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4874 return NT_STATUS_INVALID_LEVEL;
4877 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4878 return NT_STATUS_INVALID_PARAMETER;
4881 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4882 case POSIX_LOCK_TYPE_READ:
4883 lock_type = READ_LOCK;
4884 break;
4885 case POSIX_LOCK_TYPE_WRITE:
4886 lock_type = WRITE_LOCK;
4887 break;
4888 case POSIX_LOCK_TYPE_UNLOCK:
4889 default:
4890 /* There's no point in asking for an unlock... */
4891 return NT_STATUS_INVALID_PARAMETER;
4894 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4895 #if defined(HAVE_LONGLONG)
4896 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4897 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4898 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4899 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4900 #else /* HAVE_LONGLONG */
4901 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4902 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4903 #endif /* HAVE_LONGLONG */
4905 status = query_lock(fsp,
4906 &lock_pid,
4907 &count,
4908 &offset,
4909 &lock_type,
4910 POSIX_LOCK);
4912 if (ERROR_WAS_LOCK_DENIED(status)) {
4913 /* Here we need to report who has it locked... */
4914 data_size = POSIX_LOCK_DATA_SIZE;
4916 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4917 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4918 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4919 #if defined(HAVE_LONGLONG)
4920 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4921 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4922 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4923 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4924 #else /* HAVE_LONGLONG */
4925 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4926 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4927 #endif /* HAVE_LONGLONG */
4929 } else if (NT_STATUS_IS_OK(status)) {
4930 /* For success we just return a copy of what we sent
4931 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4932 data_size = POSIX_LOCK_DATA_SIZE;
4933 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4934 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4935 } else {
4936 return status;
4938 break;
4941 default:
4942 return NT_STATUS_INVALID_LEVEL;
4945 *pdata_size = data_size;
4946 return NT_STATUS_OK;
4949 /****************************************************************************
4950 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4951 file name or file id).
4952 ****************************************************************************/
4954 static void call_trans2qfilepathinfo(connection_struct *conn,
4955 struct smb_request *req,
4956 unsigned int tran_call,
4957 char **pparams, int total_params,
4958 char **ppdata, int total_data,
4959 unsigned int max_data_bytes)
4961 char *params = *pparams;
4962 char *pdata = *ppdata;
4963 uint16 info_level;
4964 unsigned int data_size = 0;
4965 unsigned int param_size = 2;
4966 struct smb_filename *smb_fname = NULL;
4967 bool delete_pending = False;
4968 struct timespec write_time_ts;
4969 files_struct *fsp = NULL;
4970 struct file_id fileid;
4971 struct ea_list *ea_list = NULL;
4972 int lock_data_count = 0;
4973 char *lock_data = NULL;
4974 bool ms_dfs_link = false;
4975 NTSTATUS status = NT_STATUS_OK;
4977 if (!params) {
4978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4979 return;
4982 ZERO_STRUCT(write_time_ts);
4984 if (tran_call == TRANSACT2_QFILEINFO) {
4985 if (total_params < 4) {
4986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4987 return;
4990 if (IS_IPC(conn)) {
4991 call_trans2qpipeinfo(conn, req, tran_call,
4992 pparams, total_params,
4993 ppdata, total_data,
4994 max_data_bytes);
4995 return;
4998 fsp = file_fsp(req, SVAL(params,0));
4999 info_level = SVAL(params,2);
5001 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5003 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5004 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5005 return;
5008 /* Initial check for valid fsp ptr. */
5009 if (!check_fsp_open(conn, req, fsp)) {
5010 return;
5013 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5014 &smb_fname);
5015 if (!NT_STATUS_IS_OK(status)) {
5016 reply_nterror(req, status);
5017 return;
5020 if(fsp->fake_file_handle) {
5022 * This is actually for the QUOTA_FAKE_FILE --metze
5025 /* We know this name is ok, it's already passed the checks. */
5027 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5029 * This is actually a QFILEINFO on a directory
5030 * handle (returned from an NT SMB). NT5.0 seems
5031 * to do this call. JRA.
5034 if (INFO_LEVEL_IS_UNIX(info_level)) {
5035 /* Always do lstat for UNIX calls. */
5036 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5037 DEBUG(3,("call_trans2qfilepathinfo: "
5038 "SMB_VFS_LSTAT of %s failed "
5039 "(%s)\n",
5040 smb_fname_str_dbg(smb_fname),
5041 strerror(errno)));
5042 reply_nterror(req,
5043 map_nt_error_from_unix(errno));
5044 return;
5046 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5047 DEBUG(3,("call_trans2qfilepathinfo: "
5048 "SMB_VFS_STAT of %s failed (%s)\n",
5049 smb_fname_str_dbg(smb_fname),
5050 strerror(errno)));
5051 reply_nterror(req,
5052 map_nt_error_from_unix(errno));
5053 return;
5056 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5057 get_file_infos(fileid, &delete_pending, &write_time_ts);
5058 } else {
5060 * Original code - this is an open file.
5062 if (!check_fsp(conn, req, fsp)) {
5063 return;
5066 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5067 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5068 fsp->fnum, strerror(errno)));
5069 reply_nterror(req,
5070 map_nt_error_from_unix(errno));
5071 return;
5073 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5074 get_file_infos(fileid, &delete_pending, &write_time_ts);
5077 } else {
5078 char *fname = NULL;
5080 /* qpathinfo */
5081 if (total_params < 7) {
5082 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5083 return;
5086 info_level = SVAL(params,0);
5088 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5090 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5091 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5092 return;
5095 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5096 total_params - 6,
5097 STR_TERMINATE, &status);
5098 if (!NT_STATUS_IS_OK(status)) {
5099 reply_nterror(req, status);
5100 return;
5103 status = filename_convert(req,
5104 conn,
5105 req->flags2 & FLAGS2_DFS_PATHNAMES,
5106 fname,
5108 NULL,
5109 &smb_fname);
5110 if (!NT_STATUS_IS_OK(status)) {
5111 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5112 reply_botherror(req,
5113 NT_STATUS_PATH_NOT_COVERED,
5114 ERRSRV, ERRbadpath);
5115 return;
5117 reply_nterror(req, status);
5118 return;
5121 /* If this is a stream, check if there is a delete_pending. */
5122 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5123 && is_ntfs_stream_smb_fname(smb_fname)) {
5124 struct smb_filename *smb_fname_base = NULL;
5126 /* Create an smb_filename with stream_name == NULL. */
5127 status =
5128 create_synthetic_smb_fname(talloc_tos(),
5129 smb_fname->base_name,
5130 NULL, NULL,
5131 &smb_fname_base);
5132 if (!NT_STATUS_IS_OK(status)) {
5133 reply_nterror(req, status);
5134 return;
5137 if (INFO_LEVEL_IS_UNIX(info_level)) {
5138 /* Always do lstat for UNIX calls. */
5139 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5140 DEBUG(3,("call_trans2qfilepathinfo: "
5141 "SMB_VFS_LSTAT of %s failed "
5142 "(%s)\n",
5143 smb_fname_str_dbg(smb_fname_base),
5144 strerror(errno)));
5145 TALLOC_FREE(smb_fname_base);
5146 reply_nterror(req,
5147 map_nt_error_from_unix(errno));
5148 return;
5150 } else {
5151 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5152 DEBUG(3,("call_trans2qfilepathinfo: "
5153 "fileinfo of %s failed "
5154 "(%s)\n",
5155 smb_fname_str_dbg(smb_fname_base),
5156 strerror(errno)));
5157 TALLOC_FREE(smb_fname_base);
5158 reply_nterror(req,
5159 map_nt_error_from_unix(errno));
5160 return;
5164 fileid = vfs_file_id_from_sbuf(conn,
5165 &smb_fname_base->st);
5166 TALLOC_FREE(smb_fname_base);
5167 get_file_infos(fileid, &delete_pending, NULL);
5168 if (delete_pending) {
5169 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5170 return;
5174 if (INFO_LEVEL_IS_UNIX(info_level)) {
5175 /* Always do lstat for UNIX calls. */
5176 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5177 DEBUG(3,("call_trans2qfilepathinfo: "
5178 "SMB_VFS_LSTAT of %s failed (%s)\n",
5179 smb_fname_str_dbg(smb_fname),
5180 strerror(errno)));
5181 reply_nterror(req,
5182 map_nt_error_from_unix(errno));
5183 return;
5186 } else if (!VALID_STAT(smb_fname->st) &&
5187 SMB_VFS_STAT(conn, smb_fname) &&
5188 (info_level != SMB_INFO_IS_NAME_VALID)) {
5189 ms_dfs_link = check_msdfs_link(conn,
5190 smb_fname->base_name,
5191 &smb_fname->st);
5193 if (!ms_dfs_link) {
5194 DEBUG(3,("call_trans2qfilepathinfo: "
5195 "SMB_VFS_STAT of %s failed (%s)\n",
5196 smb_fname_str_dbg(smb_fname),
5197 strerror(errno)));
5198 reply_nterror(req,
5199 map_nt_error_from_unix(errno));
5200 return;
5204 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5205 get_file_infos(fileid, &delete_pending, &write_time_ts);
5206 if (delete_pending) {
5207 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5208 return;
5212 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5213 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5214 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5216 /* Pull out any data sent here before we realloc. */
5217 switch (info_level) {
5218 case SMB_INFO_QUERY_EAS_FROM_LIST:
5220 /* Pull any EA list from the data portion. */
5221 uint32 ea_size;
5223 if (total_data < 4) {
5224 reply_nterror(
5225 req, NT_STATUS_INVALID_PARAMETER);
5226 return;
5228 ea_size = IVAL(pdata,0);
5230 if (total_data > 0 && ea_size != total_data) {
5231 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5232 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5233 reply_nterror(
5234 req, NT_STATUS_INVALID_PARAMETER);
5235 return;
5238 if (!lp_ea_support(SNUM(conn))) {
5239 reply_doserror(req, ERRDOS,
5240 ERReasnotsupported);
5241 return;
5244 /* Pull out the list of names. */
5245 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5246 if (!ea_list) {
5247 reply_nterror(
5248 req, NT_STATUS_INVALID_PARAMETER);
5249 return;
5251 break;
5254 case SMB_QUERY_POSIX_LOCK:
5256 if (fsp == NULL || fsp->fh->fd == -1) {
5257 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5258 return;
5261 if (total_data != POSIX_LOCK_DATA_SIZE) {
5262 reply_nterror(
5263 req, NT_STATUS_INVALID_PARAMETER);
5264 return;
5267 /* Copy the lock range data. */
5268 lock_data = (char *)TALLOC_MEMDUP(
5269 req, pdata, total_data);
5270 if (!lock_data) {
5271 reply_nterror(req, NT_STATUS_NO_MEMORY);
5272 return;
5274 lock_data_count = total_data;
5276 default:
5277 break;
5280 *pparams = (char *)SMB_REALLOC(*pparams,2);
5281 if (*pparams == NULL) {
5282 reply_nterror(req, NT_STATUS_NO_MEMORY);
5283 return;
5285 params = *pparams;
5286 SSVAL(params,0,0);
5289 * draft-leach-cifs-v1-spec-02.txt
5290 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5291 * says:
5293 * The requested information is placed in the Data portion of the
5294 * transaction response. For the information levels greater than 0x100,
5295 * the transaction response has 1 parameter word which should be
5296 * ignored by the client.
5298 * However Windows only follows this rule for the IS_NAME_VALID call.
5300 switch (info_level) {
5301 case SMB_INFO_IS_NAME_VALID:
5302 param_size = 0;
5303 break;
5306 if ((info_level & 0xFF00) == 0xFF00) {
5308 * We use levels that start with 0xFF00
5309 * internally to represent SMB2 specific levels
5311 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5312 return;
5315 status = smbd_do_qfilepathinfo(conn, req, info_level,
5316 fsp, smb_fname,
5317 delete_pending, write_time_ts,
5318 ms_dfs_link, ea_list,
5319 lock_data_count, lock_data,
5320 req->flags2, max_data_bytes,
5321 ppdata, &data_size);
5322 if (!NT_STATUS_IS_OK(status)) {
5323 reply_nterror(req, status);
5324 return;
5327 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5328 max_data_bytes);
5330 return;
5333 /****************************************************************************
5334 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5335 code.
5336 ****************************************************************************/
5338 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5339 connection_struct *conn,
5340 const struct smb_filename *smb_fname_old,
5341 const struct smb_filename *smb_fname_new)
5343 NTSTATUS status = NT_STATUS_OK;
5345 /* source must already exist. */
5346 if (!VALID_STAT(smb_fname_old->st)) {
5347 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5350 /* Disallow if newname already exists. */
5351 if (VALID_STAT(smb_fname_new->st)) {
5352 return NT_STATUS_OBJECT_NAME_COLLISION;
5355 /* No links from a directory. */
5356 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5357 return NT_STATUS_FILE_IS_A_DIRECTORY;
5360 /* Setting a hardlink to/from a stream isn't currently supported. */
5361 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5362 is_ntfs_stream_smb_fname(smb_fname_new)) {
5363 return NT_STATUS_INVALID_PARAMETER;
5366 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5367 smb_fname_old->base_name, smb_fname_new->base_name));
5369 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5370 smb_fname_new->base_name) != 0) {
5371 status = map_nt_error_from_unix(errno);
5372 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5373 nt_errstr(status), smb_fname_old->base_name,
5374 smb_fname_new->base_name));
5376 return status;
5379 /****************************************************************************
5380 Deal with setting the time from any of the setfilepathinfo functions.
5381 ****************************************************************************/
5383 NTSTATUS smb_set_file_time(connection_struct *conn,
5384 files_struct *fsp,
5385 const struct smb_filename *smb_fname,
5386 struct smb_file_time *ft,
5387 bool setting_write_time)
5389 struct smb_filename smb_fname_base;
5390 uint32 action =
5391 FILE_NOTIFY_CHANGE_LAST_ACCESS
5392 |FILE_NOTIFY_CHANGE_LAST_WRITE
5393 |FILE_NOTIFY_CHANGE_CREATION;
5395 if (!VALID_STAT(smb_fname->st)) {
5396 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5399 /* get some defaults (no modifications) if any info is zero or -1. */
5400 if (null_timespec(ft->create_time)) {
5401 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5404 if (null_timespec(ft->atime)) {
5405 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5408 if (null_timespec(ft->mtime)) {
5409 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5412 if (!setting_write_time) {
5413 /* ft->mtime comes from change time, not write time. */
5414 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5417 /* Ensure the resolution is the correct for
5418 * what we can store on this filesystem. */
5420 round_timespec(conn->ts_res, &ft->create_time);
5421 round_timespec(conn->ts_res, &ft->ctime);
5422 round_timespec(conn->ts_res, &ft->atime);
5423 round_timespec(conn->ts_res, &ft->mtime);
5425 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5426 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5427 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5428 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5429 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5430 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5431 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5432 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5434 if (setting_write_time) {
5436 * This was a Windows setfileinfo on an open file.
5437 * NT does this a lot. We also need to
5438 * set the time here, as it can be read by
5439 * FindFirst/FindNext and with the patch for bug #2045
5440 * in smbd/fileio.c it ensures that this timestamp is
5441 * kept sticky even after a write. We save the request
5442 * away and will set it on file close and after a write. JRA.
5445 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5446 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5448 if (fsp != NULL) {
5449 if (fsp->base_fsp) {
5450 set_sticky_write_time_fsp(fsp->base_fsp,
5451 ft->mtime);
5452 } else {
5453 set_sticky_write_time_fsp(fsp, ft->mtime);
5455 } else {
5456 set_sticky_write_time_path(
5457 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5458 ft->mtime);
5462 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5464 /* Always call ntimes on the base, even if a stream was passed in. */
5465 smb_fname_base = *smb_fname;
5466 smb_fname_base.stream_name = NULL;
5468 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5469 return map_nt_error_from_unix(errno);
5472 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5473 smb_fname->base_name);
5474 return NT_STATUS_OK;
5477 /****************************************************************************
5478 Deal with setting the dosmode from any of the setfilepathinfo functions.
5479 ****************************************************************************/
5481 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5482 const struct smb_filename *smb_fname,
5483 uint32 dosmode)
5485 struct smb_filename *smb_fname_base = NULL;
5486 NTSTATUS status;
5488 if (!VALID_STAT(smb_fname->st)) {
5489 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5492 /* Always operate on the base_name, even if a stream was passed in. */
5493 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5494 NULL, &smb_fname->st,
5495 &smb_fname_base);
5496 if (!NT_STATUS_IS_OK(status)) {
5497 return status;
5500 if (dosmode) {
5501 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5502 dosmode |= aDIR;
5503 } else {
5504 dosmode &= ~aDIR;
5508 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5510 /* check the mode isn't different, before changing it */
5511 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5512 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5513 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5514 (unsigned int)dosmode));
5516 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5517 false)) {
5518 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5519 "%s failed (%s)\n",
5520 smb_fname_str_dbg(smb_fname_base),
5521 strerror(errno)));
5522 status = map_nt_error_from_unix(errno);
5523 goto out;
5526 status = NT_STATUS_OK;
5527 out:
5528 TALLOC_FREE(smb_fname_base);
5529 return status;
5532 /****************************************************************************
5533 Deal with setting the size from any of the setfilepathinfo functions.
5534 ****************************************************************************/
5536 static NTSTATUS smb_set_file_size(connection_struct *conn,
5537 struct smb_request *req,
5538 files_struct *fsp,
5539 const struct smb_filename *smb_fname,
5540 const SMB_STRUCT_STAT *psbuf,
5541 SMB_OFF_T size,
5542 bool fail_after_createfile)
5544 NTSTATUS status = NT_STATUS_OK;
5545 struct smb_filename *smb_fname_tmp = NULL;
5546 files_struct *new_fsp = NULL;
5548 if (!VALID_STAT(*psbuf)) {
5549 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5552 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5554 if (size == get_file_size_stat(psbuf)) {
5555 return NT_STATUS_OK;
5558 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5559 smb_fname_str_dbg(smb_fname), (double)size));
5561 if (fsp && fsp->fh->fd != -1) {
5562 /* Handle based call. */
5563 if (vfs_set_filelen(fsp, size) == -1) {
5564 return map_nt_error_from_unix(errno);
5566 trigger_write_time_update_immediate(fsp);
5567 return NT_STATUS_OK;
5570 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5571 if (!NT_STATUS_IS_OK(status)) {
5572 return status;
5575 smb_fname_tmp->st = *psbuf;
5577 status = SMB_VFS_CREATE_FILE(
5578 conn, /* conn */
5579 req, /* req */
5580 0, /* root_dir_fid */
5581 smb_fname_tmp, /* fname */
5582 FILE_WRITE_DATA, /* access_mask */
5583 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5584 FILE_SHARE_DELETE),
5585 FILE_OPEN, /* create_disposition*/
5586 0, /* create_options */
5587 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5588 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5589 0, /* allocation_size */
5590 NULL, /* sd */
5591 NULL, /* ea_list */
5592 &new_fsp, /* result */
5593 NULL); /* pinfo */
5595 TALLOC_FREE(smb_fname_tmp);
5597 if (!NT_STATUS_IS_OK(status)) {
5598 /* NB. We check for open_was_deferred in the caller. */
5599 return status;
5602 /* See RAW-SFILEINFO-END-OF-FILE */
5603 if (fail_after_createfile) {
5604 close_file(req, new_fsp,NORMAL_CLOSE);
5605 return NT_STATUS_INVALID_LEVEL;
5608 if (vfs_set_filelen(new_fsp, size) == -1) {
5609 status = map_nt_error_from_unix(errno);
5610 close_file(req, new_fsp,NORMAL_CLOSE);
5611 return status;
5614 trigger_write_time_update_immediate(new_fsp);
5615 close_file(req, new_fsp,NORMAL_CLOSE);
5616 return NT_STATUS_OK;
5619 /****************************************************************************
5620 Deal with SMB_INFO_SET_EA.
5621 ****************************************************************************/
5623 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5624 const char *pdata,
5625 int total_data,
5626 files_struct *fsp,
5627 const struct smb_filename *smb_fname)
5629 struct ea_list *ea_list = NULL;
5630 TALLOC_CTX *ctx = NULL;
5631 NTSTATUS status = NT_STATUS_OK;
5633 if (total_data < 10) {
5635 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5636 length. They seem to have no effect. Bug #3212. JRA */
5638 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5639 /* We're done. We only get EA info in this call. */
5640 return NT_STATUS_OK;
5643 return NT_STATUS_INVALID_PARAMETER;
5646 if (IVAL(pdata,0) > total_data) {
5647 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5648 IVAL(pdata,0), (unsigned int)total_data));
5649 return NT_STATUS_INVALID_PARAMETER;
5652 ctx = talloc_tos();
5653 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5654 if (!ea_list) {
5655 return NT_STATUS_INVALID_PARAMETER;
5657 status = set_ea(conn, fsp, smb_fname, ea_list);
5659 return status;
5662 /****************************************************************************
5663 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5664 ****************************************************************************/
5666 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5667 const char *pdata,
5668 int total_data,
5669 files_struct *fsp)
5671 struct ea_list *ea_list = NULL;
5672 NTSTATUS status;
5674 if (!fsp) {
5675 return NT_STATUS_INVALID_HANDLE;
5678 if (!lp_ea_support(SNUM(conn))) {
5679 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5680 "EA's not supported.\n",
5681 (unsigned int)total_data));
5682 return NT_STATUS_EAS_NOT_SUPPORTED;
5685 if (total_data < 10) {
5686 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5687 "too small.\n",
5688 (unsigned int)total_data));
5689 return NT_STATUS_INVALID_PARAMETER;
5692 ea_list = read_nttrans_ea_list(talloc_tos(),
5693 pdata,
5694 total_data);
5696 if (!ea_list) {
5697 return NT_STATUS_INVALID_PARAMETER;
5699 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5701 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5702 smb_fname_str_dbg(fsp->fsp_name),
5703 nt_errstr(status) ));
5705 return status;
5709 /****************************************************************************
5710 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5711 ****************************************************************************/
5713 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5714 const char *pdata,
5715 int total_data,
5716 files_struct *fsp,
5717 struct smb_filename *smb_fname)
5719 NTSTATUS status = NT_STATUS_OK;
5720 bool delete_on_close;
5721 uint32 dosmode = 0;
5723 if (total_data < 1) {
5724 return NT_STATUS_INVALID_PARAMETER;
5727 if (fsp == NULL) {
5728 return NT_STATUS_INVALID_HANDLE;
5731 delete_on_close = (CVAL(pdata,0) ? True : False);
5732 dosmode = dos_mode(conn, smb_fname);
5734 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5735 "delete_on_close = %u\n",
5736 smb_fname_str_dbg(smb_fname),
5737 (unsigned int)dosmode,
5738 (unsigned int)delete_on_close ));
5740 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5742 if (!NT_STATUS_IS_OK(status)) {
5743 return status;
5746 /* The set is across all open files on this dev/inode pair. */
5747 if (!set_delete_on_close(fsp, delete_on_close,
5748 &conn->server_info->utok)) {
5749 return NT_STATUS_ACCESS_DENIED;
5751 return NT_STATUS_OK;
5754 /****************************************************************************
5755 Deal with SMB_FILE_POSITION_INFORMATION.
5756 ****************************************************************************/
5758 static NTSTATUS smb_file_position_information(connection_struct *conn,
5759 const char *pdata,
5760 int total_data,
5761 files_struct *fsp)
5763 uint64_t position_information;
5765 if (total_data < 8) {
5766 return NT_STATUS_INVALID_PARAMETER;
5769 if (fsp == NULL) {
5770 /* Ignore on pathname based set. */
5771 return NT_STATUS_OK;
5774 position_information = (uint64_t)IVAL(pdata,0);
5775 #ifdef LARGE_SMB_OFF_T
5776 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5777 #else /* LARGE_SMB_OFF_T */
5778 if (IVAL(pdata,4) != 0) {
5779 /* more than 32 bits? */
5780 return NT_STATUS_INVALID_PARAMETER;
5782 #endif /* LARGE_SMB_OFF_T */
5784 DEBUG(10,("smb_file_position_information: Set file position "
5785 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5786 (double)position_information));
5787 fsp->fh->position_information = position_information;
5788 return NT_STATUS_OK;
5791 /****************************************************************************
5792 Deal with SMB_FILE_MODE_INFORMATION.
5793 ****************************************************************************/
5795 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5796 const char *pdata,
5797 int total_data)
5799 uint32 mode;
5801 if (total_data < 4) {
5802 return NT_STATUS_INVALID_PARAMETER;
5804 mode = IVAL(pdata,0);
5805 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5806 return NT_STATUS_INVALID_PARAMETER;
5808 return NT_STATUS_OK;
5811 /****************************************************************************
5812 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5813 ****************************************************************************/
5815 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5816 struct smb_request *req,
5817 const char *pdata,
5818 int total_data,
5819 const struct smb_filename *smb_fname)
5821 char *link_target = NULL;
5822 const char *newname = smb_fname->base_name;
5823 NTSTATUS status = NT_STATUS_OK;
5824 TALLOC_CTX *ctx = talloc_tos();
5826 /* Set a symbolic link. */
5827 /* Don't allow this if follow links is false. */
5829 if (total_data == 0) {
5830 return NT_STATUS_INVALID_PARAMETER;
5833 if (!lp_symlinks(SNUM(conn))) {
5834 return NT_STATUS_ACCESS_DENIED;
5837 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5838 total_data, STR_TERMINATE);
5840 if (!link_target) {
5841 return NT_STATUS_INVALID_PARAMETER;
5844 /* !widelinks forces the target path to be within the share. */
5845 /* This means we can interpret the target as a pathname. */
5846 if (!lp_widelinks(SNUM(conn))) {
5847 char *rel_name = NULL;
5848 char *last_dirp = NULL;
5850 if (*link_target == '/') {
5851 /* No absolute paths allowed. */
5852 return NT_STATUS_ACCESS_DENIED;
5854 rel_name = talloc_strdup(ctx,newname);
5855 if (!rel_name) {
5856 return NT_STATUS_NO_MEMORY;
5858 last_dirp = strrchr_m(rel_name, '/');
5859 if (last_dirp) {
5860 last_dirp[1] = '\0';
5861 } else {
5862 rel_name = talloc_strdup(ctx,"./");
5863 if (!rel_name) {
5864 return NT_STATUS_NO_MEMORY;
5867 rel_name = talloc_asprintf_append(rel_name,
5868 "%s",
5869 link_target);
5870 if (!rel_name) {
5871 return NT_STATUS_NO_MEMORY;
5874 status = check_name(conn, rel_name);
5875 if (!NT_STATUS_IS_OK(status)) {
5876 return status;
5880 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5881 newname, link_target ));
5883 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5884 return map_nt_error_from_unix(errno);
5887 return NT_STATUS_OK;
5890 /****************************************************************************
5891 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5892 ****************************************************************************/
5894 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5895 struct smb_request *req,
5896 const char *pdata, int total_data,
5897 const struct smb_filename *smb_fname_new)
5899 char *oldname = NULL;
5900 struct smb_filename *smb_fname_old = NULL;
5901 TALLOC_CTX *ctx = talloc_tos();
5902 NTSTATUS status = NT_STATUS_OK;
5904 /* Set a hard link. */
5905 if (total_data == 0) {
5906 return NT_STATUS_INVALID_PARAMETER;
5909 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5910 total_data, STR_TERMINATE, &status);
5911 if (!NT_STATUS_IS_OK(status)) {
5912 return status;
5915 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5916 smb_fname_str_dbg(smb_fname_new), oldname));
5918 status = filename_convert(ctx,
5919 conn,
5920 req->flags2 & FLAGS2_DFS_PATHNAMES,
5921 oldname,
5923 NULL,
5924 &smb_fname_old);
5925 if (!NT_STATUS_IS_OK(status)) {
5926 return status;
5929 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5932 /****************************************************************************
5933 Deal with SMB_FILE_RENAME_INFORMATION.
5934 ****************************************************************************/
5936 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5937 struct smb_request *req,
5938 const char *pdata,
5939 int total_data,
5940 files_struct *fsp,
5941 struct smb_filename *smb_fname_src)
5943 bool overwrite;
5944 uint32 root_fid;
5945 uint32 len;
5946 char *newname = NULL;
5947 struct smb_filename *smb_fname_dst = NULL;
5948 bool dest_has_wcard = False;
5949 NTSTATUS status = NT_STATUS_OK;
5950 char *p;
5951 TALLOC_CTX *ctx = talloc_tos();
5953 if (total_data < 13) {
5954 return NT_STATUS_INVALID_PARAMETER;
5957 overwrite = (CVAL(pdata,0) ? True : False);
5958 root_fid = IVAL(pdata,4);
5959 len = IVAL(pdata,8);
5961 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5962 return NT_STATUS_INVALID_PARAMETER;
5965 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5966 len, 0, &status,
5967 &dest_has_wcard);
5968 if (!NT_STATUS_IS_OK(status)) {
5969 return status;
5972 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5973 newname));
5975 status = resolve_dfspath_wcard(ctx, conn,
5976 req->flags2 & FLAGS2_DFS_PATHNAMES,
5977 newname,
5978 &newname,
5979 &dest_has_wcard);
5980 if (!NT_STATUS_IS_OK(status)) {
5981 return status;
5984 /* Check the new name has no '/' characters. */
5985 if (strchr_m(newname, '/')) {
5986 return NT_STATUS_NOT_SUPPORTED;
5989 if (fsp && fsp->base_fsp) {
5990 /* newname must be a stream name. */
5991 if (newname[0] != ':') {
5992 return NT_STATUS_NOT_SUPPORTED;
5995 /* Create an smb_fname to call rename_internals_fsp() with. */
5996 status = create_synthetic_smb_fname(talloc_tos(),
5997 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5998 &smb_fname_dst);
5999 if (!NT_STATUS_IS_OK(status)) {
6000 goto out;
6004 * Set the original last component, since
6005 * rename_internals_fsp() requires it.
6007 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6008 newname);
6009 if (smb_fname_dst->original_lcomp == NULL) {
6010 status = NT_STATUS_NO_MEMORY;
6011 goto out;
6014 } else {
6016 * Build up an smb_fname_dst based on the filename passed in.
6017 * We basically just strip off the last component, and put on
6018 * the newname instead.
6020 char *base_name = NULL;
6022 /* newname must *not* be a stream name. */
6023 if (newname[0] == ':') {
6024 return NT_STATUS_NOT_SUPPORTED;
6028 * Strip off the last component (filename) of the path passed
6029 * in.
6031 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6032 if (!base_name) {
6033 return NT_STATUS_NO_MEMORY;
6035 p = strrchr_m(base_name, '/');
6036 if (p) {
6037 p[1] = '\0';
6038 } else {
6039 base_name = talloc_strdup(ctx, "./");
6040 if (!base_name) {
6041 return NT_STATUS_NO_MEMORY;
6044 /* Append the new name. */
6045 base_name = talloc_asprintf_append(base_name,
6046 "%s",
6047 newname);
6048 if (!base_name) {
6049 return NT_STATUS_NO_MEMORY;
6052 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6053 (UCF_SAVE_LCOMP |
6054 (dest_has_wcard ?
6055 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6056 0)));
6058 /* If an error we expect this to be
6059 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6061 if (!NT_STATUS_IS_OK(status)) {
6062 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6063 status)) {
6064 goto out;
6066 /* Create an smb_fname to call rename_internals_fsp() */
6067 status = create_synthetic_smb_fname(ctx,
6068 base_name, NULL,
6069 NULL,
6070 &smb_fname_dst);
6071 if (!NT_STATUS_IS_OK(status)) {
6072 goto out;
6077 if (fsp) {
6078 DEBUG(10,("smb_file_rename_information: "
6079 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6080 fsp->fnum, fsp_str_dbg(fsp),
6081 smb_fname_str_dbg(smb_fname_dst)));
6082 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6083 overwrite);
6084 } else {
6085 DEBUG(10,("smb_file_rename_information: "
6086 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6087 smb_fname_str_dbg(smb_fname_src),
6088 smb_fname_str_dbg(smb_fname_dst)));
6089 status = rename_internals(ctx, conn, req, smb_fname_src,
6090 smb_fname_dst, 0, overwrite, false,
6091 dest_has_wcard,
6092 FILE_WRITE_ATTRIBUTES);
6094 out:
6095 TALLOC_FREE(smb_fname_dst);
6096 return status;
6099 /****************************************************************************
6100 Deal with SMB_SET_POSIX_ACL.
6101 ****************************************************************************/
6103 #if defined(HAVE_POSIX_ACLS)
6104 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6105 const char *pdata,
6106 int total_data,
6107 files_struct *fsp,
6108 const struct smb_filename *smb_fname)
6110 uint16 posix_acl_version;
6111 uint16 num_file_acls;
6112 uint16 num_def_acls;
6113 bool valid_file_acls = True;
6114 bool valid_def_acls = True;
6116 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6117 return NT_STATUS_INVALID_PARAMETER;
6119 posix_acl_version = SVAL(pdata,0);
6120 num_file_acls = SVAL(pdata,2);
6121 num_def_acls = SVAL(pdata,4);
6123 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6124 valid_file_acls = False;
6125 num_file_acls = 0;
6128 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6129 valid_def_acls = False;
6130 num_def_acls = 0;
6133 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6134 return NT_STATUS_INVALID_PARAMETER;
6137 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6138 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6139 return NT_STATUS_INVALID_PARAMETER;
6142 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6143 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6144 (unsigned int)num_file_acls,
6145 (unsigned int)num_def_acls));
6147 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6148 smb_fname->base_name, num_file_acls,
6149 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6150 return map_nt_error_from_unix(errno);
6153 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6154 smb_fname->base_name, &smb_fname->st, num_def_acls,
6155 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6156 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6157 return map_nt_error_from_unix(errno);
6159 return NT_STATUS_OK;
6161 #endif
6163 /****************************************************************************
6164 Deal with SMB_SET_POSIX_LOCK.
6165 ****************************************************************************/
6167 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6168 struct smb_request *req,
6169 const char *pdata,
6170 int total_data,
6171 files_struct *fsp)
6173 uint64_t count;
6174 uint64_t offset;
6175 uint32 lock_pid;
6176 bool blocking_lock = False;
6177 enum brl_type lock_type;
6179 NTSTATUS status = NT_STATUS_OK;
6181 if (fsp == NULL || fsp->fh->fd == -1) {
6182 return NT_STATUS_INVALID_HANDLE;
6185 if (total_data != POSIX_LOCK_DATA_SIZE) {
6186 return NT_STATUS_INVALID_PARAMETER;
6189 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6190 case POSIX_LOCK_TYPE_READ:
6191 lock_type = READ_LOCK;
6192 break;
6193 case POSIX_LOCK_TYPE_WRITE:
6194 /* Return the right POSIX-mappable error code for files opened read-only. */
6195 if (!fsp->can_write) {
6196 return NT_STATUS_INVALID_HANDLE;
6198 lock_type = WRITE_LOCK;
6199 break;
6200 case POSIX_LOCK_TYPE_UNLOCK:
6201 lock_type = UNLOCK_LOCK;
6202 break;
6203 default:
6204 return NT_STATUS_INVALID_PARAMETER;
6207 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6208 blocking_lock = False;
6209 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6210 blocking_lock = True;
6211 } else {
6212 return NT_STATUS_INVALID_PARAMETER;
6215 if (!lp_blocking_locks(SNUM(conn))) {
6216 blocking_lock = False;
6219 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6220 #if defined(HAVE_LONGLONG)
6221 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6222 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6223 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6224 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6225 #else /* HAVE_LONGLONG */
6226 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6227 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6228 #endif /* HAVE_LONGLONG */
6230 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6231 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6232 fsp_str_dbg(fsp),
6233 (unsigned int)lock_type,
6234 (unsigned int)lock_pid,
6235 (double)count,
6236 (double)offset ));
6238 if (lock_type == UNLOCK_LOCK) {
6239 status = do_unlock(smbd_messaging_context(),
6240 fsp,
6241 lock_pid,
6242 count,
6243 offset,
6244 POSIX_LOCK);
6245 } else {
6246 uint32 block_smbpid;
6248 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6249 fsp,
6250 lock_pid,
6251 count,
6252 offset,
6253 lock_type,
6254 POSIX_LOCK,
6255 blocking_lock,
6256 &status,
6257 &block_smbpid,
6258 NULL);
6260 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6262 * A blocking lock was requested. Package up
6263 * this smb into a queued request and push it
6264 * onto the blocking lock queue.
6266 if(push_blocking_lock_request(br_lck,
6267 req,
6268 fsp,
6269 -1, /* infinite timeout. */
6271 lock_pid,
6272 lock_type,
6273 POSIX_LOCK,
6274 offset,
6275 count,
6276 block_smbpid)) {
6277 TALLOC_FREE(br_lck);
6278 return status;
6281 TALLOC_FREE(br_lck);
6284 return status;
6287 /****************************************************************************
6288 Deal with SMB_SET_FILE_BASIC_INFO.
6289 ****************************************************************************/
6291 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6292 const char *pdata,
6293 int total_data,
6294 files_struct *fsp,
6295 const struct smb_filename *smb_fname)
6297 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6298 struct smb_file_time ft;
6299 uint32 dosmode = 0;
6300 NTSTATUS status = NT_STATUS_OK;
6302 ZERO_STRUCT(ft);
6304 if (total_data < 36) {
6305 return NT_STATUS_INVALID_PARAMETER;
6308 /* Set the attributes */
6309 dosmode = IVAL(pdata,32);
6310 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6311 if (!NT_STATUS_IS_OK(status)) {
6312 return status;
6315 /* create time */
6316 ft.create_time = interpret_long_date(pdata);
6318 /* access time */
6319 ft.atime = interpret_long_date(pdata+8);
6321 /* write time. */
6322 ft.mtime = interpret_long_date(pdata+16);
6324 /* change time. */
6325 ft.ctime = interpret_long_date(pdata+24);
6327 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6328 smb_fname_str_dbg(smb_fname)));
6330 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6331 true);
6334 /****************************************************************************
6335 Deal with SMB_INFO_STANDARD.
6336 ****************************************************************************/
6338 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6339 const char *pdata,
6340 int total_data,
6341 files_struct *fsp,
6342 const struct smb_filename *smb_fname)
6344 struct smb_file_time ft;
6346 ZERO_STRUCT(ft);
6348 if (total_data < 12) {
6349 return NT_STATUS_INVALID_PARAMETER;
6352 /* create time */
6353 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6354 /* access time */
6355 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6356 /* write time */
6357 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6359 DEBUG(10,("smb_set_info_standard: file %s\n",
6360 smb_fname_str_dbg(smb_fname)));
6362 return smb_set_file_time(conn,
6363 fsp,
6364 smb_fname,
6365 &ft,
6366 true);
6369 /****************************************************************************
6370 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6371 ****************************************************************************/
6373 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6374 struct smb_request *req,
6375 const char *pdata,
6376 int total_data,
6377 files_struct *fsp,
6378 struct smb_filename *smb_fname)
6380 uint64_t allocation_size = 0;
6381 NTSTATUS status = NT_STATUS_OK;
6382 files_struct *new_fsp = NULL;
6384 if (!VALID_STAT(smb_fname->st)) {
6385 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6388 if (total_data < 8) {
6389 return NT_STATUS_INVALID_PARAMETER;
6392 allocation_size = (uint64_t)IVAL(pdata,0);
6393 #ifdef LARGE_SMB_OFF_T
6394 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6395 #else /* LARGE_SMB_OFF_T */
6396 if (IVAL(pdata,4) != 0) {
6397 /* more than 32 bits? */
6398 return NT_STATUS_INVALID_PARAMETER;
6400 #endif /* LARGE_SMB_OFF_T */
6402 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6403 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6404 (double)allocation_size));
6406 if (allocation_size) {
6407 allocation_size = smb_roundup(conn, allocation_size);
6410 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6411 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6412 (double)allocation_size));
6414 if (fsp && fsp->fh->fd != -1) {
6415 /* Open file handle. */
6416 /* Only change if needed. */
6417 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6418 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6419 return map_nt_error_from_unix(errno);
6422 /* But always update the time. */
6424 * This is equivalent to a write. Ensure it's seen immediately
6425 * if there are no pending writes.
6427 trigger_write_time_update_immediate(fsp);
6428 return NT_STATUS_OK;
6431 /* Pathname or stat or directory file. */
6432 status = SMB_VFS_CREATE_FILE(
6433 conn, /* conn */
6434 req, /* req */
6435 0, /* root_dir_fid */
6436 smb_fname, /* fname */
6437 FILE_WRITE_DATA, /* access_mask */
6438 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6439 FILE_SHARE_DELETE),
6440 FILE_OPEN, /* create_disposition*/
6441 0, /* create_options */
6442 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6443 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6444 0, /* allocation_size */
6445 NULL, /* sd */
6446 NULL, /* ea_list */
6447 &new_fsp, /* result */
6448 NULL); /* pinfo */
6450 if (!NT_STATUS_IS_OK(status)) {
6451 /* NB. We check for open_was_deferred in the caller. */
6452 return status;
6455 /* Only change if needed. */
6456 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6457 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6458 status = map_nt_error_from_unix(errno);
6459 close_file(req, new_fsp, NORMAL_CLOSE);
6460 return status;
6464 /* Changing the allocation size should set the last mod time. */
6466 * This is equivalent to a write. Ensure it's seen immediately
6467 * if there are no pending writes.
6469 trigger_write_time_update_immediate(new_fsp);
6471 close_file(req, new_fsp, NORMAL_CLOSE);
6472 return NT_STATUS_OK;
6475 /****************************************************************************
6476 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6477 ****************************************************************************/
6479 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6480 struct smb_request *req,
6481 const char *pdata,
6482 int total_data,
6483 files_struct *fsp,
6484 const struct smb_filename *smb_fname,
6485 bool fail_after_createfile)
6487 SMB_OFF_T size;
6489 if (total_data < 8) {
6490 return NT_STATUS_INVALID_PARAMETER;
6493 size = IVAL(pdata,0);
6494 #ifdef LARGE_SMB_OFF_T
6495 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6496 #else /* LARGE_SMB_OFF_T */
6497 if (IVAL(pdata,4) != 0) {
6498 /* more than 32 bits? */
6499 return NT_STATUS_INVALID_PARAMETER;
6501 #endif /* LARGE_SMB_OFF_T */
6502 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6503 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6504 (double)size));
6506 return smb_set_file_size(conn, req,
6507 fsp,
6508 smb_fname,
6509 &smb_fname->st,
6510 size,
6511 fail_after_createfile);
6514 /****************************************************************************
6515 Allow a UNIX info mknod.
6516 ****************************************************************************/
6518 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6519 const char *pdata,
6520 int total_data,
6521 const struct smb_filename *smb_fname)
6523 uint32 file_type = IVAL(pdata,56);
6524 #if defined(HAVE_MAKEDEV)
6525 uint32 dev_major = IVAL(pdata,60);
6526 uint32 dev_minor = IVAL(pdata,68);
6527 #endif
6528 SMB_DEV_T dev = (SMB_DEV_T)0;
6529 uint32 raw_unixmode = IVAL(pdata,84);
6530 NTSTATUS status;
6531 mode_t unixmode;
6533 if (total_data < 100) {
6534 return NT_STATUS_INVALID_PARAMETER;
6537 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6538 PERM_NEW_FILE, &unixmode);
6539 if (!NT_STATUS_IS_OK(status)) {
6540 return status;
6543 #if defined(HAVE_MAKEDEV)
6544 dev = makedev(dev_major, dev_minor);
6545 #endif
6547 switch (file_type) {
6548 #if defined(S_IFIFO)
6549 case UNIX_TYPE_FIFO:
6550 unixmode |= S_IFIFO;
6551 break;
6552 #endif
6553 #if defined(S_IFSOCK)
6554 case UNIX_TYPE_SOCKET:
6555 unixmode |= S_IFSOCK;
6556 break;
6557 #endif
6558 #if defined(S_IFCHR)
6559 case UNIX_TYPE_CHARDEV:
6560 unixmode |= S_IFCHR;
6561 break;
6562 #endif
6563 #if defined(S_IFBLK)
6564 case UNIX_TYPE_BLKDEV:
6565 unixmode |= S_IFBLK;
6566 break;
6567 #endif
6568 default:
6569 return NT_STATUS_INVALID_PARAMETER;
6572 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6573 "%.0f mode 0%o for file %s\n", (double)dev,
6574 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6576 /* Ok - do the mknod. */
6577 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6578 return map_nt_error_from_unix(errno);
6581 /* If any of the other "set" calls fail we
6582 * don't want to end up with a half-constructed mknod.
6585 if (lp_inherit_perms(SNUM(conn))) {
6586 char *parent;
6587 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6588 &parent, NULL)) {
6589 return NT_STATUS_NO_MEMORY;
6591 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6592 unixmode);
6593 TALLOC_FREE(parent);
6596 return NT_STATUS_OK;
6599 /****************************************************************************
6600 Deal with SMB_SET_FILE_UNIX_BASIC.
6601 ****************************************************************************/
6603 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6604 struct smb_request *req,
6605 const char *pdata,
6606 int total_data,
6607 files_struct *fsp,
6608 const struct smb_filename *smb_fname)
6610 struct smb_file_time ft;
6611 uint32 raw_unixmode;
6612 mode_t unixmode;
6613 SMB_OFF_T size = 0;
6614 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6615 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6616 NTSTATUS status = NT_STATUS_OK;
6617 bool delete_on_fail = False;
6618 enum perm_type ptype;
6619 files_struct *all_fsps = NULL;
6620 bool modify_mtime = true;
6621 struct file_id id;
6622 SMB_STRUCT_STAT sbuf;
6624 ZERO_STRUCT(ft);
6626 if (total_data < 100) {
6627 return NT_STATUS_INVALID_PARAMETER;
6630 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6631 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6632 size=IVAL(pdata,0); /* first 8 Bytes are size */
6633 #ifdef LARGE_SMB_OFF_T
6634 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6635 #else /* LARGE_SMB_OFF_T */
6636 if (IVAL(pdata,4) != 0) {
6637 /* more than 32 bits? */
6638 return NT_STATUS_INVALID_PARAMETER;
6640 #endif /* LARGE_SMB_OFF_T */
6643 ft.atime = interpret_long_date(pdata+24); /* access_time */
6644 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6645 set_owner = (uid_t)IVAL(pdata,40);
6646 set_grp = (gid_t)IVAL(pdata,48);
6647 raw_unixmode = IVAL(pdata,84);
6649 if (VALID_STAT(smb_fname->st)) {
6650 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6651 ptype = PERM_EXISTING_DIR;
6652 } else {
6653 ptype = PERM_EXISTING_FILE;
6655 } else {
6656 ptype = PERM_NEW_FILE;
6659 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6660 ptype, &unixmode);
6661 if (!NT_STATUS_IS_OK(status)) {
6662 return status;
6665 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6666 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6667 smb_fname_str_dbg(smb_fname), (double)size,
6668 (unsigned int)set_owner, (unsigned int)set_grp,
6669 (int)raw_unixmode));
6671 sbuf = smb_fname->st;
6673 if (!VALID_STAT(sbuf)) {
6674 struct smb_filename *smb_fname_tmp = NULL;
6676 * The only valid use of this is to create character and block
6677 * devices, and named pipes. This is deprecated (IMHO) and
6678 * a new info level should be used for mknod. JRA.
6681 status = smb_unix_mknod(conn,
6682 pdata,
6683 total_data,
6684 smb_fname);
6685 if (!NT_STATUS_IS_OK(status)) {
6686 return status;
6689 status = copy_smb_filename(talloc_tos(), smb_fname,
6690 &smb_fname_tmp);
6691 if (!NT_STATUS_IS_OK(status)) {
6692 return status;
6695 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6696 status = map_nt_error_from_unix(errno);
6697 TALLOC_FREE(smb_fname_tmp);
6698 SMB_VFS_UNLINK(conn, smb_fname);
6699 return status;
6702 sbuf = smb_fname_tmp->st;
6703 TALLOC_FREE(smb_fname_tmp);
6705 /* Ensure we don't try and change anything else. */
6706 raw_unixmode = SMB_MODE_NO_CHANGE;
6707 size = get_file_size_stat(&sbuf);
6708 ft.atime = sbuf.st_ex_atime;
6709 ft.mtime = sbuf.st_ex_mtime;
6711 * We continue here as we might want to change the
6712 * owner uid/gid.
6714 delete_on_fail = True;
6717 #if 1
6718 /* Horrible backwards compatibility hack as an old server bug
6719 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6720 * */
6722 if (!size) {
6723 size = get_file_size_stat(&sbuf);
6725 #endif
6728 * Deal with the UNIX specific mode set.
6731 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6732 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6733 "setting mode 0%o for file %s\n",
6734 (unsigned int)unixmode,
6735 smb_fname_str_dbg(smb_fname)));
6736 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6737 return map_nt_error_from_unix(errno);
6742 * Deal with the UNIX specific uid set.
6745 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6746 (sbuf.st_ex_uid != set_owner)) {
6747 int ret;
6749 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6750 "changing owner %u for path %s\n",
6751 (unsigned int)set_owner,
6752 smb_fname_str_dbg(smb_fname)));
6754 if (S_ISLNK(sbuf.st_ex_mode)) {
6755 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6756 set_owner, (gid_t)-1);
6757 } else {
6758 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6759 set_owner, (gid_t)-1);
6762 if (ret != 0) {
6763 status = map_nt_error_from_unix(errno);
6764 if (delete_on_fail) {
6765 SMB_VFS_UNLINK(conn, smb_fname);
6767 return status;
6772 * Deal with the UNIX specific gid set.
6775 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6776 (sbuf.st_ex_gid != set_grp)) {
6777 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6778 "changing group %u for file %s\n",
6779 (unsigned int)set_owner,
6780 smb_fname_str_dbg(smb_fname)));
6781 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6782 set_grp) != 0) {
6783 status = map_nt_error_from_unix(errno);
6784 if (delete_on_fail) {
6785 SMB_VFS_UNLINK(conn, smb_fname);
6787 return status;
6791 /* Deal with any size changes. */
6793 status = smb_set_file_size(conn, req,
6794 fsp,
6795 smb_fname,
6796 &sbuf,
6797 size,
6798 false);
6799 if (!NT_STATUS_IS_OK(status)) {
6800 return status;
6803 /* Deal with any time changes. */
6804 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6805 /* No change, don't cancel anything. */
6806 return status;
6809 id = vfs_file_id_from_sbuf(conn, &sbuf);
6810 for(all_fsps = file_find_di_first(id); all_fsps;
6811 all_fsps = file_find_di_next(all_fsps)) {
6813 * We're setting the time explicitly for UNIX.
6814 * Cancel any pending changes over all handles.
6816 all_fsps->update_write_time_on_close = false;
6817 TALLOC_FREE(all_fsps->update_write_time_event);
6821 * Override the "setting_write_time"
6822 * parameter here as it almost does what
6823 * we need. Just remember if we modified
6824 * mtime and send the notify ourselves.
6826 if (null_timespec(ft.mtime)) {
6827 modify_mtime = false;
6830 status = smb_set_file_time(conn,
6831 fsp,
6832 smb_fname,
6833 &ft,
6834 false);
6835 if (modify_mtime) {
6836 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6837 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6839 return status;
6842 /****************************************************************************
6843 Deal with SMB_SET_FILE_UNIX_INFO2.
6844 ****************************************************************************/
6846 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6847 struct smb_request *req,
6848 const char *pdata,
6849 int total_data,
6850 files_struct *fsp,
6851 const struct smb_filename *smb_fname)
6853 NTSTATUS status;
6854 uint32 smb_fflags;
6855 uint32 smb_fmask;
6857 if (total_data < 116) {
6858 return NT_STATUS_INVALID_PARAMETER;
6861 /* Start by setting all the fields that are common between UNIX_BASIC
6862 * and UNIX_INFO2.
6864 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6865 fsp, smb_fname);
6866 if (!NT_STATUS_IS_OK(status)) {
6867 return status;
6870 smb_fflags = IVAL(pdata, 108);
6871 smb_fmask = IVAL(pdata, 112);
6873 /* NB: We should only attempt to alter the file flags if the client
6874 * sends a non-zero mask.
6876 if (smb_fmask != 0) {
6877 int stat_fflags = 0;
6879 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6880 smb_fmask, &stat_fflags)) {
6881 /* Client asked to alter a flag we don't understand. */
6882 return NT_STATUS_INVALID_PARAMETER;
6885 if (fsp && fsp->fh->fd != -1) {
6886 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6887 return NT_STATUS_NOT_SUPPORTED;
6888 } else {
6889 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6890 stat_fflags) != 0) {
6891 return map_nt_error_from_unix(errno);
6896 /* XXX: need to add support for changing the create_time here. You
6897 * can do this for paths on Darwin with setattrlist(2). The right way
6898 * to hook this up is probably by extending the VFS utimes interface.
6901 return NT_STATUS_OK;
6904 /****************************************************************************
6905 Create a directory with POSIX semantics.
6906 ****************************************************************************/
6908 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6909 struct smb_request *req,
6910 char **ppdata,
6911 int total_data,
6912 struct smb_filename *smb_fname,
6913 int *pdata_return_size)
6915 NTSTATUS status = NT_STATUS_OK;
6916 uint32 raw_unixmode = 0;
6917 uint32 mod_unixmode = 0;
6918 mode_t unixmode = (mode_t)0;
6919 files_struct *fsp = NULL;
6920 uint16 info_level_return = 0;
6921 int info;
6922 char *pdata = *ppdata;
6924 if (total_data < 18) {
6925 return NT_STATUS_INVALID_PARAMETER;
6928 raw_unixmode = IVAL(pdata,8);
6929 /* Next 4 bytes are not yet defined. */
6931 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6932 PERM_NEW_DIR, &unixmode);
6933 if (!NT_STATUS_IS_OK(status)) {
6934 return status;
6937 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6939 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6940 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6942 status = SMB_VFS_CREATE_FILE(
6943 conn, /* conn */
6944 req, /* req */
6945 0, /* root_dir_fid */
6946 smb_fname, /* fname */
6947 FILE_READ_ATTRIBUTES, /* access_mask */
6948 FILE_SHARE_NONE, /* share_access */
6949 FILE_CREATE, /* create_disposition*/
6950 FILE_DIRECTORY_FILE, /* create_options */
6951 mod_unixmode, /* file_attributes */
6952 0, /* oplock_request */
6953 0, /* allocation_size */
6954 NULL, /* sd */
6955 NULL, /* ea_list */
6956 &fsp, /* result */
6957 &info); /* pinfo */
6959 if (NT_STATUS_IS_OK(status)) {
6960 close_file(req, fsp, NORMAL_CLOSE);
6963 info_level_return = SVAL(pdata,16);
6965 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6966 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6967 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6968 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6969 } else {
6970 *pdata_return_size = 12;
6973 /* Realloc the data size */
6974 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6975 if (*ppdata == NULL) {
6976 *pdata_return_size = 0;
6977 return NT_STATUS_NO_MEMORY;
6979 pdata = *ppdata;
6981 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6982 SSVAL(pdata,2,0); /* No fnum. */
6983 SIVAL(pdata,4,info); /* Was directory created. */
6985 switch (info_level_return) {
6986 case SMB_QUERY_FILE_UNIX_BASIC:
6987 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6988 SSVAL(pdata,10,0); /* Padding. */
6989 store_file_unix_basic(conn, pdata + 12, fsp,
6990 &smb_fname->st);
6991 break;
6992 case SMB_QUERY_FILE_UNIX_INFO2:
6993 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6994 SSVAL(pdata,10,0); /* Padding. */
6995 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6996 &smb_fname->st);
6997 break;
6998 default:
6999 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7000 SSVAL(pdata,10,0); /* Padding. */
7001 break;
7004 return status;
7007 /****************************************************************************
7008 Open/Create a file with POSIX semantics.
7009 ****************************************************************************/
7011 static NTSTATUS smb_posix_open(connection_struct *conn,
7012 struct smb_request *req,
7013 char **ppdata,
7014 int total_data,
7015 struct smb_filename *smb_fname,
7016 int *pdata_return_size)
7018 bool extended_oplock_granted = False;
7019 char *pdata = *ppdata;
7020 uint32 flags = 0;
7021 uint32 wire_open_mode = 0;
7022 uint32 raw_unixmode = 0;
7023 uint32 mod_unixmode = 0;
7024 uint32 create_disp = 0;
7025 uint32 access_mask = 0;
7026 uint32 create_options = 0;
7027 NTSTATUS status = NT_STATUS_OK;
7028 mode_t unixmode = (mode_t)0;
7029 files_struct *fsp = NULL;
7030 int oplock_request = 0;
7031 int info = 0;
7032 uint16 info_level_return = 0;
7034 if (total_data < 18) {
7035 return NT_STATUS_INVALID_PARAMETER;
7038 flags = IVAL(pdata,0);
7039 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7040 if (oplock_request) {
7041 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7044 wire_open_mode = IVAL(pdata,4);
7046 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7047 return smb_posix_mkdir(conn, req,
7048 ppdata,
7049 total_data,
7050 smb_fname,
7051 pdata_return_size);
7054 switch (wire_open_mode & SMB_ACCMODE) {
7055 case SMB_O_RDONLY:
7056 access_mask = FILE_READ_DATA;
7057 break;
7058 case SMB_O_WRONLY:
7059 access_mask = FILE_WRITE_DATA;
7060 break;
7061 case SMB_O_RDWR:
7062 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7063 break;
7064 default:
7065 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7066 (unsigned int)wire_open_mode ));
7067 return NT_STATUS_INVALID_PARAMETER;
7070 wire_open_mode &= ~SMB_ACCMODE;
7072 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7073 create_disp = FILE_CREATE;
7074 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7075 create_disp = FILE_OVERWRITE_IF;
7076 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7077 create_disp = FILE_OPEN_IF;
7078 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7079 create_disp = FILE_OPEN;
7080 } else {
7081 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7082 (unsigned int)wire_open_mode ));
7083 return NT_STATUS_INVALID_PARAMETER;
7086 raw_unixmode = IVAL(pdata,8);
7087 /* Next 4 bytes are not yet defined. */
7089 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7090 (VALID_STAT(smb_fname->st) ?
7091 PERM_EXISTING_FILE : PERM_NEW_FILE),
7092 &unixmode);
7094 if (!NT_STATUS_IS_OK(status)) {
7095 return status;
7098 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7100 if (wire_open_mode & SMB_O_SYNC) {
7101 create_options |= FILE_WRITE_THROUGH;
7103 if (wire_open_mode & SMB_O_APPEND) {
7104 access_mask |= FILE_APPEND_DATA;
7106 if (wire_open_mode & SMB_O_DIRECT) {
7107 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7110 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7111 smb_fname_str_dbg(smb_fname),
7112 (unsigned int)wire_open_mode,
7113 (unsigned int)unixmode ));
7115 status = SMB_VFS_CREATE_FILE(
7116 conn, /* conn */
7117 req, /* req */
7118 0, /* root_dir_fid */
7119 smb_fname, /* fname */
7120 access_mask, /* access_mask */
7121 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7122 FILE_SHARE_DELETE),
7123 create_disp, /* create_disposition*/
7124 FILE_NON_DIRECTORY_FILE, /* create_options */
7125 mod_unixmode, /* file_attributes */
7126 oplock_request, /* oplock_request */
7127 0, /* allocation_size */
7128 NULL, /* sd */
7129 NULL, /* ea_list */
7130 &fsp, /* result */
7131 &info); /* pinfo */
7133 if (!NT_STATUS_IS_OK(status)) {
7134 return status;
7137 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7138 extended_oplock_granted = True;
7141 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7142 extended_oplock_granted = True;
7145 info_level_return = SVAL(pdata,16);
7147 /* Allocate the correct return size. */
7149 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7150 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7151 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7152 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7153 } else {
7154 *pdata_return_size = 12;
7157 /* Realloc the data size */
7158 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7159 if (*ppdata == NULL) {
7160 close_file(req, fsp, ERROR_CLOSE);
7161 *pdata_return_size = 0;
7162 return NT_STATUS_NO_MEMORY;
7164 pdata = *ppdata;
7166 if (extended_oplock_granted) {
7167 if (flags & REQUEST_BATCH_OPLOCK) {
7168 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7169 } else {
7170 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7172 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7173 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7174 } else {
7175 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7178 SSVAL(pdata,2,fsp->fnum);
7179 SIVAL(pdata,4,info); /* Was file created etc. */
7181 switch (info_level_return) {
7182 case SMB_QUERY_FILE_UNIX_BASIC:
7183 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7184 SSVAL(pdata,10,0); /* padding. */
7185 store_file_unix_basic(conn, pdata + 12, fsp,
7186 &smb_fname->st);
7187 break;
7188 case SMB_QUERY_FILE_UNIX_INFO2:
7189 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7190 SSVAL(pdata,10,0); /* padding. */
7191 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7192 &smb_fname->st);
7193 break;
7194 default:
7195 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7196 SSVAL(pdata,10,0); /* padding. */
7197 break;
7199 return NT_STATUS_OK;
7202 /****************************************************************************
7203 Delete a file with POSIX semantics.
7204 ****************************************************************************/
7206 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7207 struct smb_request *req,
7208 const char *pdata,
7209 int total_data,
7210 struct smb_filename *smb_fname)
7212 NTSTATUS status = NT_STATUS_OK;
7213 files_struct *fsp = NULL;
7214 uint16 flags = 0;
7215 char del = 1;
7216 int info = 0;
7217 int create_options = 0;
7218 int i;
7219 struct share_mode_lock *lck = NULL;
7221 if (total_data < 2) {
7222 return NT_STATUS_INVALID_PARAMETER;
7225 flags = SVAL(pdata,0);
7227 if (!VALID_STAT(smb_fname->st)) {
7228 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7231 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7232 !VALID_STAT_OF_DIR(smb_fname->st)) {
7233 return NT_STATUS_NOT_A_DIRECTORY;
7236 DEBUG(10,("smb_posix_unlink: %s %s\n",
7237 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7238 smb_fname_str_dbg(smb_fname)));
7240 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7241 create_options |= FILE_DIRECTORY_FILE;
7244 status = SMB_VFS_CREATE_FILE(
7245 conn, /* conn */
7246 req, /* req */
7247 0, /* root_dir_fid */
7248 smb_fname, /* fname */
7249 DELETE_ACCESS, /* access_mask */
7250 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7251 FILE_SHARE_DELETE),
7252 FILE_OPEN, /* create_disposition*/
7253 create_options, /* create_options */
7254 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7255 0, /* oplock_request */
7256 0, /* allocation_size */
7257 NULL, /* sd */
7258 NULL, /* ea_list */
7259 &fsp, /* result */
7260 &info); /* pinfo */
7262 if (!NT_STATUS_IS_OK(status)) {
7263 return status;
7267 * Don't lie to client. If we can't really delete due to
7268 * non-POSIX opens return SHARING_VIOLATION.
7271 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7272 NULL);
7273 if (lck == NULL) {
7274 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7275 "lock for file %s\n", fsp_str_dbg(fsp)));
7276 close_file(req, fsp, NORMAL_CLOSE);
7277 return NT_STATUS_INVALID_PARAMETER;
7281 * See if others still have the file open. If this is the case, then
7282 * don't delete. If all opens are POSIX delete we can set the delete
7283 * on close disposition.
7285 for (i=0; i<lck->num_share_modes; i++) {
7286 struct share_mode_entry *e = &lck->share_modes[i];
7287 if (is_valid_share_mode_entry(e)) {
7288 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7289 continue;
7291 /* Fail with sharing violation. */
7292 close_file(req, fsp, NORMAL_CLOSE);
7293 TALLOC_FREE(lck);
7294 return NT_STATUS_SHARING_VIOLATION;
7299 * Set the delete on close.
7301 status = smb_set_file_disposition_info(conn,
7302 &del,
7304 fsp,
7305 smb_fname);
7307 if (!NT_STATUS_IS_OK(status)) {
7308 close_file(req, fsp, NORMAL_CLOSE);
7309 TALLOC_FREE(lck);
7310 return status;
7312 TALLOC_FREE(lck);
7313 return close_file(req, fsp, NORMAL_CLOSE);
7316 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7317 struct smb_request *req,
7318 TALLOC_CTX *mem_ctx,
7319 uint16_t info_level,
7320 files_struct *fsp,
7321 struct smb_filename *smb_fname,
7322 char **ppdata, int total_data,
7323 int *ret_data_size)
7325 char *pdata = *ppdata;
7326 NTSTATUS status = NT_STATUS_OK;
7327 int data_return_size = 0;
7329 *ret_data_size = 0;
7331 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7332 return NT_STATUS_INVALID_LEVEL;
7335 if (!CAN_WRITE(conn)) {
7336 /* Allow POSIX opens. The open path will deny
7337 * any non-readonly opens. */
7338 if (info_level != SMB_POSIX_PATH_OPEN) {
7339 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7343 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7344 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7345 fsp ? fsp->fnum : -1, info_level, total_data));
7347 switch (info_level) {
7349 case SMB_INFO_STANDARD:
7351 status = smb_set_info_standard(conn,
7352 pdata,
7353 total_data,
7354 fsp,
7355 smb_fname);
7356 break;
7359 case SMB_INFO_SET_EA:
7361 status = smb_info_set_ea(conn,
7362 pdata,
7363 total_data,
7364 fsp,
7365 smb_fname);
7366 break;
7369 case SMB_SET_FILE_BASIC_INFO:
7370 case SMB_FILE_BASIC_INFORMATION:
7372 status = smb_set_file_basic_info(conn,
7373 pdata,
7374 total_data,
7375 fsp,
7376 smb_fname);
7377 break;
7380 case SMB_FILE_ALLOCATION_INFORMATION:
7381 case SMB_SET_FILE_ALLOCATION_INFO:
7383 status = smb_set_file_allocation_info(conn, req,
7384 pdata,
7385 total_data,
7386 fsp,
7387 smb_fname);
7388 break;
7391 case SMB_FILE_END_OF_FILE_INFORMATION:
7392 case SMB_SET_FILE_END_OF_FILE_INFO:
7395 * XP/Win7 both fail after the createfile with
7396 * SMB_SET_FILE_END_OF_FILE_INFO but not
7397 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7398 * The level is known here, so pass it down
7399 * appropriately.
7401 bool should_fail =
7402 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7404 status = smb_set_file_end_of_file_info(conn, req,
7405 pdata,
7406 total_data,
7407 fsp,
7408 smb_fname,
7409 should_fail);
7410 break;
7413 case SMB_FILE_DISPOSITION_INFORMATION:
7414 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7416 #if 0
7417 /* JRA - We used to just ignore this on a path ?
7418 * Shouldn't this be invalid level on a pathname
7419 * based call ?
7421 if (tran_call != TRANSACT2_SETFILEINFO) {
7422 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7424 #endif
7425 status = smb_set_file_disposition_info(conn,
7426 pdata,
7427 total_data,
7428 fsp,
7429 smb_fname);
7430 break;
7433 case SMB_FILE_POSITION_INFORMATION:
7435 status = smb_file_position_information(conn,
7436 pdata,
7437 total_data,
7438 fsp);
7439 break;
7442 case SMB_FILE_FULL_EA_INFORMATION:
7444 status = smb_set_file_full_ea_info(conn,
7445 pdata,
7446 total_data,
7447 fsp);
7448 break;
7451 /* From tridge Samba4 :
7452 * MODE_INFORMATION in setfileinfo (I have no
7453 * idea what "mode information" on a file is - it takes a value of 0,
7454 * 2, 4 or 6. What could it be?).
7457 case SMB_FILE_MODE_INFORMATION:
7459 status = smb_file_mode_information(conn,
7460 pdata,
7461 total_data);
7462 break;
7466 * CIFS UNIX extensions.
7469 case SMB_SET_FILE_UNIX_BASIC:
7471 status = smb_set_file_unix_basic(conn, req,
7472 pdata,
7473 total_data,
7474 fsp,
7475 smb_fname);
7476 break;
7479 case SMB_SET_FILE_UNIX_INFO2:
7481 status = smb_set_file_unix_info2(conn, req,
7482 pdata,
7483 total_data,
7484 fsp,
7485 smb_fname);
7486 break;
7489 case SMB_SET_FILE_UNIX_LINK:
7491 if (fsp) {
7492 /* We must have a pathname for this. */
7493 return NT_STATUS_INVALID_LEVEL;
7495 status = smb_set_file_unix_link(conn, req, pdata,
7496 total_data, smb_fname);
7497 break;
7500 case SMB_SET_FILE_UNIX_HLINK:
7502 if (fsp) {
7503 /* We must have a pathname for this. */
7504 return NT_STATUS_INVALID_LEVEL;
7506 status = smb_set_file_unix_hlink(conn, req,
7507 pdata, total_data,
7508 smb_fname);
7509 break;
7512 case SMB_FILE_RENAME_INFORMATION:
7514 status = smb_file_rename_information(conn, req,
7515 pdata, total_data,
7516 fsp, smb_fname);
7517 break;
7520 #if defined(HAVE_POSIX_ACLS)
7521 case SMB_SET_POSIX_ACL:
7523 status = smb_set_posix_acl(conn,
7524 pdata,
7525 total_data,
7526 fsp,
7527 smb_fname);
7528 break;
7530 #endif
7532 case SMB_SET_POSIX_LOCK:
7534 if (!fsp) {
7535 return NT_STATUS_INVALID_LEVEL;
7537 status = smb_set_posix_lock(conn, req,
7538 pdata, total_data, fsp);
7539 break;
7542 case SMB_POSIX_PATH_OPEN:
7544 if (fsp) {
7545 /* We must have a pathname for this. */
7546 return NT_STATUS_INVALID_LEVEL;
7549 status = smb_posix_open(conn, req,
7550 ppdata,
7551 total_data,
7552 smb_fname,
7553 &data_return_size);
7554 break;
7557 case SMB_POSIX_PATH_UNLINK:
7559 if (fsp) {
7560 /* We must have a pathname for this. */
7561 return NT_STATUS_INVALID_LEVEL;
7564 status = smb_posix_unlink(conn, req,
7565 pdata,
7566 total_data,
7567 smb_fname);
7568 break;
7571 default:
7572 return NT_STATUS_INVALID_LEVEL;
7575 if (!NT_STATUS_IS_OK(status)) {
7576 return status;
7579 *ret_data_size = data_return_size;
7580 return NT_STATUS_OK;
7583 /****************************************************************************
7584 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7585 ****************************************************************************/
7587 static void call_trans2setfilepathinfo(connection_struct *conn,
7588 struct smb_request *req,
7589 unsigned int tran_call,
7590 char **pparams, int total_params,
7591 char **ppdata, int total_data,
7592 unsigned int max_data_bytes)
7594 char *params = *pparams;
7595 char *pdata = *ppdata;
7596 uint16 info_level;
7597 struct smb_filename *smb_fname = NULL;
7598 files_struct *fsp = NULL;
7599 NTSTATUS status = NT_STATUS_OK;
7600 int data_return_size = 0;
7602 if (!params) {
7603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7604 return;
7607 if (tran_call == TRANSACT2_SETFILEINFO) {
7608 if (total_params < 4) {
7609 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7610 return;
7613 fsp = file_fsp(req, SVAL(params,0));
7614 /* Basic check for non-null fsp. */
7615 if (!check_fsp_open(conn, req, fsp)) {
7616 return;
7618 info_level = SVAL(params,2);
7620 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7621 &smb_fname);
7622 if (!NT_STATUS_IS_OK(status)) {
7623 reply_nterror(req, status);
7624 return;
7627 if(fsp->is_directory || fsp->fh->fd == -1) {
7629 * This is actually a SETFILEINFO on a directory
7630 * handle (returned from an NT SMB). NT5.0 seems
7631 * to do this call. JRA.
7633 if (INFO_LEVEL_IS_UNIX(info_level)) {
7634 /* Always do lstat for UNIX calls. */
7635 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7636 DEBUG(3,("call_trans2setfilepathinfo: "
7637 "SMB_VFS_LSTAT of %s failed "
7638 "(%s)\n",
7639 smb_fname_str_dbg(smb_fname),
7640 strerror(errno)));
7641 reply_nterror(req, map_nt_error_from_unix(errno));
7642 return;
7644 } else {
7645 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7646 DEBUG(3,("call_trans2setfilepathinfo: "
7647 "fileinfo of %s failed (%s)\n",
7648 smb_fname_str_dbg(smb_fname),
7649 strerror(errno)));
7650 reply_nterror(req, map_nt_error_from_unix(errno));
7651 return;
7654 } else if (fsp->print_file) {
7656 * Doing a DELETE_ON_CLOSE should cancel a print job.
7658 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7659 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7661 DEBUG(3,("call_trans2setfilepathinfo: "
7662 "Cancelling print job (%s)\n",
7663 fsp_str_dbg(fsp)));
7665 SSVAL(params,0,0);
7666 send_trans2_replies(conn, req, params, 2,
7667 *ppdata, 0,
7668 max_data_bytes);
7669 return;
7670 } else {
7671 reply_doserror(req, ERRDOS, ERRbadpath);
7672 return;
7674 } else {
7676 * Original code - this is an open file.
7678 if (!check_fsp(conn, req, fsp)) {
7679 return;
7682 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7683 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7684 "of fnum %d failed (%s)\n", fsp->fnum,
7685 strerror(errno)));
7686 reply_nterror(req, map_nt_error_from_unix(errno));
7687 return;
7690 } else {
7691 char *fname = NULL;
7693 /* set path info */
7694 if (total_params < 7) {
7695 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7696 return;
7699 info_level = SVAL(params,0);
7700 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7701 total_params - 6, STR_TERMINATE,
7702 &status);
7703 if (!NT_STATUS_IS_OK(status)) {
7704 reply_nterror(req, status);
7705 return;
7708 status = filename_convert(req, conn,
7709 req->flags2 & FLAGS2_DFS_PATHNAMES,
7710 fname,
7712 NULL,
7713 &smb_fname);
7714 if (!NT_STATUS_IS_OK(status)) {
7715 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7716 reply_botherror(req,
7717 NT_STATUS_PATH_NOT_COVERED,
7718 ERRSRV, ERRbadpath);
7719 return;
7721 reply_nterror(req, status);
7722 return;
7725 if (INFO_LEVEL_IS_UNIX(info_level)) {
7727 * For CIFS UNIX extensions the target name may not exist.
7730 /* Always do lstat for UNIX calls. */
7731 SMB_VFS_LSTAT(conn, smb_fname);
7733 } else if (!VALID_STAT(smb_fname->st) &&
7734 SMB_VFS_STAT(conn, smb_fname)) {
7735 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7736 "%s failed (%s)\n",
7737 smb_fname_str_dbg(smb_fname),
7738 strerror(errno)));
7739 reply_nterror(req, map_nt_error_from_unix(errno));
7740 return;
7744 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7745 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7746 fsp ? fsp->fnum : -1, info_level,total_data));
7748 /* Realloc the parameter size */
7749 *pparams = (char *)SMB_REALLOC(*pparams,2);
7750 if (*pparams == NULL) {
7751 reply_nterror(req, NT_STATUS_NO_MEMORY);
7752 return;
7754 params = *pparams;
7756 SSVAL(params,0,0);
7758 status = smbd_do_setfilepathinfo(conn, req, req,
7759 info_level,
7760 fsp,
7761 smb_fname,
7762 ppdata, total_data,
7763 &data_return_size);
7764 if (!NT_STATUS_IS_OK(status)) {
7765 if (open_was_deferred(req->mid)) {
7766 /* We have re-scheduled this call. */
7767 return;
7769 if (blocking_lock_was_deferred(req->mid)) {
7770 /* We have re-scheduled this call. */
7771 return;
7773 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7774 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7775 ERRSRV, ERRbadpath);
7776 return;
7778 if (info_level == SMB_POSIX_PATH_OPEN) {
7779 reply_openerror(req, status);
7780 return;
7783 reply_nterror(req, status);
7784 return;
7787 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7788 max_data_bytes);
7790 return;
7793 /****************************************************************************
7794 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7795 ****************************************************************************/
7797 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7798 char **pparams, int total_params,
7799 char **ppdata, int total_data,
7800 unsigned int max_data_bytes)
7802 struct smb_filename *smb_dname = NULL;
7803 char *params = *pparams;
7804 char *pdata = *ppdata;
7805 char *directory = NULL;
7806 NTSTATUS status = NT_STATUS_OK;
7807 struct ea_list *ea_list = NULL;
7808 TALLOC_CTX *ctx = talloc_tos();
7810 if (!CAN_WRITE(conn)) {
7811 reply_doserror(req, ERRSRV, ERRaccess);
7812 return;
7815 if (total_params < 5) {
7816 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7817 return;
7820 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7821 total_params - 4, STR_TERMINATE,
7822 &status);
7823 if (!NT_STATUS_IS_OK(status)) {
7824 reply_nterror(req, status);
7825 return;
7828 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7830 status = filename_convert(ctx,
7831 conn,
7832 req->flags2 & FLAGS2_DFS_PATHNAMES,
7833 directory,
7835 NULL,
7836 &smb_dname);
7838 if (!NT_STATUS_IS_OK(status)) {
7839 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7840 reply_botherror(req,
7841 NT_STATUS_PATH_NOT_COVERED,
7842 ERRSRV, ERRbadpath);
7843 return;
7845 reply_nterror(req, status);
7846 return;
7849 /* Any data in this call is an EA list. */
7850 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7851 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7852 goto out;
7856 * OS/2 workplace shell seems to send SET_EA requests of "null"
7857 * length (4 bytes containing IVAL 4).
7858 * They seem to have no effect. Bug #3212. JRA.
7861 if (total_data != 4) {
7862 if (total_data < 10) {
7863 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7864 goto out;
7867 if (IVAL(pdata,0) > total_data) {
7868 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7869 IVAL(pdata,0), (unsigned int)total_data));
7870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7871 goto out;
7874 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7875 total_data - 4);
7876 if (!ea_list) {
7877 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7878 goto out;
7881 /* If total_data == 4 Windows doesn't care what values
7882 * are placed in that field, it just ignores them.
7883 * The System i QNTC IBM SMB client puts bad values here,
7884 * so ignore them. */
7886 status = create_directory(conn, req, smb_dname);
7888 if (!NT_STATUS_IS_OK(status)) {
7889 reply_nterror(req, status);
7890 goto out;
7893 /* Try and set any given EA. */
7894 if (ea_list) {
7895 status = set_ea(conn, NULL, smb_dname, ea_list);
7896 if (!NT_STATUS_IS_OK(status)) {
7897 reply_nterror(req, status);
7898 goto out;
7902 /* Realloc the parameter and data sizes */
7903 *pparams = (char *)SMB_REALLOC(*pparams,2);
7904 if(*pparams == NULL) {
7905 reply_nterror(req, NT_STATUS_NO_MEMORY);
7906 goto out;
7908 params = *pparams;
7910 SSVAL(params,0,0);
7912 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7914 out:
7915 TALLOC_FREE(smb_dname);
7916 return;
7919 /****************************************************************************
7920 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7921 We don't actually do this - we just send a null response.
7922 ****************************************************************************/
7924 static void call_trans2findnotifyfirst(connection_struct *conn,
7925 struct smb_request *req,
7926 char **pparams, int total_params,
7927 char **ppdata, int total_data,
7928 unsigned int max_data_bytes)
7930 char *params = *pparams;
7931 uint16 info_level;
7933 if (total_params < 6) {
7934 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7935 return;
7938 info_level = SVAL(params,4);
7939 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7941 switch (info_level) {
7942 case 1:
7943 case 2:
7944 break;
7945 default:
7946 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7947 return;
7950 /* Realloc the parameter and data sizes */
7951 *pparams = (char *)SMB_REALLOC(*pparams,6);
7952 if (*pparams == NULL) {
7953 reply_nterror(req, NT_STATUS_NO_MEMORY);
7954 return;
7956 params = *pparams;
7958 SSVAL(params,0,fnf_handle);
7959 SSVAL(params,2,0); /* No changes */
7960 SSVAL(params,4,0); /* No EA errors */
7962 fnf_handle++;
7964 if(fnf_handle == 0)
7965 fnf_handle = 257;
7967 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7969 return;
7972 /****************************************************************************
7973 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7974 changes). Currently this does nothing.
7975 ****************************************************************************/
7977 static void call_trans2findnotifynext(connection_struct *conn,
7978 struct smb_request *req,
7979 char **pparams, int total_params,
7980 char **ppdata, int total_data,
7981 unsigned int max_data_bytes)
7983 char *params = *pparams;
7985 DEBUG(3,("call_trans2findnotifynext\n"));
7987 /* Realloc the parameter and data sizes */
7988 *pparams = (char *)SMB_REALLOC(*pparams,4);
7989 if (*pparams == NULL) {
7990 reply_nterror(req, NT_STATUS_NO_MEMORY);
7991 return;
7993 params = *pparams;
7995 SSVAL(params,0,0); /* No changes */
7996 SSVAL(params,2,0); /* No EA errors */
7998 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8000 return;
8003 /****************************************************************************
8004 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8005 ****************************************************************************/
8007 static void call_trans2getdfsreferral(connection_struct *conn,
8008 struct smb_request *req,
8009 char **pparams, int total_params,
8010 char **ppdata, int total_data,
8011 unsigned int max_data_bytes)
8013 char *params = *pparams;
8014 char *pathname = NULL;
8015 int reply_size = 0;
8016 int max_referral_level;
8017 NTSTATUS status = NT_STATUS_OK;
8018 TALLOC_CTX *ctx = talloc_tos();
8020 DEBUG(10,("call_trans2getdfsreferral\n"));
8022 if (total_params < 3) {
8023 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8024 return;
8027 max_referral_level = SVAL(params,0);
8029 if(!lp_host_msdfs()) {
8030 reply_doserror(req, ERRDOS, ERRbadfunc);
8031 return;
8034 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8035 total_params - 2, STR_TERMINATE);
8036 if (!pathname) {
8037 reply_nterror(req, NT_STATUS_NOT_FOUND);
8038 return;
8040 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8041 ppdata,&status)) < 0) {
8042 reply_nterror(req, status);
8043 return;
8046 SSVAL(req->inbuf, smb_flg2,
8047 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8048 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8050 return;
8053 #define LMCAT_SPL 0x53
8054 #define LMFUNC_GETJOBID 0x60
8056 /****************************************************************************
8057 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8058 ****************************************************************************/
8060 static void call_trans2ioctl(connection_struct *conn,
8061 struct smb_request *req,
8062 char **pparams, int total_params,
8063 char **ppdata, int total_data,
8064 unsigned int max_data_bytes)
8066 char *pdata = *ppdata;
8067 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8069 /* check for an invalid fid before proceeding */
8071 if (!fsp) {
8072 reply_doserror(req, ERRDOS, ERRbadfid);
8073 return;
8076 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8077 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8078 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8079 if (*ppdata == NULL) {
8080 reply_nterror(req, NT_STATUS_NO_MEMORY);
8081 return;
8083 pdata = *ppdata;
8085 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8086 CAN ACCEPT THIS IN UNICODE. JRA. */
8088 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8089 srvstr_push(pdata, req->flags2, pdata + 2,
8090 global_myname(), 15,
8091 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8092 srvstr_push(pdata, req->flags2, pdata+18,
8093 lp_servicename(SNUM(conn)), 13,
8094 STR_ASCII|STR_TERMINATE); /* Service name */
8095 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8096 max_data_bytes);
8097 return;
8100 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8101 reply_doserror(req, ERRSRV, ERRerror);
8104 /****************************************************************************
8105 Reply to a SMBfindclose (stop trans2 directory search).
8106 ****************************************************************************/
8108 void reply_findclose(struct smb_request *req)
8110 int dptr_num;
8111 struct smbd_server_connection *sconn = smbd_server_conn;
8113 START_PROFILE(SMBfindclose);
8115 if (req->wct < 1) {
8116 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8117 END_PROFILE(SMBfindclose);
8118 return;
8121 dptr_num = SVALS(req->vwv+0, 0);
8123 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8125 dptr_close(sconn, &dptr_num);
8127 reply_outbuf(req, 0, 0);
8129 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8131 END_PROFILE(SMBfindclose);
8132 return;
8135 /****************************************************************************
8136 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8137 ****************************************************************************/
8139 void reply_findnclose(struct smb_request *req)
8141 int dptr_num;
8143 START_PROFILE(SMBfindnclose);
8145 if (req->wct < 1) {
8146 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8147 END_PROFILE(SMBfindnclose);
8148 return;
8151 dptr_num = SVAL(req->vwv+0, 0);
8153 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8155 /* We never give out valid handles for a
8156 findnotifyfirst - so any dptr_num is ok here.
8157 Just ignore it. */
8159 reply_outbuf(req, 0, 0);
8161 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8163 END_PROFILE(SMBfindnclose);
8164 return;
8167 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8168 struct trans_state *state)
8170 if (get_Protocol() >= PROTOCOL_NT1) {
8171 req->flags2 |= 0x40; /* IS_LONG_NAME */
8172 SSVAL(req->inbuf,smb_flg2,req->flags2);
8175 if (conn->encrypt_level == Required && !req->encrypted) {
8176 if (state->call != TRANSACT2_QFSINFO &&
8177 state->call != TRANSACT2_SETFSINFO) {
8178 DEBUG(0,("handle_trans2: encryption required "
8179 "with call 0x%x\n",
8180 (unsigned int)state->call));
8181 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8182 return;
8186 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8188 /* Now we must call the relevant TRANS2 function */
8189 switch(state->call) {
8190 case TRANSACT2_OPEN:
8192 START_PROFILE(Trans2_open);
8193 call_trans2open(conn, req,
8194 &state->param, state->total_param,
8195 &state->data, state->total_data,
8196 state->max_data_return);
8197 END_PROFILE(Trans2_open);
8198 break;
8201 case TRANSACT2_FINDFIRST:
8203 START_PROFILE(Trans2_findfirst);
8204 call_trans2findfirst(conn, req,
8205 &state->param, state->total_param,
8206 &state->data, state->total_data,
8207 state->max_data_return);
8208 END_PROFILE(Trans2_findfirst);
8209 break;
8212 case TRANSACT2_FINDNEXT:
8214 START_PROFILE(Trans2_findnext);
8215 call_trans2findnext(conn, req,
8216 &state->param, state->total_param,
8217 &state->data, state->total_data,
8218 state->max_data_return);
8219 END_PROFILE(Trans2_findnext);
8220 break;
8223 case TRANSACT2_QFSINFO:
8225 START_PROFILE(Trans2_qfsinfo);
8226 call_trans2qfsinfo(conn, req,
8227 &state->param, state->total_param,
8228 &state->data, state->total_data,
8229 state->max_data_return);
8230 END_PROFILE(Trans2_qfsinfo);
8231 break;
8234 case TRANSACT2_SETFSINFO:
8236 START_PROFILE(Trans2_setfsinfo);
8237 call_trans2setfsinfo(conn, req,
8238 &state->param, state->total_param,
8239 &state->data, state->total_data,
8240 state->max_data_return);
8241 END_PROFILE(Trans2_setfsinfo);
8242 break;
8245 case TRANSACT2_QPATHINFO:
8246 case TRANSACT2_QFILEINFO:
8248 START_PROFILE(Trans2_qpathinfo);
8249 call_trans2qfilepathinfo(conn, req, state->call,
8250 &state->param, state->total_param,
8251 &state->data, state->total_data,
8252 state->max_data_return);
8253 END_PROFILE(Trans2_qpathinfo);
8254 break;
8257 case TRANSACT2_SETPATHINFO:
8258 case TRANSACT2_SETFILEINFO:
8260 START_PROFILE(Trans2_setpathinfo);
8261 call_trans2setfilepathinfo(conn, req, state->call,
8262 &state->param, state->total_param,
8263 &state->data, state->total_data,
8264 state->max_data_return);
8265 END_PROFILE(Trans2_setpathinfo);
8266 break;
8269 case TRANSACT2_FINDNOTIFYFIRST:
8271 START_PROFILE(Trans2_findnotifyfirst);
8272 call_trans2findnotifyfirst(conn, req,
8273 &state->param, state->total_param,
8274 &state->data, state->total_data,
8275 state->max_data_return);
8276 END_PROFILE(Trans2_findnotifyfirst);
8277 break;
8280 case TRANSACT2_FINDNOTIFYNEXT:
8282 START_PROFILE(Trans2_findnotifynext);
8283 call_trans2findnotifynext(conn, req,
8284 &state->param, state->total_param,
8285 &state->data, state->total_data,
8286 state->max_data_return);
8287 END_PROFILE(Trans2_findnotifynext);
8288 break;
8291 case TRANSACT2_MKDIR:
8293 START_PROFILE(Trans2_mkdir);
8294 call_trans2mkdir(conn, req,
8295 &state->param, state->total_param,
8296 &state->data, state->total_data,
8297 state->max_data_return);
8298 END_PROFILE(Trans2_mkdir);
8299 break;
8302 case TRANSACT2_GET_DFS_REFERRAL:
8304 START_PROFILE(Trans2_get_dfs_referral);
8305 call_trans2getdfsreferral(conn, req,
8306 &state->param, state->total_param,
8307 &state->data, state->total_data,
8308 state->max_data_return);
8309 END_PROFILE(Trans2_get_dfs_referral);
8310 break;
8313 case TRANSACT2_IOCTL:
8315 START_PROFILE(Trans2_ioctl);
8316 call_trans2ioctl(conn, req,
8317 &state->param, state->total_param,
8318 &state->data, state->total_data,
8319 state->max_data_return);
8320 END_PROFILE(Trans2_ioctl);
8321 break;
8324 default:
8325 /* Error in request */
8326 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8327 reply_doserror(req, ERRSRV,ERRerror);
8331 /****************************************************************************
8332 Reply to a SMBtrans2.
8333 ****************************************************************************/
8335 void reply_trans2(struct smb_request *req)
8337 connection_struct *conn = req->conn;
8338 unsigned int dsoff;
8339 unsigned int dscnt;
8340 unsigned int psoff;
8341 unsigned int pscnt;
8342 unsigned int tran_call;
8343 struct trans_state *state;
8344 NTSTATUS result;
8346 START_PROFILE(SMBtrans2);
8348 if (req->wct < 14) {
8349 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8350 END_PROFILE(SMBtrans2);
8351 return;
8354 dsoff = SVAL(req->vwv+12, 0);
8355 dscnt = SVAL(req->vwv+11, 0);
8356 psoff = SVAL(req->vwv+10, 0);
8357 pscnt = SVAL(req->vwv+9, 0);
8358 tran_call = SVAL(req->vwv+14, 0);
8360 result = allow_new_trans(conn->pending_trans, req->mid);
8361 if (!NT_STATUS_IS_OK(result)) {
8362 DEBUG(2, ("Got invalid trans2 request: %s\n",
8363 nt_errstr(result)));
8364 reply_nterror(req, result);
8365 END_PROFILE(SMBtrans2);
8366 return;
8369 if (IS_IPC(conn)) {
8370 switch (tran_call) {
8371 /* List the allowed trans2 calls on IPC$ */
8372 case TRANSACT2_OPEN:
8373 case TRANSACT2_GET_DFS_REFERRAL:
8374 case TRANSACT2_QFILEINFO:
8375 case TRANSACT2_QFSINFO:
8376 case TRANSACT2_SETFSINFO:
8377 break;
8378 default:
8379 reply_doserror(req, ERRSRV, ERRaccess);
8380 END_PROFILE(SMBtrans2);
8381 return;
8385 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8386 DEBUG(0, ("talloc failed\n"));
8387 reply_nterror(req, NT_STATUS_NO_MEMORY);
8388 END_PROFILE(SMBtrans2);
8389 return;
8392 state->cmd = SMBtrans2;
8394 state->mid = req->mid;
8395 state->vuid = req->vuid;
8396 state->setup_count = SVAL(req->vwv+13, 0);
8397 state->setup = NULL;
8398 state->total_param = SVAL(req->vwv+0, 0);
8399 state->param = NULL;
8400 state->total_data = SVAL(req->vwv+1, 0);
8401 state->data = NULL;
8402 state->max_param_return = SVAL(req->vwv+2, 0);
8403 state->max_data_return = SVAL(req->vwv+3, 0);
8404 state->max_setup_return = SVAL(req->vwv+4, 0);
8405 state->close_on_completion = BITSETW(req->vwv+5, 0);
8406 state->one_way = BITSETW(req->vwv+5, 1);
8408 state->call = tran_call;
8410 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8411 is so as a sanity check */
8412 if (state->setup_count != 1) {
8414 * Need to have rc=0 for ioctl to get job id for OS/2.
8415 * Network printing will fail if function is not successful.
8416 * Similar function in reply.c will be used if protocol
8417 * is LANMAN1.0 instead of LM1.2X002.
8418 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8419 * outbuf doesn't have to be set(only job id is used).
8421 if ( (state->setup_count == 4)
8422 && (tran_call == TRANSACT2_IOCTL)
8423 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8424 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8425 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8426 } else {
8427 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8428 DEBUG(2,("Transaction is %d\n",tran_call));
8429 TALLOC_FREE(state);
8430 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8431 END_PROFILE(SMBtrans2);
8432 return;
8436 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8437 goto bad_param;
8439 if (state->total_data) {
8441 if (trans_oob(state->total_data, 0, dscnt)
8442 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8443 goto bad_param;
8446 /* Can't use talloc here, the core routines do realloc on the
8447 * params and data. */
8448 state->data = (char *)SMB_MALLOC(state->total_data);
8449 if (state->data == NULL) {
8450 DEBUG(0,("reply_trans2: data malloc fail for %u "
8451 "bytes !\n", (unsigned int)state->total_data));
8452 TALLOC_FREE(state);
8453 reply_nterror(req, NT_STATUS_NO_MEMORY);
8454 END_PROFILE(SMBtrans2);
8455 return;
8458 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8461 if (state->total_param) {
8463 if (trans_oob(state->total_param, 0, pscnt)
8464 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8465 goto bad_param;
8468 /* Can't use talloc here, the core routines do realloc on the
8469 * params and data. */
8470 state->param = (char *)SMB_MALLOC(state->total_param);
8471 if (state->param == NULL) {
8472 DEBUG(0,("reply_trans: param malloc fail for %u "
8473 "bytes !\n", (unsigned int)state->total_param));
8474 SAFE_FREE(state->data);
8475 TALLOC_FREE(state);
8476 reply_nterror(req, NT_STATUS_NO_MEMORY);
8477 END_PROFILE(SMBtrans2);
8478 return;
8481 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8484 state->received_data = dscnt;
8485 state->received_param = pscnt;
8487 if ((state->received_param == state->total_param) &&
8488 (state->received_data == state->total_data)) {
8490 handle_trans2(conn, req, state);
8492 SAFE_FREE(state->data);
8493 SAFE_FREE(state->param);
8494 TALLOC_FREE(state);
8495 END_PROFILE(SMBtrans2);
8496 return;
8499 DLIST_ADD(conn->pending_trans, state);
8501 /* We need to send an interim response then receive the rest
8502 of the parameter/data bytes */
8503 reply_outbuf(req, 0, 0);
8504 show_msg((char *)req->outbuf);
8505 END_PROFILE(SMBtrans2);
8506 return;
8508 bad_param:
8510 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8511 SAFE_FREE(state->data);
8512 SAFE_FREE(state->param);
8513 TALLOC_FREE(state);
8514 END_PROFILE(SMBtrans2);
8515 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8519 /****************************************************************************
8520 Reply to a SMBtranss2
8521 ****************************************************************************/
8523 void reply_transs2(struct smb_request *req)
8525 connection_struct *conn = req->conn;
8526 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8527 struct trans_state *state;
8529 START_PROFILE(SMBtranss2);
8531 show_msg((char *)req->inbuf);
8533 if (req->wct < 8) {
8534 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8535 END_PROFILE(SMBtranss2);
8536 return;
8539 for (state = conn->pending_trans; state != NULL;
8540 state = state->next) {
8541 if (state->mid == req->mid) {
8542 break;
8546 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8547 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8548 END_PROFILE(SMBtranss2);
8549 return;
8552 /* Revise state->total_param and state->total_data in case they have
8553 changed downwards */
8555 if (SVAL(req->vwv+0, 0) < state->total_param)
8556 state->total_param = SVAL(req->vwv+0, 0);
8557 if (SVAL(req->vwv+1, 0) < state->total_data)
8558 state->total_data = SVAL(req->vwv+1, 0);
8560 pcnt = SVAL(req->vwv+2, 0);
8561 poff = SVAL(req->vwv+3, 0);
8562 pdisp = SVAL(req->vwv+4, 0);
8564 dcnt = SVAL(req->vwv+5, 0);
8565 doff = SVAL(req->vwv+6, 0);
8566 ddisp = SVAL(req->vwv+7, 0);
8568 state->received_param += pcnt;
8569 state->received_data += dcnt;
8571 if ((state->received_data > state->total_data) ||
8572 (state->received_param > state->total_param))
8573 goto bad_param;
8575 if (pcnt) {
8576 if (trans_oob(state->total_param, pdisp, pcnt)
8577 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8578 goto bad_param;
8580 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8583 if (dcnt) {
8584 if (trans_oob(state->total_data, ddisp, dcnt)
8585 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8586 goto bad_param;
8588 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8591 if ((state->received_param < state->total_param) ||
8592 (state->received_data < state->total_data)) {
8593 END_PROFILE(SMBtranss2);
8594 return;
8597 handle_trans2(conn, req, state);
8599 DLIST_REMOVE(conn->pending_trans, state);
8600 SAFE_FREE(state->data);
8601 SAFE_FREE(state->param);
8602 TALLOC_FREE(state);
8604 END_PROFILE(SMBtranss2);
8605 return;
8607 bad_param:
8609 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8610 DLIST_REMOVE(conn->pending_trans, state);
8611 SAFE_FREE(state->data);
8612 SAFE_FREE(state->param);
8613 TALLOC_FREE(state);
8614 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8615 END_PROFILE(SMBtranss2);
8616 return;