s4-install: fixed install path for python scripts
[Samba/cd1.git] / source3 / smbd / trans2.c
blob2892e26c772e9b392bf760c3b25bf99053c0f881
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_DOSTIMESTAMPS,
74 SAMBA_XATTR_MARKER,
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)
5543 NTSTATUS status = NT_STATUS_OK;
5544 struct smb_filename *smb_fname_tmp = NULL;
5545 files_struct *new_fsp = NULL;
5547 if (!VALID_STAT(*psbuf)) {
5548 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5551 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5553 if (size == get_file_size_stat(psbuf)) {
5554 return NT_STATUS_OK;
5557 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5558 smb_fname_str_dbg(smb_fname), (double)size));
5560 if (fsp && fsp->fh->fd != -1) {
5561 /* Handle based call. */
5562 if (vfs_set_filelen(fsp, size) == -1) {
5563 return map_nt_error_from_unix(errno);
5565 trigger_write_time_update_immediate(fsp);
5566 return NT_STATUS_OK;
5569 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5570 if (!NT_STATUS_IS_OK(status)) {
5571 return status;
5574 smb_fname_tmp->st = *psbuf;
5576 status = SMB_VFS_CREATE_FILE(
5577 conn, /* conn */
5578 req, /* req */
5579 0, /* root_dir_fid */
5580 smb_fname_tmp, /* fname */
5581 FILE_WRITE_DATA, /* access_mask */
5582 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5583 FILE_SHARE_DELETE),
5584 FILE_OPEN, /* create_disposition*/
5585 0, /* create_options */
5586 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5587 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5588 0, /* allocation_size */
5589 NULL, /* sd */
5590 NULL, /* ea_list */
5591 &new_fsp, /* result */
5592 NULL); /* pinfo */
5594 TALLOC_FREE(smb_fname_tmp);
5596 if (!NT_STATUS_IS_OK(status)) {
5597 /* NB. We check for open_was_deferred in the caller. */
5598 return status;
5601 if (vfs_set_filelen(new_fsp, size) == -1) {
5602 status = map_nt_error_from_unix(errno);
5603 close_file(req, new_fsp,NORMAL_CLOSE);
5604 return status;
5607 trigger_write_time_update_immediate(new_fsp);
5608 close_file(req, new_fsp,NORMAL_CLOSE);
5609 return NT_STATUS_OK;
5612 /****************************************************************************
5613 Deal with SMB_INFO_SET_EA.
5614 ****************************************************************************/
5616 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5617 const char *pdata,
5618 int total_data,
5619 files_struct *fsp,
5620 const struct smb_filename *smb_fname)
5622 struct ea_list *ea_list = NULL;
5623 TALLOC_CTX *ctx = NULL;
5624 NTSTATUS status = NT_STATUS_OK;
5626 if (total_data < 10) {
5628 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5629 length. They seem to have no effect. Bug #3212. JRA */
5631 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5632 /* We're done. We only get EA info in this call. */
5633 return NT_STATUS_OK;
5636 return NT_STATUS_INVALID_PARAMETER;
5639 if (IVAL(pdata,0) > total_data) {
5640 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5641 IVAL(pdata,0), (unsigned int)total_data));
5642 return NT_STATUS_INVALID_PARAMETER;
5645 ctx = talloc_tos();
5646 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5647 if (!ea_list) {
5648 return NT_STATUS_INVALID_PARAMETER;
5650 status = set_ea(conn, fsp, smb_fname, ea_list);
5652 return status;
5655 /****************************************************************************
5656 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5657 ****************************************************************************/
5659 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5660 const char *pdata,
5661 int total_data,
5662 files_struct *fsp)
5664 struct ea_list *ea_list = NULL;
5665 NTSTATUS status;
5667 if (!fsp) {
5668 return NT_STATUS_INVALID_HANDLE;
5671 if (!lp_ea_support(SNUM(conn))) {
5672 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5673 "EA's not supported.\n",
5674 (unsigned int)total_data));
5675 return NT_STATUS_EAS_NOT_SUPPORTED;
5678 if (total_data < 10) {
5679 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5680 "too small.\n",
5681 (unsigned int)total_data));
5682 return NT_STATUS_INVALID_PARAMETER;
5685 ea_list = read_nttrans_ea_list(talloc_tos(),
5686 pdata,
5687 total_data);
5689 if (!ea_list) {
5690 return NT_STATUS_INVALID_PARAMETER;
5692 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5694 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5695 smb_fname_str_dbg(fsp->fsp_name),
5696 nt_errstr(status) ));
5698 return status;
5702 /****************************************************************************
5703 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5704 ****************************************************************************/
5706 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5707 const char *pdata,
5708 int total_data,
5709 files_struct *fsp,
5710 struct smb_filename *smb_fname)
5712 NTSTATUS status = NT_STATUS_OK;
5713 bool delete_on_close;
5714 uint32 dosmode = 0;
5716 if (total_data < 1) {
5717 return NT_STATUS_INVALID_PARAMETER;
5720 if (fsp == NULL) {
5721 return NT_STATUS_INVALID_HANDLE;
5724 delete_on_close = (CVAL(pdata,0) ? True : False);
5725 dosmode = dos_mode(conn, smb_fname);
5727 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5728 "delete_on_close = %u\n",
5729 smb_fname_str_dbg(smb_fname),
5730 (unsigned int)dosmode,
5731 (unsigned int)delete_on_close ));
5733 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5735 if (!NT_STATUS_IS_OK(status)) {
5736 return status;
5739 /* The set is across all open files on this dev/inode pair. */
5740 if (!set_delete_on_close(fsp, delete_on_close,
5741 &conn->server_info->utok)) {
5742 return NT_STATUS_ACCESS_DENIED;
5744 return NT_STATUS_OK;
5747 /****************************************************************************
5748 Deal with SMB_FILE_POSITION_INFORMATION.
5749 ****************************************************************************/
5751 static NTSTATUS smb_file_position_information(connection_struct *conn,
5752 const char *pdata,
5753 int total_data,
5754 files_struct *fsp)
5756 uint64_t position_information;
5758 if (total_data < 8) {
5759 return NT_STATUS_INVALID_PARAMETER;
5762 if (fsp == NULL) {
5763 /* Ignore on pathname based set. */
5764 return NT_STATUS_OK;
5767 position_information = (uint64_t)IVAL(pdata,0);
5768 #ifdef LARGE_SMB_OFF_T
5769 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5770 #else /* LARGE_SMB_OFF_T */
5771 if (IVAL(pdata,4) != 0) {
5772 /* more than 32 bits? */
5773 return NT_STATUS_INVALID_PARAMETER;
5775 #endif /* LARGE_SMB_OFF_T */
5777 DEBUG(10,("smb_file_position_information: Set file position "
5778 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5779 (double)position_information));
5780 fsp->fh->position_information = position_information;
5781 return NT_STATUS_OK;
5784 /****************************************************************************
5785 Deal with SMB_FILE_MODE_INFORMATION.
5786 ****************************************************************************/
5788 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5789 const char *pdata,
5790 int total_data)
5792 uint32 mode;
5794 if (total_data < 4) {
5795 return NT_STATUS_INVALID_PARAMETER;
5797 mode = IVAL(pdata,0);
5798 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5799 return NT_STATUS_INVALID_PARAMETER;
5801 return NT_STATUS_OK;
5804 /****************************************************************************
5805 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5806 ****************************************************************************/
5808 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5809 struct smb_request *req,
5810 const char *pdata,
5811 int total_data,
5812 const struct smb_filename *smb_fname)
5814 char *link_target = NULL;
5815 const char *newname = smb_fname->base_name;
5816 NTSTATUS status = NT_STATUS_OK;
5817 TALLOC_CTX *ctx = talloc_tos();
5819 /* Set a symbolic link. */
5820 /* Don't allow this if follow links is false. */
5822 if (total_data == 0) {
5823 return NT_STATUS_INVALID_PARAMETER;
5826 if (!lp_symlinks(SNUM(conn))) {
5827 return NT_STATUS_ACCESS_DENIED;
5830 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5831 total_data, STR_TERMINATE);
5833 if (!link_target) {
5834 return NT_STATUS_INVALID_PARAMETER;
5837 /* !widelinks forces the target path to be within the share. */
5838 /* This means we can interpret the target as a pathname. */
5839 if (!lp_widelinks(SNUM(conn))) {
5840 char *rel_name = NULL;
5841 char *last_dirp = NULL;
5843 if (*link_target == '/') {
5844 /* No absolute paths allowed. */
5845 return NT_STATUS_ACCESS_DENIED;
5847 rel_name = talloc_strdup(ctx,newname);
5848 if (!rel_name) {
5849 return NT_STATUS_NO_MEMORY;
5851 last_dirp = strrchr_m(rel_name, '/');
5852 if (last_dirp) {
5853 last_dirp[1] = '\0';
5854 } else {
5855 rel_name = talloc_strdup(ctx,"./");
5856 if (!rel_name) {
5857 return NT_STATUS_NO_MEMORY;
5860 rel_name = talloc_asprintf_append(rel_name,
5861 "%s",
5862 link_target);
5863 if (!rel_name) {
5864 return NT_STATUS_NO_MEMORY;
5867 status = check_name(conn, rel_name);
5868 if (!NT_STATUS_IS_OK(status)) {
5869 return status;
5873 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5874 newname, link_target ));
5876 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5877 return map_nt_error_from_unix(errno);
5880 return NT_STATUS_OK;
5883 /****************************************************************************
5884 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5885 ****************************************************************************/
5887 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5888 struct smb_request *req,
5889 const char *pdata, int total_data,
5890 const struct smb_filename *smb_fname_new)
5892 char *oldname = NULL;
5893 struct smb_filename *smb_fname_old = NULL;
5894 TALLOC_CTX *ctx = talloc_tos();
5895 NTSTATUS status = NT_STATUS_OK;
5897 /* Set a hard link. */
5898 if (total_data == 0) {
5899 return NT_STATUS_INVALID_PARAMETER;
5902 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5903 total_data, STR_TERMINATE, &status);
5904 if (!NT_STATUS_IS_OK(status)) {
5905 return status;
5908 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5909 smb_fname_str_dbg(smb_fname_new), oldname));
5911 status = filename_convert(ctx,
5912 conn,
5913 req->flags2 & FLAGS2_DFS_PATHNAMES,
5914 oldname,
5916 NULL,
5917 &smb_fname_old);
5918 if (!NT_STATUS_IS_OK(status)) {
5919 return status;
5922 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5925 /****************************************************************************
5926 Deal with SMB_FILE_RENAME_INFORMATION.
5927 ****************************************************************************/
5929 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5930 struct smb_request *req,
5931 const char *pdata,
5932 int total_data,
5933 files_struct *fsp,
5934 struct smb_filename *smb_fname_src)
5936 bool overwrite;
5937 uint32 root_fid;
5938 uint32 len;
5939 char *newname = NULL;
5940 struct smb_filename *smb_fname_dst = NULL;
5941 bool dest_has_wcard = False;
5942 NTSTATUS status = NT_STATUS_OK;
5943 char *p;
5944 TALLOC_CTX *ctx = talloc_tos();
5946 if (total_data < 13) {
5947 return NT_STATUS_INVALID_PARAMETER;
5950 overwrite = (CVAL(pdata,0) ? True : False);
5951 root_fid = IVAL(pdata,4);
5952 len = IVAL(pdata,8);
5954 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5955 return NT_STATUS_INVALID_PARAMETER;
5958 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5959 len, 0, &status,
5960 &dest_has_wcard);
5961 if (!NT_STATUS_IS_OK(status)) {
5962 return status;
5965 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5966 newname));
5968 status = resolve_dfspath_wcard(ctx, conn,
5969 req->flags2 & FLAGS2_DFS_PATHNAMES,
5970 newname,
5971 &newname,
5972 &dest_has_wcard);
5973 if (!NT_STATUS_IS_OK(status)) {
5974 return status;
5977 /* Check the new name has no '/' characters. */
5978 if (strchr_m(newname, '/')) {
5979 return NT_STATUS_NOT_SUPPORTED;
5982 if (fsp && fsp->base_fsp) {
5983 /* newname must be a stream name. */
5984 if (newname[0] != ':') {
5985 return NT_STATUS_NOT_SUPPORTED;
5988 /* Create an smb_fname to call rename_internals_fsp() with. */
5989 status = create_synthetic_smb_fname(talloc_tos(),
5990 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5991 &smb_fname_dst);
5992 if (!NT_STATUS_IS_OK(status)) {
5993 goto out;
5997 * Set the original last component, since
5998 * rename_internals_fsp() requires it.
6000 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6001 newname);
6002 if (smb_fname_dst->original_lcomp == NULL) {
6003 status = NT_STATUS_NO_MEMORY;
6004 goto out;
6007 } else {
6009 * Build up an smb_fname_dst based on the filename passed in.
6010 * We basically just strip off the last component, and put on
6011 * the newname instead.
6013 char *base_name = NULL;
6015 /* newname must *not* be a stream name. */
6016 if (newname[0] == ':') {
6017 return NT_STATUS_NOT_SUPPORTED;
6021 * Strip off the last component (filename) of the path passed
6022 * in.
6024 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6025 if (!base_name) {
6026 return NT_STATUS_NO_MEMORY;
6028 p = strrchr_m(base_name, '/');
6029 if (p) {
6030 p[1] = '\0';
6031 } else {
6032 base_name = talloc_strdup(ctx, "./");
6033 if (!base_name) {
6034 return NT_STATUS_NO_MEMORY;
6037 /* Append the new name. */
6038 base_name = talloc_asprintf_append(base_name,
6039 "%s",
6040 newname);
6041 if (!base_name) {
6042 return NT_STATUS_NO_MEMORY;
6045 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6046 (UCF_SAVE_LCOMP |
6047 (dest_has_wcard ?
6048 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6049 0)));
6051 /* If an error we expect this to be
6052 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6054 if (!NT_STATUS_IS_OK(status)) {
6055 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6056 status)) {
6057 goto out;
6059 /* Create an smb_fname to call rename_internals_fsp() */
6060 status = create_synthetic_smb_fname(ctx,
6061 base_name, NULL,
6062 NULL,
6063 &smb_fname_dst);
6064 if (!NT_STATUS_IS_OK(status)) {
6065 goto out;
6070 if (fsp) {
6071 DEBUG(10,("smb_file_rename_information: "
6072 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6073 fsp->fnum, fsp_str_dbg(fsp),
6074 smb_fname_str_dbg(smb_fname_dst)));
6075 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6076 overwrite);
6077 } else {
6078 DEBUG(10,("smb_file_rename_information: "
6079 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6080 smb_fname_str_dbg(smb_fname_src),
6081 smb_fname_str_dbg(smb_fname_dst)));
6082 status = rename_internals(ctx, conn, req, smb_fname_src,
6083 smb_fname_dst, 0, overwrite, false,
6084 dest_has_wcard,
6085 FILE_WRITE_ATTRIBUTES);
6087 out:
6088 TALLOC_FREE(smb_fname_dst);
6089 return status;
6092 /****************************************************************************
6093 Deal with SMB_SET_POSIX_ACL.
6094 ****************************************************************************/
6096 #if defined(HAVE_POSIX_ACLS)
6097 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6098 const char *pdata,
6099 int total_data,
6100 files_struct *fsp,
6101 const struct smb_filename *smb_fname)
6103 uint16 posix_acl_version;
6104 uint16 num_file_acls;
6105 uint16 num_def_acls;
6106 bool valid_file_acls = True;
6107 bool valid_def_acls = True;
6109 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6110 return NT_STATUS_INVALID_PARAMETER;
6112 posix_acl_version = SVAL(pdata,0);
6113 num_file_acls = SVAL(pdata,2);
6114 num_def_acls = SVAL(pdata,4);
6116 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6117 valid_file_acls = False;
6118 num_file_acls = 0;
6121 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6122 valid_def_acls = False;
6123 num_def_acls = 0;
6126 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6127 return NT_STATUS_INVALID_PARAMETER;
6130 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6131 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6132 return NT_STATUS_INVALID_PARAMETER;
6135 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6136 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6137 (unsigned int)num_file_acls,
6138 (unsigned int)num_def_acls));
6140 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6141 smb_fname->base_name, num_file_acls,
6142 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6143 return map_nt_error_from_unix(errno);
6146 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6147 smb_fname->base_name, &smb_fname->st, num_def_acls,
6148 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6149 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6150 return map_nt_error_from_unix(errno);
6152 return NT_STATUS_OK;
6154 #endif
6156 /****************************************************************************
6157 Deal with SMB_SET_POSIX_LOCK.
6158 ****************************************************************************/
6160 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6161 struct smb_request *req,
6162 const char *pdata,
6163 int total_data,
6164 files_struct *fsp)
6166 uint64_t count;
6167 uint64_t offset;
6168 uint32 lock_pid;
6169 bool blocking_lock = False;
6170 enum brl_type lock_type;
6172 NTSTATUS status = NT_STATUS_OK;
6174 if (fsp == NULL || fsp->fh->fd == -1) {
6175 return NT_STATUS_INVALID_HANDLE;
6178 if (total_data != POSIX_LOCK_DATA_SIZE) {
6179 return NT_STATUS_INVALID_PARAMETER;
6182 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6183 case POSIX_LOCK_TYPE_READ:
6184 lock_type = READ_LOCK;
6185 break;
6186 case POSIX_LOCK_TYPE_WRITE:
6187 /* Return the right POSIX-mappable error code for files opened read-only. */
6188 if (!fsp->can_write) {
6189 return NT_STATUS_INVALID_HANDLE;
6191 lock_type = WRITE_LOCK;
6192 break;
6193 case POSIX_LOCK_TYPE_UNLOCK:
6194 lock_type = UNLOCK_LOCK;
6195 break;
6196 default:
6197 return NT_STATUS_INVALID_PARAMETER;
6200 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6201 blocking_lock = False;
6202 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6203 blocking_lock = True;
6204 } else {
6205 return NT_STATUS_INVALID_PARAMETER;
6208 if (!lp_blocking_locks(SNUM(conn))) {
6209 blocking_lock = False;
6212 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6213 #if defined(HAVE_LONGLONG)
6214 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6215 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6216 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6217 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6218 #else /* HAVE_LONGLONG */
6219 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6220 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6221 #endif /* HAVE_LONGLONG */
6223 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6224 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6225 fsp_str_dbg(fsp),
6226 (unsigned int)lock_type,
6227 (unsigned int)lock_pid,
6228 (double)count,
6229 (double)offset ));
6231 if (lock_type == UNLOCK_LOCK) {
6232 status = do_unlock(smbd_messaging_context(),
6233 fsp,
6234 lock_pid,
6235 count,
6236 offset,
6237 POSIX_LOCK);
6238 } else {
6239 uint32 block_smbpid;
6241 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6242 fsp,
6243 lock_pid,
6244 count,
6245 offset,
6246 lock_type,
6247 POSIX_LOCK,
6248 blocking_lock,
6249 &status,
6250 &block_smbpid,
6251 NULL);
6253 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6255 * A blocking lock was requested. Package up
6256 * this smb into a queued request and push it
6257 * onto the blocking lock queue.
6259 if(push_blocking_lock_request(br_lck,
6260 req,
6261 fsp,
6262 -1, /* infinite timeout. */
6264 lock_pid,
6265 lock_type,
6266 POSIX_LOCK,
6267 offset,
6268 count,
6269 block_smbpid)) {
6270 TALLOC_FREE(br_lck);
6271 return status;
6274 TALLOC_FREE(br_lck);
6277 return status;
6280 /****************************************************************************
6281 Deal with SMB_SET_FILE_BASIC_INFO.
6282 ****************************************************************************/
6284 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6285 const char *pdata,
6286 int total_data,
6287 files_struct *fsp,
6288 const struct smb_filename *smb_fname)
6290 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6291 struct smb_file_time ft;
6292 uint32 dosmode = 0;
6293 NTSTATUS status = NT_STATUS_OK;
6295 ZERO_STRUCT(ft);
6297 if (total_data < 36) {
6298 return NT_STATUS_INVALID_PARAMETER;
6301 /* Set the attributes */
6302 dosmode = IVAL(pdata,32);
6303 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6304 if (!NT_STATUS_IS_OK(status)) {
6305 return status;
6308 /* create time */
6309 ft.create_time = interpret_long_date(pdata);
6311 /* access time */
6312 ft.atime = interpret_long_date(pdata+8);
6314 /* write time. */
6315 ft.mtime = interpret_long_date(pdata+16);
6317 /* change time. */
6318 ft.ctime = interpret_long_date(pdata+24);
6320 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6321 smb_fname_str_dbg(smb_fname)));
6323 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6324 true);
6327 /****************************************************************************
6328 Deal with SMB_INFO_STANDARD.
6329 ****************************************************************************/
6331 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6332 const char *pdata,
6333 int total_data,
6334 files_struct *fsp,
6335 const struct smb_filename *smb_fname)
6337 struct smb_file_time ft;
6339 ZERO_STRUCT(ft);
6341 if (total_data < 12) {
6342 return NT_STATUS_INVALID_PARAMETER;
6345 /* create time */
6346 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6347 /* access time */
6348 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6349 /* write time */
6350 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6352 DEBUG(10,("smb_set_info_standard: file %s\n",
6353 smb_fname_str_dbg(smb_fname)));
6355 return smb_set_file_time(conn,
6356 fsp,
6357 smb_fname,
6358 &ft,
6359 true);
6362 /****************************************************************************
6363 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6364 ****************************************************************************/
6366 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6367 struct smb_request *req,
6368 const char *pdata,
6369 int total_data,
6370 files_struct *fsp,
6371 struct smb_filename *smb_fname)
6373 uint64_t allocation_size = 0;
6374 NTSTATUS status = NT_STATUS_OK;
6375 files_struct *new_fsp = NULL;
6377 if (!VALID_STAT(smb_fname->st)) {
6378 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6381 if (total_data < 8) {
6382 return NT_STATUS_INVALID_PARAMETER;
6385 allocation_size = (uint64_t)IVAL(pdata,0);
6386 #ifdef LARGE_SMB_OFF_T
6387 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6388 #else /* LARGE_SMB_OFF_T */
6389 if (IVAL(pdata,4) != 0) {
6390 /* more than 32 bits? */
6391 return NT_STATUS_INVALID_PARAMETER;
6393 #endif /* LARGE_SMB_OFF_T */
6395 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6396 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6397 (double)allocation_size));
6399 if (allocation_size) {
6400 allocation_size = smb_roundup(conn, allocation_size);
6403 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6404 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6405 (double)allocation_size));
6407 if (fsp && fsp->fh->fd != -1) {
6408 /* Open file handle. */
6409 /* Only change if needed. */
6410 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6411 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6412 return map_nt_error_from_unix(errno);
6415 /* But always update the time. */
6417 * This is equivalent to a write. Ensure it's seen immediately
6418 * if there are no pending writes.
6420 trigger_write_time_update_immediate(fsp);
6421 return NT_STATUS_OK;
6424 /* Pathname or stat or directory file. */
6425 status = SMB_VFS_CREATE_FILE(
6426 conn, /* conn */
6427 req, /* req */
6428 0, /* root_dir_fid */
6429 smb_fname, /* fname */
6430 FILE_WRITE_DATA, /* access_mask */
6431 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6432 FILE_SHARE_DELETE),
6433 FILE_OPEN, /* create_disposition*/
6434 0, /* create_options */
6435 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6436 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6437 0, /* allocation_size */
6438 NULL, /* sd */
6439 NULL, /* ea_list */
6440 &new_fsp, /* result */
6441 NULL); /* pinfo */
6443 if (!NT_STATUS_IS_OK(status)) {
6444 /* NB. We check for open_was_deferred in the caller. */
6445 return status;
6448 /* Only change if needed. */
6449 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6450 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6451 status = map_nt_error_from_unix(errno);
6452 close_file(req, new_fsp, NORMAL_CLOSE);
6453 return status;
6457 /* Changing the allocation size should set the last mod time. */
6459 * This is equivalent to a write. Ensure it's seen immediately
6460 * if there are no pending writes.
6462 trigger_write_time_update_immediate(new_fsp);
6464 close_file(req, new_fsp, NORMAL_CLOSE);
6465 return NT_STATUS_OK;
6468 /****************************************************************************
6469 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6470 ****************************************************************************/
6472 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6473 struct smb_request *req,
6474 const char *pdata,
6475 int total_data,
6476 files_struct *fsp,
6477 const struct smb_filename *smb_fname)
6479 SMB_OFF_T size;
6481 if (total_data < 8) {
6482 return NT_STATUS_INVALID_PARAMETER;
6485 size = IVAL(pdata,0);
6486 #ifdef LARGE_SMB_OFF_T
6487 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6488 #else /* LARGE_SMB_OFF_T */
6489 if (IVAL(pdata,4) != 0) {
6490 /* more than 32 bits? */
6491 return NT_STATUS_INVALID_PARAMETER;
6493 #endif /* LARGE_SMB_OFF_T */
6494 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6495 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6496 (double)size));
6498 return smb_set_file_size(conn, req,
6499 fsp,
6500 smb_fname,
6501 &smb_fname->st,
6502 size);
6505 /****************************************************************************
6506 Allow a UNIX info mknod.
6507 ****************************************************************************/
6509 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6510 const char *pdata,
6511 int total_data,
6512 const struct smb_filename *smb_fname)
6514 uint32 file_type = IVAL(pdata,56);
6515 #if defined(HAVE_MAKEDEV)
6516 uint32 dev_major = IVAL(pdata,60);
6517 uint32 dev_minor = IVAL(pdata,68);
6518 #endif
6519 SMB_DEV_T dev = (SMB_DEV_T)0;
6520 uint32 raw_unixmode = IVAL(pdata,84);
6521 NTSTATUS status;
6522 mode_t unixmode;
6524 if (total_data < 100) {
6525 return NT_STATUS_INVALID_PARAMETER;
6528 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6529 PERM_NEW_FILE, &unixmode);
6530 if (!NT_STATUS_IS_OK(status)) {
6531 return status;
6534 #if defined(HAVE_MAKEDEV)
6535 dev = makedev(dev_major, dev_minor);
6536 #endif
6538 switch (file_type) {
6539 #if defined(S_IFIFO)
6540 case UNIX_TYPE_FIFO:
6541 unixmode |= S_IFIFO;
6542 break;
6543 #endif
6544 #if defined(S_IFSOCK)
6545 case UNIX_TYPE_SOCKET:
6546 unixmode |= S_IFSOCK;
6547 break;
6548 #endif
6549 #if defined(S_IFCHR)
6550 case UNIX_TYPE_CHARDEV:
6551 unixmode |= S_IFCHR;
6552 break;
6553 #endif
6554 #if defined(S_IFBLK)
6555 case UNIX_TYPE_BLKDEV:
6556 unixmode |= S_IFBLK;
6557 break;
6558 #endif
6559 default:
6560 return NT_STATUS_INVALID_PARAMETER;
6563 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6564 "%.0f mode 0%o for file %s\n", (double)dev,
6565 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6567 /* Ok - do the mknod. */
6568 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6569 return map_nt_error_from_unix(errno);
6572 /* If any of the other "set" calls fail we
6573 * don't want to end up with a half-constructed mknod.
6576 if (lp_inherit_perms(SNUM(conn))) {
6577 char *parent;
6578 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6579 &parent, NULL)) {
6580 return NT_STATUS_NO_MEMORY;
6582 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6583 unixmode);
6584 TALLOC_FREE(parent);
6587 return NT_STATUS_OK;
6590 /****************************************************************************
6591 Deal with SMB_SET_FILE_UNIX_BASIC.
6592 ****************************************************************************/
6594 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6595 struct smb_request *req,
6596 const char *pdata,
6597 int total_data,
6598 files_struct *fsp,
6599 const struct smb_filename *smb_fname)
6601 struct smb_file_time ft;
6602 uint32 raw_unixmode;
6603 mode_t unixmode;
6604 SMB_OFF_T size = 0;
6605 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6606 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6607 NTSTATUS status = NT_STATUS_OK;
6608 bool delete_on_fail = False;
6609 enum perm_type ptype;
6610 files_struct *all_fsps = NULL;
6611 bool modify_mtime = true;
6612 struct file_id id;
6613 SMB_STRUCT_STAT sbuf;
6615 ZERO_STRUCT(ft);
6617 if (total_data < 100) {
6618 return NT_STATUS_INVALID_PARAMETER;
6621 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6622 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6623 size=IVAL(pdata,0); /* first 8 Bytes are size */
6624 #ifdef LARGE_SMB_OFF_T
6625 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6626 #else /* LARGE_SMB_OFF_T */
6627 if (IVAL(pdata,4) != 0) {
6628 /* more than 32 bits? */
6629 return NT_STATUS_INVALID_PARAMETER;
6631 #endif /* LARGE_SMB_OFF_T */
6634 ft.atime = interpret_long_date(pdata+24); /* access_time */
6635 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6636 set_owner = (uid_t)IVAL(pdata,40);
6637 set_grp = (gid_t)IVAL(pdata,48);
6638 raw_unixmode = IVAL(pdata,84);
6640 if (VALID_STAT(smb_fname->st)) {
6641 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6642 ptype = PERM_EXISTING_DIR;
6643 } else {
6644 ptype = PERM_EXISTING_FILE;
6646 } else {
6647 ptype = PERM_NEW_FILE;
6650 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6651 ptype, &unixmode);
6652 if (!NT_STATUS_IS_OK(status)) {
6653 return status;
6656 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6657 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6658 smb_fname_str_dbg(smb_fname), (double)size,
6659 (unsigned int)set_owner, (unsigned int)set_grp,
6660 (int)raw_unixmode));
6662 sbuf = smb_fname->st;
6664 if (!VALID_STAT(sbuf)) {
6665 struct smb_filename *smb_fname_tmp = NULL;
6667 * The only valid use of this is to create character and block
6668 * devices, and named pipes. This is deprecated (IMHO) and
6669 * a new info level should be used for mknod. JRA.
6672 status = smb_unix_mknod(conn,
6673 pdata,
6674 total_data,
6675 smb_fname);
6676 if (!NT_STATUS_IS_OK(status)) {
6677 return status;
6680 status = copy_smb_filename(talloc_tos(), smb_fname,
6681 &smb_fname_tmp);
6682 if (!NT_STATUS_IS_OK(status)) {
6683 return status;
6686 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6687 status = map_nt_error_from_unix(errno);
6688 TALLOC_FREE(smb_fname_tmp);
6689 SMB_VFS_UNLINK(conn, smb_fname);
6690 return status;
6693 sbuf = smb_fname_tmp->st;
6694 TALLOC_FREE(smb_fname_tmp);
6696 /* Ensure we don't try and change anything else. */
6697 raw_unixmode = SMB_MODE_NO_CHANGE;
6698 size = get_file_size_stat(&sbuf);
6699 ft.atime = sbuf.st_ex_atime;
6700 ft.mtime = sbuf.st_ex_mtime;
6702 * We continue here as we might want to change the
6703 * owner uid/gid.
6705 delete_on_fail = True;
6708 #if 1
6709 /* Horrible backwards compatibility hack as an old server bug
6710 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6711 * */
6713 if (!size) {
6714 size = get_file_size_stat(&sbuf);
6716 #endif
6719 * Deal with the UNIX specific mode set.
6722 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6723 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6724 "setting mode 0%o for file %s\n",
6725 (unsigned int)unixmode,
6726 smb_fname_str_dbg(smb_fname)));
6727 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6728 return map_nt_error_from_unix(errno);
6733 * Deal with the UNIX specific uid set.
6736 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6737 (sbuf.st_ex_uid != set_owner)) {
6738 int ret;
6740 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6741 "changing owner %u for path %s\n",
6742 (unsigned int)set_owner,
6743 smb_fname_str_dbg(smb_fname)));
6745 if (S_ISLNK(sbuf.st_ex_mode)) {
6746 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6747 set_owner, (gid_t)-1);
6748 } else {
6749 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6750 set_owner, (gid_t)-1);
6753 if (ret != 0) {
6754 status = map_nt_error_from_unix(errno);
6755 if (delete_on_fail) {
6756 SMB_VFS_UNLINK(conn, smb_fname);
6758 return status;
6763 * Deal with the UNIX specific gid set.
6766 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6767 (sbuf.st_ex_gid != set_grp)) {
6768 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6769 "changing group %u for file %s\n",
6770 (unsigned int)set_owner,
6771 smb_fname_str_dbg(smb_fname)));
6772 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6773 set_grp) != 0) {
6774 status = map_nt_error_from_unix(errno);
6775 if (delete_on_fail) {
6776 SMB_VFS_UNLINK(conn, smb_fname);
6778 return status;
6782 /* Deal with any size changes. */
6784 status = smb_set_file_size(conn, req,
6785 fsp,
6786 smb_fname,
6787 &sbuf,
6788 size);
6789 if (!NT_STATUS_IS_OK(status)) {
6790 return status;
6793 /* Deal with any time changes. */
6794 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6795 /* No change, don't cancel anything. */
6796 return status;
6799 id = vfs_file_id_from_sbuf(conn, &sbuf);
6800 for(all_fsps = file_find_di_first(id); all_fsps;
6801 all_fsps = file_find_di_next(all_fsps)) {
6803 * We're setting the time explicitly for UNIX.
6804 * Cancel any pending changes over all handles.
6806 all_fsps->update_write_time_on_close = false;
6807 TALLOC_FREE(all_fsps->update_write_time_event);
6811 * Override the "setting_write_time"
6812 * parameter here as it almost does what
6813 * we need. Just remember if we modified
6814 * mtime and send the notify ourselves.
6816 if (null_timespec(ft.mtime)) {
6817 modify_mtime = false;
6820 status = smb_set_file_time(conn,
6821 fsp,
6822 smb_fname,
6823 &ft,
6824 false);
6825 if (modify_mtime) {
6826 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6827 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6829 return status;
6832 /****************************************************************************
6833 Deal with SMB_SET_FILE_UNIX_INFO2.
6834 ****************************************************************************/
6836 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6837 struct smb_request *req,
6838 const char *pdata,
6839 int total_data,
6840 files_struct *fsp,
6841 const struct smb_filename *smb_fname)
6843 NTSTATUS status;
6844 uint32 smb_fflags;
6845 uint32 smb_fmask;
6847 if (total_data < 116) {
6848 return NT_STATUS_INVALID_PARAMETER;
6851 /* Start by setting all the fields that are common between UNIX_BASIC
6852 * and UNIX_INFO2.
6854 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6855 fsp, smb_fname);
6856 if (!NT_STATUS_IS_OK(status)) {
6857 return status;
6860 smb_fflags = IVAL(pdata, 108);
6861 smb_fmask = IVAL(pdata, 112);
6863 /* NB: We should only attempt to alter the file flags if the client
6864 * sends a non-zero mask.
6866 if (smb_fmask != 0) {
6867 int stat_fflags = 0;
6869 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6870 smb_fmask, &stat_fflags)) {
6871 /* Client asked to alter a flag we don't understand. */
6872 return NT_STATUS_INVALID_PARAMETER;
6875 if (fsp && fsp->fh->fd != -1) {
6876 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6877 return NT_STATUS_NOT_SUPPORTED;
6878 } else {
6879 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6880 stat_fflags) != 0) {
6881 return map_nt_error_from_unix(errno);
6886 /* XXX: need to add support for changing the create_time here. You
6887 * can do this for paths on Darwin with setattrlist(2). The right way
6888 * to hook this up is probably by extending the VFS utimes interface.
6891 return NT_STATUS_OK;
6894 /****************************************************************************
6895 Create a directory with POSIX semantics.
6896 ****************************************************************************/
6898 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6899 struct smb_request *req,
6900 char **ppdata,
6901 int total_data,
6902 struct smb_filename *smb_fname,
6903 int *pdata_return_size)
6905 NTSTATUS status = NT_STATUS_OK;
6906 uint32 raw_unixmode = 0;
6907 uint32 mod_unixmode = 0;
6908 mode_t unixmode = (mode_t)0;
6909 files_struct *fsp = NULL;
6910 uint16 info_level_return = 0;
6911 int info;
6912 char *pdata = *ppdata;
6914 if (total_data < 18) {
6915 return NT_STATUS_INVALID_PARAMETER;
6918 raw_unixmode = IVAL(pdata,8);
6919 /* Next 4 bytes are not yet defined. */
6921 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6922 PERM_NEW_DIR, &unixmode);
6923 if (!NT_STATUS_IS_OK(status)) {
6924 return status;
6927 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6929 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6930 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6932 status = SMB_VFS_CREATE_FILE(
6933 conn, /* conn */
6934 req, /* req */
6935 0, /* root_dir_fid */
6936 smb_fname, /* fname */
6937 FILE_READ_ATTRIBUTES, /* access_mask */
6938 FILE_SHARE_NONE, /* share_access */
6939 FILE_CREATE, /* create_disposition*/
6940 FILE_DIRECTORY_FILE, /* create_options */
6941 mod_unixmode, /* file_attributes */
6942 0, /* oplock_request */
6943 0, /* allocation_size */
6944 NULL, /* sd */
6945 NULL, /* ea_list */
6946 &fsp, /* result */
6947 &info); /* pinfo */
6949 if (NT_STATUS_IS_OK(status)) {
6950 close_file(req, fsp, NORMAL_CLOSE);
6953 info_level_return = SVAL(pdata,16);
6955 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6956 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6957 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6958 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6959 } else {
6960 *pdata_return_size = 12;
6963 /* Realloc the data size */
6964 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6965 if (*ppdata == NULL) {
6966 *pdata_return_size = 0;
6967 return NT_STATUS_NO_MEMORY;
6969 pdata = *ppdata;
6971 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6972 SSVAL(pdata,2,0); /* No fnum. */
6973 SIVAL(pdata,4,info); /* Was directory created. */
6975 switch (info_level_return) {
6976 case SMB_QUERY_FILE_UNIX_BASIC:
6977 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6978 SSVAL(pdata,10,0); /* Padding. */
6979 store_file_unix_basic(conn, pdata + 12, fsp,
6980 &smb_fname->st);
6981 break;
6982 case SMB_QUERY_FILE_UNIX_INFO2:
6983 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6984 SSVAL(pdata,10,0); /* Padding. */
6985 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6986 &smb_fname->st);
6987 break;
6988 default:
6989 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6990 SSVAL(pdata,10,0); /* Padding. */
6991 break;
6994 return status;
6997 /****************************************************************************
6998 Open/Create a file with POSIX semantics.
6999 ****************************************************************************/
7001 static NTSTATUS smb_posix_open(connection_struct *conn,
7002 struct smb_request *req,
7003 char **ppdata,
7004 int total_data,
7005 struct smb_filename *smb_fname,
7006 int *pdata_return_size)
7008 bool extended_oplock_granted = False;
7009 char *pdata = *ppdata;
7010 uint32 flags = 0;
7011 uint32 wire_open_mode = 0;
7012 uint32 raw_unixmode = 0;
7013 uint32 mod_unixmode = 0;
7014 uint32 create_disp = 0;
7015 uint32 access_mask = 0;
7016 uint32 create_options = 0;
7017 NTSTATUS status = NT_STATUS_OK;
7018 mode_t unixmode = (mode_t)0;
7019 files_struct *fsp = NULL;
7020 int oplock_request = 0;
7021 int info = 0;
7022 uint16 info_level_return = 0;
7024 if (total_data < 18) {
7025 return NT_STATUS_INVALID_PARAMETER;
7028 flags = IVAL(pdata,0);
7029 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7030 if (oplock_request) {
7031 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7034 wire_open_mode = IVAL(pdata,4);
7036 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7037 return smb_posix_mkdir(conn, req,
7038 ppdata,
7039 total_data,
7040 smb_fname,
7041 pdata_return_size);
7044 switch (wire_open_mode & SMB_ACCMODE) {
7045 case SMB_O_RDONLY:
7046 access_mask = FILE_READ_DATA;
7047 break;
7048 case SMB_O_WRONLY:
7049 access_mask = FILE_WRITE_DATA;
7050 break;
7051 case SMB_O_RDWR:
7052 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7053 break;
7054 default:
7055 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7056 (unsigned int)wire_open_mode ));
7057 return NT_STATUS_INVALID_PARAMETER;
7060 wire_open_mode &= ~SMB_ACCMODE;
7062 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7063 create_disp = FILE_CREATE;
7064 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7065 create_disp = FILE_OVERWRITE_IF;
7066 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7067 create_disp = FILE_OPEN_IF;
7068 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7069 create_disp = FILE_OPEN;
7070 } else {
7071 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7072 (unsigned int)wire_open_mode ));
7073 return NT_STATUS_INVALID_PARAMETER;
7076 raw_unixmode = IVAL(pdata,8);
7077 /* Next 4 bytes are not yet defined. */
7079 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7080 (VALID_STAT(smb_fname->st) ?
7081 PERM_EXISTING_FILE : PERM_NEW_FILE),
7082 &unixmode);
7084 if (!NT_STATUS_IS_OK(status)) {
7085 return status;
7088 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7090 if (wire_open_mode & SMB_O_SYNC) {
7091 create_options |= FILE_WRITE_THROUGH;
7093 if (wire_open_mode & SMB_O_APPEND) {
7094 access_mask |= FILE_APPEND_DATA;
7096 if (wire_open_mode & SMB_O_DIRECT) {
7097 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7100 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7101 smb_fname_str_dbg(smb_fname),
7102 (unsigned int)wire_open_mode,
7103 (unsigned int)unixmode ));
7105 status = SMB_VFS_CREATE_FILE(
7106 conn, /* conn */
7107 req, /* req */
7108 0, /* root_dir_fid */
7109 smb_fname, /* fname */
7110 access_mask, /* access_mask */
7111 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7112 FILE_SHARE_DELETE),
7113 create_disp, /* create_disposition*/
7114 FILE_NON_DIRECTORY_FILE, /* create_options */
7115 mod_unixmode, /* file_attributes */
7116 oplock_request, /* oplock_request */
7117 0, /* allocation_size */
7118 NULL, /* sd */
7119 NULL, /* ea_list */
7120 &fsp, /* result */
7121 &info); /* pinfo */
7123 if (!NT_STATUS_IS_OK(status)) {
7124 return status;
7127 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7128 extended_oplock_granted = True;
7131 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7132 extended_oplock_granted = True;
7135 info_level_return = SVAL(pdata,16);
7137 /* Allocate the correct return size. */
7139 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7140 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7141 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7142 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7143 } else {
7144 *pdata_return_size = 12;
7147 /* Realloc the data size */
7148 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7149 if (*ppdata == NULL) {
7150 close_file(req, fsp, ERROR_CLOSE);
7151 *pdata_return_size = 0;
7152 return NT_STATUS_NO_MEMORY;
7154 pdata = *ppdata;
7156 if (extended_oplock_granted) {
7157 if (flags & REQUEST_BATCH_OPLOCK) {
7158 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7159 } else {
7160 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7162 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7163 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7164 } else {
7165 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7168 SSVAL(pdata,2,fsp->fnum);
7169 SIVAL(pdata,4,info); /* Was file created etc. */
7171 switch (info_level_return) {
7172 case SMB_QUERY_FILE_UNIX_BASIC:
7173 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7174 SSVAL(pdata,10,0); /* padding. */
7175 store_file_unix_basic(conn, pdata + 12, fsp,
7176 &smb_fname->st);
7177 break;
7178 case SMB_QUERY_FILE_UNIX_INFO2:
7179 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7180 SSVAL(pdata,10,0); /* padding. */
7181 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7182 &smb_fname->st);
7183 break;
7184 default:
7185 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7186 SSVAL(pdata,10,0); /* padding. */
7187 break;
7189 return NT_STATUS_OK;
7192 /****************************************************************************
7193 Delete a file with POSIX semantics.
7194 ****************************************************************************/
7196 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7197 struct smb_request *req,
7198 const char *pdata,
7199 int total_data,
7200 struct smb_filename *smb_fname)
7202 NTSTATUS status = NT_STATUS_OK;
7203 files_struct *fsp = NULL;
7204 uint16 flags = 0;
7205 char del = 1;
7206 int info = 0;
7207 int create_options = 0;
7208 int i;
7209 struct share_mode_lock *lck = NULL;
7211 if (total_data < 2) {
7212 return NT_STATUS_INVALID_PARAMETER;
7215 flags = SVAL(pdata,0);
7217 if (!VALID_STAT(smb_fname->st)) {
7218 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7221 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7222 !VALID_STAT_OF_DIR(smb_fname->st)) {
7223 return NT_STATUS_NOT_A_DIRECTORY;
7226 DEBUG(10,("smb_posix_unlink: %s %s\n",
7227 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7228 smb_fname_str_dbg(smb_fname)));
7230 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7231 create_options |= FILE_DIRECTORY_FILE;
7234 status = SMB_VFS_CREATE_FILE(
7235 conn, /* conn */
7236 req, /* req */
7237 0, /* root_dir_fid */
7238 smb_fname, /* fname */
7239 DELETE_ACCESS, /* access_mask */
7240 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7241 FILE_SHARE_DELETE),
7242 FILE_OPEN, /* create_disposition*/
7243 create_options, /* create_options */
7244 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7245 0, /* oplock_request */
7246 0, /* allocation_size */
7247 NULL, /* sd */
7248 NULL, /* ea_list */
7249 &fsp, /* result */
7250 &info); /* pinfo */
7252 if (!NT_STATUS_IS_OK(status)) {
7253 return status;
7257 * Don't lie to client. If we can't really delete due to
7258 * non-POSIX opens return SHARING_VIOLATION.
7261 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7262 NULL);
7263 if (lck == NULL) {
7264 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7265 "lock for file %s\n", fsp_str_dbg(fsp)));
7266 close_file(req, fsp, NORMAL_CLOSE);
7267 return NT_STATUS_INVALID_PARAMETER;
7271 * See if others still have the file open. If this is the case, then
7272 * don't delete. If all opens are POSIX delete we can set the delete
7273 * on close disposition.
7275 for (i=0; i<lck->num_share_modes; i++) {
7276 struct share_mode_entry *e = &lck->share_modes[i];
7277 if (is_valid_share_mode_entry(e)) {
7278 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7279 continue;
7281 /* Fail with sharing violation. */
7282 close_file(req, fsp, NORMAL_CLOSE);
7283 TALLOC_FREE(lck);
7284 return NT_STATUS_SHARING_VIOLATION;
7289 * Set the delete on close.
7291 status = smb_set_file_disposition_info(conn,
7292 &del,
7294 fsp,
7295 smb_fname);
7297 if (!NT_STATUS_IS_OK(status)) {
7298 close_file(req, fsp, NORMAL_CLOSE);
7299 TALLOC_FREE(lck);
7300 return status;
7302 TALLOC_FREE(lck);
7303 return close_file(req, fsp, NORMAL_CLOSE);
7306 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7307 struct smb_request *req,
7308 TALLOC_CTX *mem_ctx,
7309 uint16_t info_level,
7310 files_struct *fsp,
7311 struct smb_filename *smb_fname,
7312 char **ppdata, int total_data,
7313 int *ret_data_size)
7315 char *pdata = *ppdata;
7316 NTSTATUS status = NT_STATUS_OK;
7317 int data_return_size = 0;
7319 *ret_data_size = 0;
7321 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7322 return NT_STATUS_INVALID_LEVEL;
7325 if (!CAN_WRITE(conn)) {
7326 /* Allow POSIX opens. The open path will deny
7327 * any non-readonly opens. */
7328 if (info_level != SMB_POSIX_PATH_OPEN) {
7329 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7333 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7334 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7335 fsp ? fsp->fnum : -1, info_level, total_data));
7337 switch (info_level) {
7339 case SMB_INFO_STANDARD:
7341 status = smb_set_info_standard(conn,
7342 pdata,
7343 total_data,
7344 fsp,
7345 smb_fname);
7346 break;
7349 case SMB_INFO_SET_EA:
7351 status = smb_info_set_ea(conn,
7352 pdata,
7353 total_data,
7354 fsp,
7355 smb_fname);
7356 break;
7359 case SMB_SET_FILE_BASIC_INFO:
7360 case SMB_FILE_BASIC_INFORMATION:
7362 status = smb_set_file_basic_info(conn,
7363 pdata,
7364 total_data,
7365 fsp,
7366 smb_fname);
7367 break;
7370 case SMB_FILE_ALLOCATION_INFORMATION:
7371 case SMB_SET_FILE_ALLOCATION_INFO:
7373 status = smb_set_file_allocation_info(conn, req,
7374 pdata,
7375 total_data,
7376 fsp,
7377 smb_fname);
7378 break;
7381 case SMB_FILE_END_OF_FILE_INFORMATION:
7382 case SMB_SET_FILE_END_OF_FILE_INFO:
7384 status = smb_set_file_end_of_file_info(conn, req,
7385 pdata,
7386 total_data,
7387 fsp,
7388 smb_fname);
7389 break;
7392 case SMB_FILE_DISPOSITION_INFORMATION:
7393 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7395 #if 0
7396 /* JRA - We used to just ignore this on a path ?
7397 * Shouldn't this be invalid level on a pathname
7398 * based call ?
7400 if (tran_call != TRANSACT2_SETFILEINFO) {
7401 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7403 #endif
7404 status = smb_set_file_disposition_info(conn,
7405 pdata,
7406 total_data,
7407 fsp,
7408 smb_fname);
7409 break;
7412 case SMB_FILE_POSITION_INFORMATION:
7414 status = smb_file_position_information(conn,
7415 pdata,
7416 total_data,
7417 fsp);
7418 break;
7421 case SMB_FILE_FULL_EA_INFORMATION:
7423 status = smb_set_file_full_ea_info(conn,
7424 pdata,
7425 total_data,
7426 fsp);
7427 break;
7430 /* From tridge Samba4 :
7431 * MODE_INFORMATION in setfileinfo (I have no
7432 * idea what "mode information" on a file is - it takes a value of 0,
7433 * 2, 4 or 6. What could it be?).
7436 case SMB_FILE_MODE_INFORMATION:
7438 status = smb_file_mode_information(conn,
7439 pdata,
7440 total_data);
7441 break;
7445 * CIFS UNIX extensions.
7448 case SMB_SET_FILE_UNIX_BASIC:
7450 status = smb_set_file_unix_basic(conn, req,
7451 pdata,
7452 total_data,
7453 fsp,
7454 smb_fname);
7455 break;
7458 case SMB_SET_FILE_UNIX_INFO2:
7460 status = smb_set_file_unix_info2(conn, req,
7461 pdata,
7462 total_data,
7463 fsp,
7464 smb_fname);
7465 break;
7468 case SMB_SET_FILE_UNIX_LINK:
7470 if (fsp) {
7471 /* We must have a pathname for this. */
7472 return NT_STATUS_INVALID_LEVEL;
7474 status = smb_set_file_unix_link(conn, req, pdata,
7475 total_data, smb_fname);
7476 break;
7479 case SMB_SET_FILE_UNIX_HLINK:
7481 if (fsp) {
7482 /* We must have a pathname for this. */
7483 return NT_STATUS_INVALID_LEVEL;
7485 status = smb_set_file_unix_hlink(conn, req,
7486 pdata, total_data,
7487 smb_fname);
7488 break;
7491 case SMB_FILE_RENAME_INFORMATION:
7493 status = smb_file_rename_information(conn, req,
7494 pdata, total_data,
7495 fsp, smb_fname);
7496 break;
7499 #if defined(HAVE_POSIX_ACLS)
7500 case SMB_SET_POSIX_ACL:
7502 status = smb_set_posix_acl(conn,
7503 pdata,
7504 total_data,
7505 fsp,
7506 smb_fname);
7507 break;
7509 #endif
7511 case SMB_SET_POSIX_LOCK:
7513 if (!fsp) {
7514 return NT_STATUS_INVALID_LEVEL;
7516 status = smb_set_posix_lock(conn, req,
7517 pdata, total_data, fsp);
7518 break;
7521 case SMB_POSIX_PATH_OPEN:
7523 if (fsp) {
7524 /* We must have a pathname for this. */
7525 return NT_STATUS_INVALID_LEVEL;
7528 status = smb_posix_open(conn, req,
7529 ppdata,
7530 total_data,
7531 smb_fname,
7532 &data_return_size);
7533 break;
7536 case SMB_POSIX_PATH_UNLINK:
7538 if (fsp) {
7539 /* We must have a pathname for this. */
7540 return NT_STATUS_INVALID_LEVEL;
7543 status = smb_posix_unlink(conn, req,
7544 pdata,
7545 total_data,
7546 smb_fname);
7547 break;
7550 default:
7551 return NT_STATUS_INVALID_LEVEL;
7554 if (!NT_STATUS_IS_OK(status)) {
7555 return status;
7558 *ret_data_size = data_return_size;
7559 return NT_STATUS_OK;
7562 /****************************************************************************
7563 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7564 ****************************************************************************/
7566 static void call_trans2setfilepathinfo(connection_struct *conn,
7567 struct smb_request *req,
7568 unsigned int tran_call,
7569 char **pparams, int total_params,
7570 char **ppdata, int total_data,
7571 unsigned int max_data_bytes)
7573 char *params = *pparams;
7574 char *pdata = *ppdata;
7575 uint16 info_level;
7576 struct smb_filename *smb_fname = NULL;
7577 files_struct *fsp = NULL;
7578 NTSTATUS status = NT_STATUS_OK;
7579 int data_return_size = 0;
7581 if (!params) {
7582 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7583 return;
7586 if (tran_call == TRANSACT2_SETFILEINFO) {
7587 if (total_params < 4) {
7588 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7589 return;
7592 fsp = file_fsp(req, SVAL(params,0));
7593 /* Basic check for non-null fsp. */
7594 if (!check_fsp_open(conn, req, fsp)) {
7595 return;
7597 info_level = SVAL(params,2);
7599 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7600 &smb_fname);
7601 if (!NT_STATUS_IS_OK(status)) {
7602 reply_nterror(req, status);
7603 return;
7606 if(fsp->is_directory || fsp->fh->fd == -1) {
7608 * This is actually a SETFILEINFO on a directory
7609 * handle (returned from an NT SMB). NT5.0 seems
7610 * to do this call. JRA.
7612 if (INFO_LEVEL_IS_UNIX(info_level)) {
7613 /* Always do lstat for UNIX calls. */
7614 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7615 DEBUG(3,("call_trans2setfilepathinfo: "
7616 "SMB_VFS_LSTAT of %s failed "
7617 "(%s)\n",
7618 smb_fname_str_dbg(smb_fname),
7619 strerror(errno)));
7620 reply_nterror(req, map_nt_error_from_unix(errno));
7621 return;
7623 } else {
7624 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7625 DEBUG(3,("call_trans2setfilepathinfo: "
7626 "fileinfo of %s failed (%s)\n",
7627 smb_fname_str_dbg(smb_fname),
7628 strerror(errno)));
7629 reply_nterror(req, map_nt_error_from_unix(errno));
7630 return;
7633 } else if (fsp->print_file) {
7635 * Doing a DELETE_ON_CLOSE should cancel a print job.
7637 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7638 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7640 DEBUG(3,("call_trans2setfilepathinfo: "
7641 "Cancelling print job (%s)\n",
7642 fsp_str_dbg(fsp)));
7644 SSVAL(params,0,0);
7645 send_trans2_replies(conn, req, params, 2,
7646 *ppdata, 0,
7647 max_data_bytes);
7648 return;
7649 } else {
7650 reply_doserror(req, ERRDOS, ERRbadpath);
7651 return;
7653 } else {
7655 * Original code - this is an open file.
7657 if (!check_fsp(conn, req, fsp)) {
7658 return;
7661 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7662 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7663 "of fnum %d failed (%s)\n", fsp->fnum,
7664 strerror(errno)));
7665 reply_nterror(req, map_nt_error_from_unix(errno));
7666 return;
7669 } else {
7670 char *fname = NULL;
7672 /* set path info */
7673 if (total_params < 7) {
7674 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7675 return;
7678 info_level = SVAL(params,0);
7679 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7680 total_params - 6, STR_TERMINATE,
7681 &status);
7682 if (!NT_STATUS_IS_OK(status)) {
7683 reply_nterror(req, status);
7684 return;
7687 status = filename_convert(req, conn,
7688 req->flags2 & FLAGS2_DFS_PATHNAMES,
7689 fname,
7691 NULL,
7692 &smb_fname);
7693 if (!NT_STATUS_IS_OK(status)) {
7694 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7695 reply_botherror(req,
7696 NT_STATUS_PATH_NOT_COVERED,
7697 ERRSRV, ERRbadpath);
7698 return;
7700 reply_nterror(req, status);
7701 return;
7704 if (INFO_LEVEL_IS_UNIX(info_level)) {
7706 * For CIFS UNIX extensions the target name may not exist.
7709 /* Always do lstat for UNIX calls. */
7710 SMB_VFS_LSTAT(conn, smb_fname);
7712 } else if (!VALID_STAT(smb_fname->st) &&
7713 SMB_VFS_STAT(conn, smb_fname)) {
7714 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7715 "%s failed (%s)\n",
7716 smb_fname_str_dbg(smb_fname),
7717 strerror(errno)));
7718 reply_nterror(req, map_nt_error_from_unix(errno));
7719 return;
7723 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7724 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7725 fsp ? fsp->fnum : -1, info_level,total_data));
7727 /* Realloc the parameter size */
7728 *pparams = (char *)SMB_REALLOC(*pparams,2);
7729 if (*pparams == NULL) {
7730 reply_nterror(req, NT_STATUS_NO_MEMORY);
7731 return;
7733 params = *pparams;
7735 SSVAL(params,0,0);
7737 status = smbd_do_setfilepathinfo(conn, req, req,
7738 info_level,
7739 fsp,
7740 smb_fname,
7741 ppdata, total_data,
7742 &data_return_size);
7743 if (!NT_STATUS_IS_OK(status)) {
7744 if (open_was_deferred(req->mid)) {
7745 /* We have re-scheduled this call. */
7746 return;
7748 if (blocking_lock_was_deferred(req->mid)) {
7749 /* We have re-scheduled this call. */
7750 return;
7752 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7753 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7754 ERRSRV, ERRbadpath);
7755 return;
7757 if (info_level == SMB_POSIX_PATH_OPEN) {
7758 reply_openerror(req, status);
7759 return;
7762 reply_nterror(req, status);
7763 return;
7766 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7767 max_data_bytes);
7769 return;
7772 /****************************************************************************
7773 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7774 ****************************************************************************/
7776 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7777 char **pparams, int total_params,
7778 char **ppdata, int total_data,
7779 unsigned int max_data_bytes)
7781 struct smb_filename *smb_dname = NULL;
7782 char *params = *pparams;
7783 char *pdata = *ppdata;
7784 char *directory = NULL;
7785 NTSTATUS status = NT_STATUS_OK;
7786 struct ea_list *ea_list = NULL;
7787 TALLOC_CTX *ctx = talloc_tos();
7789 if (!CAN_WRITE(conn)) {
7790 reply_doserror(req, ERRSRV, ERRaccess);
7791 return;
7794 if (total_params < 5) {
7795 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7796 return;
7799 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7800 total_params - 4, STR_TERMINATE,
7801 &status);
7802 if (!NT_STATUS_IS_OK(status)) {
7803 reply_nterror(req, status);
7804 return;
7807 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7809 status = filename_convert(ctx,
7810 conn,
7811 req->flags2 & FLAGS2_DFS_PATHNAMES,
7812 directory,
7814 NULL,
7815 &smb_dname);
7817 if (!NT_STATUS_IS_OK(status)) {
7818 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7819 reply_botherror(req,
7820 NT_STATUS_PATH_NOT_COVERED,
7821 ERRSRV, ERRbadpath);
7822 return;
7824 reply_nterror(req, status);
7825 return;
7828 /* Any data in this call is an EA list. */
7829 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7830 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7831 goto out;
7835 * OS/2 workplace shell seems to send SET_EA requests of "null"
7836 * length (4 bytes containing IVAL 4).
7837 * They seem to have no effect. Bug #3212. JRA.
7840 if (total_data != 4) {
7841 if (total_data < 10) {
7842 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7843 goto out;
7846 if (IVAL(pdata,0) > total_data) {
7847 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7848 IVAL(pdata,0), (unsigned int)total_data));
7849 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7850 goto out;
7853 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7854 total_data - 4);
7855 if (!ea_list) {
7856 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7857 goto out;
7860 /* If total_data == 4 Windows doesn't care what values
7861 * are placed in that field, it just ignores them.
7862 * The System i QNTC IBM SMB client puts bad values here,
7863 * so ignore them. */
7865 status = create_directory(conn, req, smb_dname);
7867 if (!NT_STATUS_IS_OK(status)) {
7868 reply_nterror(req, status);
7869 goto out;
7872 /* Try and set any given EA. */
7873 if (ea_list) {
7874 status = set_ea(conn, NULL, smb_dname, ea_list);
7875 if (!NT_STATUS_IS_OK(status)) {
7876 reply_nterror(req, status);
7877 goto out;
7881 /* Realloc the parameter and data sizes */
7882 *pparams = (char *)SMB_REALLOC(*pparams,2);
7883 if(*pparams == NULL) {
7884 reply_nterror(req, NT_STATUS_NO_MEMORY);
7885 goto out;
7887 params = *pparams;
7889 SSVAL(params,0,0);
7891 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7893 out:
7894 TALLOC_FREE(smb_dname);
7895 return;
7898 /****************************************************************************
7899 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7900 We don't actually do this - we just send a null response.
7901 ****************************************************************************/
7903 static void call_trans2findnotifyfirst(connection_struct *conn,
7904 struct smb_request *req,
7905 char **pparams, int total_params,
7906 char **ppdata, int total_data,
7907 unsigned int max_data_bytes)
7909 char *params = *pparams;
7910 uint16 info_level;
7912 if (total_params < 6) {
7913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7914 return;
7917 info_level = SVAL(params,4);
7918 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7920 switch (info_level) {
7921 case 1:
7922 case 2:
7923 break;
7924 default:
7925 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7926 return;
7929 /* Realloc the parameter and data sizes */
7930 *pparams = (char *)SMB_REALLOC(*pparams,6);
7931 if (*pparams == NULL) {
7932 reply_nterror(req, NT_STATUS_NO_MEMORY);
7933 return;
7935 params = *pparams;
7937 SSVAL(params,0,fnf_handle);
7938 SSVAL(params,2,0); /* No changes */
7939 SSVAL(params,4,0); /* No EA errors */
7941 fnf_handle++;
7943 if(fnf_handle == 0)
7944 fnf_handle = 257;
7946 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7948 return;
7951 /****************************************************************************
7952 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7953 changes). Currently this does nothing.
7954 ****************************************************************************/
7956 static void call_trans2findnotifynext(connection_struct *conn,
7957 struct smb_request *req,
7958 char **pparams, int total_params,
7959 char **ppdata, int total_data,
7960 unsigned int max_data_bytes)
7962 char *params = *pparams;
7964 DEBUG(3,("call_trans2findnotifynext\n"));
7966 /* Realloc the parameter and data sizes */
7967 *pparams = (char *)SMB_REALLOC(*pparams,4);
7968 if (*pparams == NULL) {
7969 reply_nterror(req, NT_STATUS_NO_MEMORY);
7970 return;
7972 params = *pparams;
7974 SSVAL(params,0,0); /* No changes */
7975 SSVAL(params,2,0); /* No EA errors */
7977 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7979 return;
7982 /****************************************************************************
7983 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7984 ****************************************************************************/
7986 static void call_trans2getdfsreferral(connection_struct *conn,
7987 struct smb_request *req,
7988 char **pparams, int total_params,
7989 char **ppdata, int total_data,
7990 unsigned int max_data_bytes)
7992 char *params = *pparams;
7993 char *pathname = NULL;
7994 int reply_size = 0;
7995 int max_referral_level;
7996 NTSTATUS status = NT_STATUS_OK;
7997 TALLOC_CTX *ctx = talloc_tos();
7999 DEBUG(10,("call_trans2getdfsreferral\n"));
8001 if (total_params < 3) {
8002 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8003 return;
8006 max_referral_level = SVAL(params,0);
8008 if(!lp_host_msdfs()) {
8009 reply_doserror(req, ERRDOS, ERRbadfunc);
8010 return;
8013 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8014 total_params - 2, STR_TERMINATE);
8015 if (!pathname) {
8016 reply_nterror(req, NT_STATUS_NOT_FOUND);
8017 return;
8019 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8020 ppdata,&status)) < 0) {
8021 reply_nterror(req, status);
8022 return;
8025 SSVAL(req->inbuf, smb_flg2,
8026 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8027 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8029 return;
8032 #define LMCAT_SPL 0x53
8033 #define LMFUNC_GETJOBID 0x60
8035 /****************************************************************************
8036 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8037 ****************************************************************************/
8039 static void call_trans2ioctl(connection_struct *conn,
8040 struct smb_request *req,
8041 char **pparams, int total_params,
8042 char **ppdata, int total_data,
8043 unsigned int max_data_bytes)
8045 char *pdata = *ppdata;
8046 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8048 /* check for an invalid fid before proceeding */
8050 if (!fsp) {
8051 reply_doserror(req, ERRDOS, ERRbadfid);
8052 return;
8055 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8056 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8057 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8058 if (*ppdata == NULL) {
8059 reply_nterror(req, NT_STATUS_NO_MEMORY);
8060 return;
8062 pdata = *ppdata;
8064 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8065 CAN ACCEPT THIS IN UNICODE. JRA. */
8067 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8068 srvstr_push(pdata, req->flags2, pdata + 2,
8069 global_myname(), 15,
8070 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8071 srvstr_push(pdata, req->flags2, pdata+18,
8072 lp_servicename(SNUM(conn)), 13,
8073 STR_ASCII|STR_TERMINATE); /* Service name */
8074 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8075 max_data_bytes);
8076 return;
8079 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8080 reply_doserror(req, ERRSRV, ERRerror);
8083 /****************************************************************************
8084 Reply to a SMBfindclose (stop trans2 directory search).
8085 ****************************************************************************/
8087 void reply_findclose(struct smb_request *req)
8089 int dptr_num;
8090 struct smbd_server_connection *sconn = smbd_server_conn;
8092 START_PROFILE(SMBfindclose);
8094 if (req->wct < 1) {
8095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8096 END_PROFILE(SMBfindclose);
8097 return;
8100 dptr_num = SVALS(req->vwv+0, 0);
8102 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8104 dptr_close(sconn, &dptr_num);
8106 reply_outbuf(req, 0, 0);
8108 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8110 END_PROFILE(SMBfindclose);
8111 return;
8114 /****************************************************************************
8115 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8116 ****************************************************************************/
8118 void reply_findnclose(struct smb_request *req)
8120 int dptr_num;
8122 START_PROFILE(SMBfindnclose);
8124 if (req->wct < 1) {
8125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8126 END_PROFILE(SMBfindnclose);
8127 return;
8130 dptr_num = SVAL(req->vwv+0, 0);
8132 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8134 /* We never give out valid handles for a
8135 findnotifyfirst - so any dptr_num is ok here.
8136 Just ignore it. */
8138 reply_outbuf(req, 0, 0);
8140 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8142 END_PROFILE(SMBfindnclose);
8143 return;
8146 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8147 struct trans_state *state)
8149 if (get_Protocol() >= PROTOCOL_NT1) {
8150 req->flags2 |= 0x40; /* IS_LONG_NAME */
8151 SSVAL(req->inbuf,smb_flg2,req->flags2);
8154 if (conn->encrypt_level == Required && !req->encrypted) {
8155 if (state->call != TRANSACT2_QFSINFO &&
8156 state->call != TRANSACT2_SETFSINFO) {
8157 DEBUG(0,("handle_trans2: encryption required "
8158 "with call 0x%x\n",
8159 (unsigned int)state->call));
8160 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8161 return;
8165 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8167 /* Now we must call the relevant TRANS2 function */
8168 switch(state->call) {
8169 case TRANSACT2_OPEN:
8171 START_PROFILE(Trans2_open);
8172 call_trans2open(conn, req,
8173 &state->param, state->total_param,
8174 &state->data, state->total_data,
8175 state->max_data_return);
8176 END_PROFILE(Trans2_open);
8177 break;
8180 case TRANSACT2_FINDFIRST:
8182 START_PROFILE(Trans2_findfirst);
8183 call_trans2findfirst(conn, req,
8184 &state->param, state->total_param,
8185 &state->data, state->total_data,
8186 state->max_data_return);
8187 END_PROFILE(Trans2_findfirst);
8188 break;
8191 case TRANSACT2_FINDNEXT:
8193 START_PROFILE(Trans2_findnext);
8194 call_trans2findnext(conn, req,
8195 &state->param, state->total_param,
8196 &state->data, state->total_data,
8197 state->max_data_return);
8198 END_PROFILE(Trans2_findnext);
8199 break;
8202 case TRANSACT2_QFSINFO:
8204 START_PROFILE(Trans2_qfsinfo);
8205 call_trans2qfsinfo(conn, req,
8206 &state->param, state->total_param,
8207 &state->data, state->total_data,
8208 state->max_data_return);
8209 END_PROFILE(Trans2_qfsinfo);
8210 break;
8213 case TRANSACT2_SETFSINFO:
8215 START_PROFILE(Trans2_setfsinfo);
8216 call_trans2setfsinfo(conn, req,
8217 &state->param, state->total_param,
8218 &state->data, state->total_data,
8219 state->max_data_return);
8220 END_PROFILE(Trans2_setfsinfo);
8221 break;
8224 case TRANSACT2_QPATHINFO:
8225 case TRANSACT2_QFILEINFO:
8227 START_PROFILE(Trans2_qpathinfo);
8228 call_trans2qfilepathinfo(conn, req, state->call,
8229 &state->param, state->total_param,
8230 &state->data, state->total_data,
8231 state->max_data_return);
8232 END_PROFILE(Trans2_qpathinfo);
8233 break;
8236 case TRANSACT2_SETPATHINFO:
8237 case TRANSACT2_SETFILEINFO:
8239 START_PROFILE(Trans2_setpathinfo);
8240 call_trans2setfilepathinfo(conn, req, state->call,
8241 &state->param, state->total_param,
8242 &state->data, state->total_data,
8243 state->max_data_return);
8244 END_PROFILE(Trans2_setpathinfo);
8245 break;
8248 case TRANSACT2_FINDNOTIFYFIRST:
8250 START_PROFILE(Trans2_findnotifyfirst);
8251 call_trans2findnotifyfirst(conn, req,
8252 &state->param, state->total_param,
8253 &state->data, state->total_data,
8254 state->max_data_return);
8255 END_PROFILE(Trans2_findnotifyfirst);
8256 break;
8259 case TRANSACT2_FINDNOTIFYNEXT:
8261 START_PROFILE(Trans2_findnotifynext);
8262 call_trans2findnotifynext(conn, req,
8263 &state->param, state->total_param,
8264 &state->data, state->total_data,
8265 state->max_data_return);
8266 END_PROFILE(Trans2_findnotifynext);
8267 break;
8270 case TRANSACT2_MKDIR:
8272 START_PROFILE(Trans2_mkdir);
8273 call_trans2mkdir(conn, req,
8274 &state->param, state->total_param,
8275 &state->data, state->total_data,
8276 state->max_data_return);
8277 END_PROFILE(Trans2_mkdir);
8278 break;
8281 case TRANSACT2_GET_DFS_REFERRAL:
8283 START_PROFILE(Trans2_get_dfs_referral);
8284 call_trans2getdfsreferral(conn, req,
8285 &state->param, state->total_param,
8286 &state->data, state->total_data,
8287 state->max_data_return);
8288 END_PROFILE(Trans2_get_dfs_referral);
8289 break;
8292 case TRANSACT2_IOCTL:
8294 START_PROFILE(Trans2_ioctl);
8295 call_trans2ioctl(conn, req,
8296 &state->param, state->total_param,
8297 &state->data, state->total_data,
8298 state->max_data_return);
8299 END_PROFILE(Trans2_ioctl);
8300 break;
8303 default:
8304 /* Error in request */
8305 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8306 reply_doserror(req, ERRSRV,ERRerror);
8310 /****************************************************************************
8311 Reply to a SMBtrans2.
8312 ****************************************************************************/
8314 void reply_trans2(struct smb_request *req)
8316 connection_struct *conn = req->conn;
8317 unsigned int dsoff;
8318 unsigned int dscnt;
8319 unsigned int psoff;
8320 unsigned int pscnt;
8321 unsigned int tran_call;
8322 struct trans_state *state;
8323 NTSTATUS result;
8325 START_PROFILE(SMBtrans2);
8327 if (req->wct < 14) {
8328 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8329 END_PROFILE(SMBtrans2);
8330 return;
8333 dsoff = SVAL(req->vwv+12, 0);
8334 dscnt = SVAL(req->vwv+11, 0);
8335 psoff = SVAL(req->vwv+10, 0);
8336 pscnt = SVAL(req->vwv+9, 0);
8337 tran_call = SVAL(req->vwv+14, 0);
8339 result = allow_new_trans(conn->pending_trans, req->mid);
8340 if (!NT_STATUS_IS_OK(result)) {
8341 DEBUG(2, ("Got invalid trans2 request: %s\n",
8342 nt_errstr(result)));
8343 reply_nterror(req, result);
8344 END_PROFILE(SMBtrans2);
8345 return;
8348 if (IS_IPC(conn)) {
8349 switch (tran_call) {
8350 /* List the allowed trans2 calls on IPC$ */
8351 case TRANSACT2_OPEN:
8352 case TRANSACT2_GET_DFS_REFERRAL:
8353 case TRANSACT2_QFILEINFO:
8354 case TRANSACT2_QFSINFO:
8355 case TRANSACT2_SETFSINFO:
8356 break;
8357 default:
8358 reply_doserror(req, ERRSRV, ERRaccess);
8359 END_PROFILE(SMBtrans2);
8360 return;
8364 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8365 DEBUG(0, ("talloc failed\n"));
8366 reply_nterror(req, NT_STATUS_NO_MEMORY);
8367 END_PROFILE(SMBtrans2);
8368 return;
8371 state->cmd = SMBtrans2;
8373 state->mid = req->mid;
8374 state->vuid = req->vuid;
8375 state->setup_count = SVAL(req->vwv+13, 0);
8376 state->setup = NULL;
8377 state->total_param = SVAL(req->vwv+0, 0);
8378 state->param = NULL;
8379 state->total_data = SVAL(req->vwv+1, 0);
8380 state->data = NULL;
8381 state->max_param_return = SVAL(req->vwv+2, 0);
8382 state->max_data_return = SVAL(req->vwv+3, 0);
8383 state->max_setup_return = SVAL(req->vwv+4, 0);
8384 state->close_on_completion = BITSETW(req->vwv+5, 0);
8385 state->one_way = BITSETW(req->vwv+5, 1);
8387 state->call = tran_call;
8389 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8390 is so as a sanity check */
8391 if (state->setup_count != 1) {
8393 * Need to have rc=0 for ioctl to get job id for OS/2.
8394 * Network printing will fail if function is not successful.
8395 * Similar function in reply.c will be used if protocol
8396 * is LANMAN1.0 instead of LM1.2X002.
8397 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8398 * outbuf doesn't have to be set(only job id is used).
8400 if ( (state->setup_count == 4)
8401 && (tran_call == TRANSACT2_IOCTL)
8402 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8403 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8404 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8405 } else {
8406 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8407 DEBUG(2,("Transaction is %d\n",tran_call));
8408 TALLOC_FREE(state);
8409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8410 END_PROFILE(SMBtrans2);
8411 return;
8415 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8416 goto bad_param;
8418 if (state->total_data) {
8420 if (trans_oob(state->total_data, 0, dscnt)
8421 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8422 goto bad_param;
8425 /* Can't use talloc here, the core routines do realloc on the
8426 * params and data. */
8427 state->data = (char *)SMB_MALLOC(state->total_data);
8428 if (state->data == NULL) {
8429 DEBUG(0,("reply_trans2: data malloc fail for %u "
8430 "bytes !\n", (unsigned int)state->total_data));
8431 TALLOC_FREE(state);
8432 reply_nterror(req, NT_STATUS_NO_MEMORY);
8433 END_PROFILE(SMBtrans2);
8434 return;
8437 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8440 if (state->total_param) {
8442 if (trans_oob(state->total_param, 0, pscnt)
8443 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8444 goto bad_param;
8447 /* Can't use talloc here, the core routines do realloc on the
8448 * params and data. */
8449 state->param = (char *)SMB_MALLOC(state->total_param);
8450 if (state->param == NULL) {
8451 DEBUG(0,("reply_trans: param malloc fail for %u "
8452 "bytes !\n", (unsigned int)state->total_param));
8453 SAFE_FREE(state->data);
8454 TALLOC_FREE(state);
8455 reply_nterror(req, NT_STATUS_NO_MEMORY);
8456 END_PROFILE(SMBtrans2);
8457 return;
8460 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8463 state->received_data = dscnt;
8464 state->received_param = pscnt;
8466 if ((state->received_param == state->total_param) &&
8467 (state->received_data == state->total_data)) {
8469 handle_trans2(conn, req, state);
8471 SAFE_FREE(state->data);
8472 SAFE_FREE(state->param);
8473 TALLOC_FREE(state);
8474 END_PROFILE(SMBtrans2);
8475 return;
8478 DLIST_ADD(conn->pending_trans, state);
8480 /* We need to send an interim response then receive the rest
8481 of the parameter/data bytes */
8482 reply_outbuf(req, 0, 0);
8483 show_msg((char *)req->outbuf);
8484 END_PROFILE(SMBtrans2);
8485 return;
8487 bad_param:
8489 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8490 SAFE_FREE(state->data);
8491 SAFE_FREE(state->param);
8492 TALLOC_FREE(state);
8493 END_PROFILE(SMBtrans2);
8494 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8498 /****************************************************************************
8499 Reply to a SMBtranss2
8500 ****************************************************************************/
8502 void reply_transs2(struct smb_request *req)
8504 connection_struct *conn = req->conn;
8505 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8506 struct trans_state *state;
8508 START_PROFILE(SMBtranss2);
8510 show_msg((char *)req->inbuf);
8512 if (req->wct < 8) {
8513 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8514 END_PROFILE(SMBtranss2);
8515 return;
8518 for (state = conn->pending_trans; state != NULL;
8519 state = state->next) {
8520 if (state->mid == req->mid) {
8521 break;
8525 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8526 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8527 END_PROFILE(SMBtranss2);
8528 return;
8531 /* Revise state->total_param and state->total_data in case they have
8532 changed downwards */
8534 if (SVAL(req->vwv+0, 0) < state->total_param)
8535 state->total_param = SVAL(req->vwv+0, 0);
8536 if (SVAL(req->vwv+1, 0) < state->total_data)
8537 state->total_data = SVAL(req->vwv+1, 0);
8539 pcnt = SVAL(req->vwv+2, 0);
8540 poff = SVAL(req->vwv+3, 0);
8541 pdisp = SVAL(req->vwv+4, 0);
8543 dcnt = SVAL(req->vwv+5, 0);
8544 doff = SVAL(req->vwv+6, 0);
8545 ddisp = SVAL(req->vwv+7, 0);
8547 state->received_param += pcnt;
8548 state->received_data += dcnt;
8550 if ((state->received_data > state->total_data) ||
8551 (state->received_param > state->total_param))
8552 goto bad_param;
8554 if (pcnt) {
8555 if (trans_oob(state->total_param, pdisp, pcnt)
8556 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8557 goto bad_param;
8559 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8562 if (dcnt) {
8563 if (trans_oob(state->total_data, ddisp, dcnt)
8564 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8565 goto bad_param;
8567 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8570 if ((state->received_param < state->total_param) ||
8571 (state->received_data < state->total_data)) {
8572 END_PROFILE(SMBtranss2);
8573 return;
8576 handle_trans2(conn, req, state);
8578 DLIST_REMOVE(conn->pending_trans, state);
8579 SAFE_FREE(state->data);
8580 SAFE_FREE(state->param);
8581 TALLOC_FREE(state);
8583 END_PROFILE(SMBtranss2);
8584 return;
8586 bad_param:
8588 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8589 DLIST_REMOVE(conn->pending_trans, state);
8590 SAFE_FREE(state->data);
8591 SAFE_FREE(state->param);
8592 TALLOC_FREE(state);
8593 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8594 END_PROFILE(SMBtranss2);
8595 return;