Fix debug statements to use correct function name.
[Samba/fernandojvsilva.git] / source3 / smbd / trans2.c
blob445817ff11cfae66c7831fa18f70f1fa711e2182
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 extern enum protocol_types Protocol;
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
36 char *pdata,
37 files_struct *fsp,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
41 char *pdata,
42 files_struct *fsp,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
59 return val;
62 /****************************************************************************
63 Utility functions for dealing with extended attributes.
64 ****************************************************************************/
66 /****************************************************************************
67 Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
70 static bool samba_private_attr_name(const char *unix_ea_name)
72 static const char * const prohibited_ea_names[] = {
73 SAMBA_POSIX_INHERITANCE_EA_NAME,
74 SAMBA_XATTR_DOS_ATTRIB,
75 SAMBA_XATTR_DOSTIMESTAMPS,
76 SAMBA_XATTR_MARKER,
77 NULL
80 int i;
82 for (i = 0; prohibited_ea_names[i]; i++) {
83 if (strequal( prohibited_ea_names[i], unix_ea_name))
84 return true;
86 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
87 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
88 return true;
90 return false;
93 /****************************************************************************
94 Get one EA value. Fill in a struct ea_struct.
95 ****************************************************************************/
97 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
98 files_struct *fsp, const char *fname,
99 const char *ea_name, struct ea_struct *pea)
101 /* Get the value of this xattr. Max size is 64k. */
102 size_t attr_size = 256;
103 char *val = NULL;
104 ssize_t sizeret;
106 again:
108 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
109 if (!val) {
110 return NT_STATUS_NO_MEMORY;
113 if (fsp && fsp->fh->fd != -1) {
114 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
115 } else {
116 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
119 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
120 attr_size = 65536;
121 goto again;
124 if (sizeret == -1) {
125 return map_nt_error_from_unix(errno);
128 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
129 dump_data(10, (uint8 *)val, sizeret);
131 pea->flags = 0;
132 if (strnequal(ea_name, "user.", 5)) {
133 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
134 } else {
135 pea->name = talloc_strdup(mem_ctx, ea_name);
137 if (pea->name == NULL) {
138 TALLOC_FREE(val);
139 return NT_STATUS_NO_MEMORY;
141 pea->value.data = (unsigned char *)val;
142 pea->value.length = (size_t)sizeret;
143 return NT_STATUS_OK;
146 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
147 files_struct *fsp, const char *fname,
148 char ***pnames, size_t *pnum_names)
150 /* Get a list of all xattrs. Max namesize is 64k. */
151 size_t ea_namelist_size = 1024;
152 char *ea_namelist = NULL;
154 char *p;
155 char **names, **tmp;
156 size_t num_names;
157 ssize_t sizeret = -1;
159 if (!lp_ea_support(SNUM(conn))) {
160 if (pnames) {
161 *pnames = NULL;
163 *pnum_names = 0;
164 return NT_STATUS_OK;
168 * TALLOC the result early to get the talloc hierarchy right.
171 names = TALLOC_ARRAY(mem_ctx, char *, 1);
172 if (names == NULL) {
173 DEBUG(0, ("talloc failed\n"));
174 return NT_STATUS_NO_MEMORY;
177 while (ea_namelist_size <= 65536) {
179 ea_namelist = TALLOC_REALLOC_ARRAY(
180 names, ea_namelist, char, ea_namelist_size);
181 if (ea_namelist == NULL) {
182 DEBUG(0, ("talloc failed\n"));
183 TALLOC_FREE(names);
184 return NT_STATUS_NO_MEMORY;
187 if (fsp && fsp->fh->fd != -1) {
188 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
189 ea_namelist_size);
190 } else {
191 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
192 ea_namelist_size);
195 if ((sizeret == -1) && (errno == ERANGE)) {
196 ea_namelist_size *= 2;
198 else {
199 break;
203 if (sizeret == -1) {
204 TALLOC_FREE(names);
205 return map_nt_error_from_unix(errno);
208 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
209 (unsigned int)sizeret));
211 if (sizeret == 0) {
212 TALLOC_FREE(names);
213 if (pnames) {
214 *pnames = NULL;
216 *pnum_names = 0;
217 return NT_STATUS_OK;
221 * Ensure the result is 0-terminated
224 if (ea_namelist[sizeret-1] != '\0') {
225 TALLOC_FREE(names);
226 return NT_STATUS_INTERNAL_ERROR;
230 * count the names
232 num_names = 0;
234 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
235 num_names += 1;
238 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
239 if (tmp == NULL) {
240 DEBUG(0, ("talloc failed\n"));
241 TALLOC_FREE(names);
242 return NT_STATUS_NO_MEMORY;
245 names = tmp;
246 num_names = 0;
248 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
249 names[num_names++] = p;
252 if (pnames) {
253 *pnames = names;
254 } else {
255 TALLOC_FREE(names);
257 *pnum_names = num_names;
258 return NT_STATUS_OK;
261 /****************************************************************************
262 Return a linked list of the total EA's. Plus the total size
263 ****************************************************************************/
265 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
266 const char *fname, size_t *pea_total_len)
268 /* Get a list of all xattrs. Max namesize is 64k. */
269 size_t i, num_names;
270 char **names;
271 struct ea_list *ea_list_head = NULL;
272 NTSTATUS status;
274 *pea_total_len = 0;
276 if (!lp_ea_support(SNUM(conn))) {
277 return NULL;
280 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
281 &names, &num_names);
283 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
284 return NULL;
287 for (i=0; i<num_names; i++) {
288 struct ea_list *listp;
289 fstring dos_ea_name;
291 if (strnequal(names[i], "system.", 7)
292 || samba_private_attr_name(names[i]))
293 continue;
295 listp = TALLOC_P(mem_ctx, struct ea_list);
296 if (listp == NULL) {
297 return NULL;
300 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
301 fname, names[i],
302 &listp->ea))) {
303 return NULL;
306 push_ascii_fstring(dos_ea_name, listp->ea.name);
308 *pea_total_len +=
309 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
311 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
312 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
313 (unsigned int)listp->ea.value.length));
315 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
319 /* Add on 4 for total length. */
320 if (*pea_total_len) {
321 *pea_total_len += 4;
324 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
325 (unsigned int)*pea_total_len));
327 return ea_list_head;
330 /****************************************************************************
331 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
332 that was filled.
333 ****************************************************************************/
335 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
336 connection_struct *conn, struct ea_list *ea_list)
338 unsigned int ret_data_size = 4;
339 char *p = pdata;
341 SMB_ASSERT(total_data_size >= 4);
343 if (!lp_ea_support(SNUM(conn))) {
344 SIVAL(pdata,4,0);
345 return 4;
348 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
349 size_t dos_namelen;
350 fstring dos_ea_name;
351 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
352 dos_namelen = strlen(dos_ea_name);
353 if (dos_namelen > 255 || dos_namelen == 0) {
354 break;
356 if (ea_list->ea.value.length > 65535) {
357 break;
359 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
360 break;
363 /* We know we have room. */
364 SCVAL(p,0,ea_list->ea.flags);
365 SCVAL(p,1,dos_namelen);
366 SSVAL(p,2,ea_list->ea.value.length);
367 fstrcpy(p+4, dos_ea_name);
368 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
370 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
371 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
374 ret_data_size = PTR_DIFF(p, pdata);
375 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
376 SIVAL(pdata,0,ret_data_size);
377 return ret_data_size;
380 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
381 char *pdata,
382 unsigned int total_data_size,
383 unsigned int *ret_data_size,
384 connection_struct *conn,
385 struct ea_list *ea_list)
387 uint8_t *p = (uint8_t *)pdata;
388 uint8_t *last_start = NULL;
390 *ret_data_size = 0;
392 if (!lp_ea_support(SNUM(conn))) {
393 return NT_STATUS_NO_EAS_ON_FILE;
396 for (; ea_list; ea_list = ea_list->next) {
397 size_t dos_namelen;
398 fstring dos_ea_name;
399 size_t this_size;
401 if (last_start) {
402 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
404 last_start = p;
406 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
407 dos_namelen = strlen(dos_ea_name);
408 if (dos_namelen > 255 || dos_namelen == 0) {
409 return NT_STATUS_INTERNAL_ERROR;
411 if (ea_list->ea.value.length > 65535) {
412 return NT_STATUS_INTERNAL_ERROR;
415 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
417 if (ea_list->next) {
418 size_t pad = 4 - (this_size % 4);
419 this_size += pad;
422 if (this_size > total_data_size) {
423 return NT_STATUS_INFO_LENGTH_MISMATCH;
426 /* We know we have room. */
427 SIVAL(p, 0x00, 0); /* next offset */
428 SCVAL(p, 0x04, ea_list->ea.flags);
429 SCVAL(p, 0x05, dos_namelen);
430 SSVAL(p, 0x06, ea_list->ea.value.length);
431 fstrcpy((char *)(p+0x08), dos_ea_name);
432 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
434 total_data_size -= this_size;
435 p += this_size;
438 *ret_data_size = PTR_DIFF(p, pdata);
439 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
440 return NT_STATUS_OK;
443 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
445 size_t total_ea_len = 0;
446 TALLOC_CTX *mem_ctx = NULL;
448 if (!lp_ea_support(SNUM(conn))) {
449 return 0;
451 mem_ctx = talloc_tos();
452 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
453 return total_ea_len;
456 /****************************************************************************
457 Ensure the EA name is case insensitive by matching any existing EA name.
458 ****************************************************************************/
460 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
462 size_t total_ea_len;
463 TALLOC_CTX *mem_ctx = talloc_tos();
464 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
466 for (; ea_list; ea_list = ea_list->next) {
467 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
468 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
469 &unix_ea_name[5], ea_list->ea.name));
470 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
471 break;
476 /****************************************************************************
477 Set or delete an extended attribute.
478 ****************************************************************************/
480 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
481 const struct smb_filename *smb_fname, struct ea_list *ea_list)
483 char *fname = NULL;
485 if (!lp_ea_support(SNUM(conn))) {
486 return NT_STATUS_EAS_NOT_SUPPORTED;
489 /* For now setting EAs on streams isn't supported. */
490 fname = smb_fname->base_name;
492 for (;ea_list; ea_list = ea_list->next) {
493 int ret;
494 fstring unix_ea_name;
496 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
497 fstrcat(unix_ea_name, ea_list->ea.name);
499 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
501 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
503 if (samba_private_attr_name(unix_ea_name)) {
504 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
505 return NT_STATUS_ACCESS_DENIED;
508 if (ea_list->ea.value.length == 0) {
509 /* Remove the attribute. */
510 if (fsp && (fsp->fh->fd != -1)) {
511 DEBUG(10,("set_ea: deleting ea name %s on "
512 "file %s by file descriptor.\n",
513 unix_ea_name, fsp_str_dbg(fsp)));
514 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
515 } else {
516 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
517 unix_ea_name, fname));
518 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
520 #ifdef ENOATTR
521 /* Removing a non existent attribute always succeeds. */
522 if (ret == -1 && errno == ENOATTR) {
523 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
524 unix_ea_name));
525 ret = 0;
527 #endif
528 } else {
529 if (fsp && (fsp->fh->fd != -1)) {
530 DEBUG(10,("set_ea: setting ea name %s on file "
531 "%s by file descriptor.\n",
532 unix_ea_name, fsp_str_dbg(fsp)));
533 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
534 ea_list->ea.value.data, ea_list->ea.value.length, 0);
535 } else {
536 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
537 unix_ea_name, fname));
538 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
539 ea_list->ea.value.data, ea_list->ea.value.length, 0);
543 if (ret == -1) {
544 #ifdef ENOTSUP
545 if (errno == ENOTSUP) {
546 return NT_STATUS_EAS_NOT_SUPPORTED;
548 #endif
549 return map_nt_error_from_unix(errno);
553 return NT_STATUS_OK;
555 /****************************************************************************
556 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
557 ****************************************************************************/
559 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
561 struct ea_list *ea_list_head = NULL;
562 size_t converted_size, offset = 0;
564 while (offset + 2 < data_size) {
565 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
566 unsigned int namelen = CVAL(pdata,offset);
568 offset++; /* Go past the namelen byte. */
570 /* integer wrap paranioa. */
571 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
572 (offset > data_size) || (namelen > data_size) ||
573 (offset + namelen >= data_size)) {
574 break;
576 /* Ensure the name is null terminated. */
577 if (pdata[offset + namelen] != '\0') {
578 return NULL;
580 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
581 &converted_size)) {
582 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
583 "failed: %s", strerror(errno)));
585 if (!eal->ea.name) {
586 return NULL;
589 offset += (namelen + 1); /* Go past the name + terminating zero. */
590 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
591 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
594 return ea_list_head;
597 /****************************************************************************
598 Read one EA list entry from the buffer.
599 ****************************************************************************/
601 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
603 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
604 uint16 val_len;
605 unsigned int namelen;
606 size_t converted_size;
608 if (!eal) {
609 return NULL;
612 if (data_size < 6) {
613 return NULL;
616 eal->ea.flags = CVAL(pdata,0);
617 namelen = CVAL(pdata,1);
618 val_len = SVAL(pdata,2);
620 if (4 + namelen + 1 + val_len > data_size) {
621 return NULL;
624 /* Ensure the name is null terminated. */
625 if (pdata[namelen + 4] != '\0') {
626 return NULL;
628 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
629 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
630 strerror(errno)));
632 if (!eal->ea.name) {
633 return NULL;
636 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
637 if (!eal->ea.value.data) {
638 return NULL;
641 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
643 /* Ensure we're null terminated just in case we print the value. */
644 eal->ea.value.data[val_len] = '\0';
645 /* But don't count the null. */
646 eal->ea.value.length--;
648 if (pbytes_used) {
649 *pbytes_used = 4 + namelen + 1 + val_len;
652 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
653 dump_data(10, eal->ea.value.data, eal->ea.value.length);
655 return eal;
658 /****************************************************************************
659 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
660 ****************************************************************************/
662 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
664 struct ea_list *ea_list_head = NULL;
665 size_t offset = 0;
666 size_t bytes_used = 0;
668 while (offset < data_size) {
669 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
671 if (!eal) {
672 return NULL;
675 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
676 offset += bytes_used;
679 return ea_list_head;
682 /****************************************************************************
683 Count the total EA size needed.
684 ****************************************************************************/
686 static size_t ea_list_size(struct ea_list *ealist)
688 fstring dos_ea_name;
689 struct ea_list *listp;
690 size_t ret = 0;
692 for (listp = ealist; listp; listp = listp->next) {
693 push_ascii_fstring(dos_ea_name, listp->ea.name);
694 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
696 /* Add on 4 for total length. */
697 if (ret) {
698 ret += 4;
701 return ret;
704 /****************************************************************************
705 Return a union of EA's from a file list and a list of names.
706 The TALLOC context for the two lists *MUST* be identical as we steal
707 memory from one list to add to another. JRA.
708 ****************************************************************************/
710 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
712 struct ea_list *nlistp, *flistp;
714 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
715 for (flistp = file_list; flistp; flistp = flistp->next) {
716 if (strequal(nlistp->ea.name, flistp->ea.name)) {
717 break;
721 if (flistp) {
722 /* Copy the data from this entry. */
723 nlistp->ea.flags = flistp->ea.flags;
724 nlistp->ea.value = flistp->ea.value;
725 } else {
726 /* Null entry. */
727 nlistp->ea.flags = 0;
728 ZERO_STRUCT(nlistp->ea.value);
732 *total_ea_len = ea_list_size(name_list);
733 return name_list;
736 /****************************************************************************
737 Send the required number of replies back.
738 We assume all fields other than the data fields are
739 set correctly for the type of call.
740 HACK ! Always assumes smb_setup field is zero.
741 ****************************************************************************/
743 void send_trans2_replies(connection_struct *conn,
744 struct smb_request *req,
745 const char *params,
746 int paramsize,
747 const char *pdata,
748 int datasize,
749 int max_data_bytes)
751 /* As we are using a protocol > LANMAN1 then the max_send
752 variable must have been set in the sessetupX call.
753 This takes precedence over the max_xmit field in the
754 global struct. These different max_xmit variables should
755 be merged as this is now too confusing */
757 int data_to_send = datasize;
758 int params_to_send = paramsize;
759 int useable_space;
760 const char *pp = params;
761 const char *pd = pdata;
762 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
763 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
764 int data_alignment_offset = 0;
765 bool overflow = False;
766 struct smbd_server_connection *sconn = smbd_server_conn;
767 int max_send = sconn->smb1.sessions.max_send;
769 /* Modify the data_to_send and datasize and set the error if
770 we're trying to send more than max_data_bytes. We still send
771 the part of the packet(s) that fit. Strange, but needed
772 for OS/2. */
774 if (max_data_bytes > 0 && datasize > max_data_bytes) {
775 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
776 max_data_bytes, datasize ));
777 datasize = data_to_send = max_data_bytes;
778 overflow = True;
781 /* If there genuinely are no parameters or data to send just send the empty packet */
783 if(params_to_send == 0 && data_to_send == 0) {
784 reply_outbuf(req, 10, 0);
785 show_msg((char *)req->outbuf);
786 if (!srv_send_smb(smbd_server_fd(),
787 (char *)req->outbuf,
788 true, req->seqnum+1,
789 IS_CONN_ENCRYPTED(conn),
790 &req->pcd)) {
791 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
793 TALLOC_FREE(req->outbuf);
794 return;
797 /* When sending params and data ensure that both are nicely aligned */
798 /* Only do this alignment when there is also data to send - else
799 can cause NT redirector problems. */
801 if (((params_to_send % 4) != 0) && (data_to_send != 0))
802 data_alignment_offset = 4 - (params_to_send % 4);
804 /* Space is bufsize minus Netbios over TCP header minus SMB header */
805 /* The alignment_offset is to align the param bytes on an even byte
806 boundary. NT 4.0 Beta needs this to work correctly. */
808 useable_space = max_send - (smb_size
809 + 2 * 10 /* wct */
810 + alignment_offset
811 + data_alignment_offset);
813 if (useable_space < 0) {
814 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
815 "= %d!!!", useable_space));
816 exit_server_cleanly("send_trans2_replies: Not enough space");
819 while (params_to_send || data_to_send) {
820 /* Calculate whether we will totally or partially fill this packet */
822 total_sent_thistime = params_to_send + data_to_send;
824 /* We can never send more than useable_space */
826 * Note that 'useable_space' does not include the alignment offsets,
827 * but we must include the alignment offsets in the calculation of
828 * the length of the data we send over the wire, as the alignment offsets
829 * are sent here. Fix from Marc_Jacobsen@hp.com.
832 total_sent_thistime = MIN(total_sent_thistime, useable_space);
834 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
835 + data_alignment_offset);
838 * We might have SMBtrans2s in req which was transferred to
839 * the outbuf, fix that.
841 SCVAL(req->outbuf, smb_com, SMBtrans2);
843 /* Set total params and data to be sent */
844 SSVAL(req->outbuf,smb_tprcnt,paramsize);
845 SSVAL(req->outbuf,smb_tdrcnt,datasize);
847 /* Calculate how many parameters and data we can fit into
848 * this packet. Parameters get precedence
851 params_sent_thistime = MIN(params_to_send,useable_space);
852 data_sent_thistime = useable_space - params_sent_thistime;
853 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
855 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
857 /* smb_proff is the offset from the start of the SMB header to the
858 parameter bytes, however the first 4 bytes of outbuf are
859 the Netbios over TCP header. Thus use smb_base() to subtract
860 them from the calculation */
862 SSVAL(req->outbuf,smb_proff,
863 ((smb_buf(req->outbuf)+alignment_offset)
864 - smb_base(req->outbuf)));
866 if(params_sent_thistime == 0)
867 SSVAL(req->outbuf,smb_prdisp,0);
868 else
869 /* Absolute displacement of param bytes sent in this packet */
870 SSVAL(req->outbuf,smb_prdisp,pp - params);
872 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
873 if(data_sent_thistime == 0) {
874 SSVAL(req->outbuf,smb_droff,0);
875 SSVAL(req->outbuf,smb_drdisp, 0);
876 } else {
877 /* The offset of the data bytes is the offset of the
878 parameter bytes plus the number of parameters being sent this time */
879 SSVAL(req->outbuf, smb_droff,
880 ((smb_buf(req->outbuf)+alignment_offset)
881 - smb_base(req->outbuf))
882 + params_sent_thistime + data_alignment_offset);
883 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
886 /* Initialize the padding for alignment */
888 if (alignment_offset != 0) {
889 memset(smb_buf(req->outbuf), 0, alignment_offset);
892 /* Copy the param bytes into the packet */
894 if(params_sent_thistime) {
895 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
896 params_sent_thistime);
899 /* Copy in the data bytes */
900 if(data_sent_thistime) {
901 if (data_alignment_offset != 0) {
902 memset((smb_buf(req->outbuf)+alignment_offset+
903 params_sent_thistime), 0,
904 data_alignment_offset);
906 memcpy(smb_buf(req->outbuf)+alignment_offset
907 +params_sent_thistime+data_alignment_offset,
908 pd,data_sent_thistime);
911 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
912 params_sent_thistime, data_sent_thistime, useable_space));
913 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
914 params_to_send, data_to_send, paramsize, datasize));
916 if (overflow) {
917 error_packet_set((char *)req->outbuf,
918 ERRDOS,ERRbufferoverflow,
919 STATUS_BUFFER_OVERFLOW,
920 __LINE__,__FILE__);
923 /* Send the packet */
924 show_msg((char *)req->outbuf);
925 if (!srv_send_smb(smbd_server_fd(),
926 (char *)req->outbuf,
927 true, req->seqnum+1,
928 IS_CONN_ENCRYPTED(conn),
929 &req->pcd))
930 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
932 TALLOC_FREE(req->outbuf);
934 pp += params_sent_thistime;
935 pd += data_sent_thistime;
937 params_to_send -= params_sent_thistime;
938 data_to_send -= data_sent_thistime;
940 /* Sanity check */
941 if(params_to_send < 0 || data_to_send < 0) {
942 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
943 params_to_send, data_to_send));
944 return;
948 return;
951 /****************************************************************************
952 Reply to a TRANSACT2_OPEN.
953 ****************************************************************************/
955 static void call_trans2open(connection_struct *conn,
956 struct smb_request *req,
957 char **pparams, int total_params,
958 char **ppdata, int total_data,
959 unsigned int max_data_bytes)
961 struct smb_filename *smb_fname = NULL;
962 char *params = *pparams;
963 char *pdata = *ppdata;
964 int deny_mode;
965 int32 open_attr;
966 bool oplock_request;
967 #if 0
968 bool return_additional_info;
969 int16 open_sattr;
970 time_t open_time;
971 #endif
972 int open_ofun;
973 uint32 open_size;
974 char *pname;
975 char *fname = NULL;
976 SMB_OFF_T size=0;
977 int fattr=0,mtime=0;
978 SMB_INO_T inode = 0;
979 int smb_action = 0;
980 files_struct *fsp;
981 struct ea_list *ea_list = NULL;
982 uint16 flags = 0;
983 NTSTATUS status;
984 uint32 access_mask;
985 uint32 share_mode;
986 uint32 create_disposition;
987 uint32 create_options = 0;
988 TALLOC_CTX *ctx = talloc_tos();
991 * Ensure we have enough parameters to perform the operation.
994 if (total_params < 29) {
995 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
996 goto out;
999 flags = SVAL(params, 0);
1000 deny_mode = SVAL(params, 2);
1001 open_attr = SVAL(params,6);
1002 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1003 if (oplock_request) {
1004 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1007 #if 0
1008 return_additional_info = BITSETW(params,0);
1009 open_sattr = SVAL(params, 4);
1010 open_time = make_unix_date3(params+8);
1011 #endif
1012 open_ofun = SVAL(params,12);
1013 open_size = IVAL(params,14);
1014 pname = &params[28];
1016 if (IS_IPC(conn)) {
1017 reply_doserror(req, ERRSRV, ERRaccess);
1018 goto out;
1021 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1022 total_params - 28, STR_TERMINATE,
1023 &status);
1024 if (!NT_STATUS_IS_OK(status)) {
1025 reply_nterror(req, status);
1026 goto out;
1029 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1030 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1031 (unsigned int)open_ofun, open_size));
1033 status = filename_convert(ctx,
1034 conn,
1035 req->flags2 & FLAGS2_DFS_PATHNAMES,
1036 fname,
1038 NULL,
1039 &smb_fname);
1040 if (!NT_STATUS_IS_OK(status)) {
1041 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1042 reply_botherror(req,
1043 NT_STATUS_PATH_NOT_COVERED,
1044 ERRSRV, ERRbadpath);
1045 goto out;
1047 reply_nterror(req, status);
1048 goto out;
1051 if (open_ofun == 0) {
1052 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1053 goto out;
1056 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1057 &access_mask, &share_mode,
1058 &create_disposition,
1059 &create_options)) {
1060 reply_doserror(req, ERRDOS, ERRbadaccess);
1061 goto out;
1064 /* Any data in this call is an EA list. */
1065 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1066 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1067 goto out;
1070 if (total_data != 4) {
1071 if (total_data < 10) {
1072 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1073 goto out;
1076 if (IVAL(pdata,0) > total_data) {
1077 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1078 IVAL(pdata,0), (unsigned int)total_data));
1079 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1080 goto out;
1083 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1084 total_data - 4);
1085 if (!ea_list) {
1086 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1087 goto out;
1089 } else if (IVAL(pdata,0) != 4) {
1090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1091 goto out;
1094 status = SMB_VFS_CREATE_FILE(
1095 conn, /* conn */
1096 req, /* req */
1097 0, /* root_dir_fid */
1098 smb_fname, /* fname */
1099 access_mask, /* access_mask */
1100 share_mode, /* share_access */
1101 create_disposition, /* create_disposition*/
1102 create_options, /* create_options */
1103 open_attr, /* file_attributes */
1104 oplock_request, /* oplock_request */
1105 open_size, /* allocation_size */
1106 NULL, /* sd */
1107 ea_list, /* ea_list */
1108 &fsp, /* result */
1109 &smb_action); /* psbuf */
1111 if (!NT_STATUS_IS_OK(status)) {
1112 if (open_was_deferred(req->mid)) {
1113 /* We have re-scheduled this call. */
1114 goto out;
1116 reply_openerror(req, status);
1117 goto out;
1120 size = get_file_size_stat(&smb_fname->st);
1121 fattr = dos_mode(conn, smb_fname);
1122 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1123 inode = smb_fname->st.st_ex_ino;
1124 if (fattr & aDIR) {
1125 close_file(req, fsp, ERROR_CLOSE);
1126 reply_doserror(req, ERRDOS,ERRnoaccess);
1127 goto out;
1130 /* Realloc the size of parameters and data we will return */
1131 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1132 if(*pparams == NULL ) {
1133 reply_nterror(req, NT_STATUS_NO_MEMORY);
1134 goto out;
1136 params = *pparams;
1138 SSVAL(params,0,fsp->fnum);
1139 SSVAL(params,2,fattr);
1140 srv_put_dos_date2(params,4, mtime);
1141 SIVAL(params,8, (uint32)size);
1142 SSVAL(params,12,deny_mode);
1143 SSVAL(params,14,0); /* open_type - file or directory. */
1144 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1146 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1147 smb_action |= EXTENDED_OPLOCK_GRANTED;
1150 SSVAL(params,18,smb_action);
1153 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1155 SIVAL(params,20,inode);
1156 SSVAL(params,24,0); /* Padding. */
1157 if (flags & 8) {
1158 uint32 ea_size = estimate_ea_size(conn, fsp,
1159 fsp->fsp_name->base_name);
1160 SIVAL(params, 26, ea_size);
1161 } else {
1162 SIVAL(params, 26, 0);
1165 /* Send the required number of replies */
1166 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1167 out:
1168 TALLOC_FREE(smb_fname);
1171 /*********************************************************
1172 Routine to check if a given string matches exactly.
1173 as a special case a mask of "." does NOT match. That
1174 is required for correct wildcard semantics
1175 Case can be significant or not.
1176 **********************************************************/
1178 static bool exact_match(bool has_wild,
1179 bool case_sensitive,
1180 const char *str,
1181 const char *mask)
1183 if (mask[0] == '.' && mask[1] == 0) {
1184 return false;
1187 if (has_wild) {
1188 return false;
1191 if (case_sensitive) {
1192 return strcmp(str,mask)==0;
1193 } else {
1194 return StrCaseCmp(str,mask) == 0;
1198 /****************************************************************************
1199 Return the filetype for UNIX extensions.
1200 ****************************************************************************/
1202 static uint32 unix_filetype(mode_t mode)
1204 if(S_ISREG(mode))
1205 return UNIX_TYPE_FILE;
1206 else if(S_ISDIR(mode))
1207 return UNIX_TYPE_DIR;
1208 #ifdef S_ISLNK
1209 else if(S_ISLNK(mode))
1210 return UNIX_TYPE_SYMLINK;
1211 #endif
1212 #ifdef S_ISCHR
1213 else if(S_ISCHR(mode))
1214 return UNIX_TYPE_CHARDEV;
1215 #endif
1216 #ifdef S_ISBLK
1217 else if(S_ISBLK(mode))
1218 return UNIX_TYPE_BLKDEV;
1219 #endif
1220 #ifdef S_ISFIFO
1221 else if(S_ISFIFO(mode))
1222 return UNIX_TYPE_FIFO;
1223 #endif
1224 #ifdef S_ISSOCK
1225 else if(S_ISSOCK(mode))
1226 return UNIX_TYPE_SOCKET;
1227 #endif
1229 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1230 return UNIX_TYPE_UNKNOWN;
1233 /****************************************************************************
1234 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1235 ****************************************************************************/
1237 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1239 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1240 const SMB_STRUCT_STAT *psbuf,
1241 uint32 perms,
1242 enum perm_type ptype,
1243 mode_t *ret_perms)
1245 mode_t ret = 0;
1247 if (perms == SMB_MODE_NO_CHANGE) {
1248 if (!VALID_STAT(*psbuf)) {
1249 return NT_STATUS_INVALID_PARAMETER;
1250 } else {
1251 *ret_perms = psbuf->st_ex_mode;
1252 return NT_STATUS_OK;
1256 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1257 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1258 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1259 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1260 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1261 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1262 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1263 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1264 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1265 #ifdef S_ISVTX
1266 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1267 #endif
1268 #ifdef S_ISGID
1269 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1270 #endif
1271 #ifdef S_ISUID
1272 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1273 #endif
1275 switch (ptype) {
1276 case PERM_NEW_FILE:
1277 /* Apply mode mask */
1278 ret &= lp_create_mask(SNUM(conn));
1279 /* Add in force bits */
1280 ret |= lp_force_create_mode(SNUM(conn));
1281 break;
1282 case PERM_NEW_DIR:
1283 ret &= lp_dir_mask(SNUM(conn));
1284 /* Add in force bits */
1285 ret |= lp_force_dir_mode(SNUM(conn));
1286 break;
1287 case PERM_EXISTING_FILE:
1288 /* Apply mode mask */
1289 ret &= lp_security_mask(SNUM(conn));
1290 /* Add in force bits */
1291 ret |= lp_force_security_mode(SNUM(conn));
1292 break;
1293 case PERM_EXISTING_DIR:
1294 /* Apply mode mask */
1295 ret &= lp_dir_security_mask(SNUM(conn));
1296 /* Add in force bits */
1297 ret |= lp_force_dir_security_mode(SNUM(conn));
1298 break;
1301 *ret_perms = ret;
1302 return NT_STATUS_OK;
1305 /****************************************************************************
1306 Needed to show the msdfs symlinks as directories. Modifies psbuf
1307 to be a directory if it's a msdfs link.
1308 ****************************************************************************/
1310 static bool check_msdfs_link(connection_struct *conn,
1311 const char *pathname,
1312 SMB_STRUCT_STAT *psbuf)
1314 int saved_errno = errno;
1315 if(lp_host_msdfs() &&
1316 lp_msdfs_root(SNUM(conn)) &&
1317 is_msdfs_link(conn, pathname, psbuf)) {
1319 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1320 "as a directory\n",
1321 pathname));
1322 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1323 errno = saved_errno;
1324 return true;
1326 errno = saved_errno;
1327 return false;
1331 /****************************************************************************
1332 Get a level dependent lanman2 dir entry.
1333 ****************************************************************************/
1335 struct smbd_dirptr_lanman2_state {
1336 connection_struct *conn;
1337 uint32_t info_level;
1338 bool check_mangled_names;
1339 bool has_wild;
1340 bool got_exact_match;
1343 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1344 void *private_data,
1345 const char *dname,
1346 const char *mask,
1347 char **_fname)
1349 struct smbd_dirptr_lanman2_state *state =
1350 (struct smbd_dirptr_lanman2_state *)private_data;
1351 bool ok;
1352 char mangled_name[13]; /* mangled 8.3 name. */
1353 bool got_match;
1354 const char *fname;
1356 /* Mangle fname if it's an illegal name. */
1357 if (mangle_must_mangle(dname, state->conn->params)) {
1358 ok = name_to_8_3(dname, mangled_name,
1359 true, state->conn->params);
1360 if (!ok) {
1361 return false;
1363 fname = mangled_name;
1364 } else {
1365 fname = dname;
1368 got_match = exact_match(state->has_wild,
1369 state->conn->case_sensitive,
1370 fname, mask);
1371 state->got_exact_match = got_match;
1372 if (!got_match) {
1373 got_match = mask_match(fname, mask,
1374 state->conn->case_sensitive);
1377 if(!got_match && state->check_mangled_names &&
1378 !mangle_is_8_3(fname, false, state->conn->params)) {
1380 * It turns out that NT matches wildcards against
1381 * both long *and* short names. This may explain some
1382 * of the wildcard wierdness from old DOS clients
1383 * that some people have been seeing.... JRA.
1385 /* Force the mangling into 8.3. */
1386 ok = name_to_8_3(fname, mangled_name,
1387 false, state->conn->params);
1388 if (!ok) {
1389 return false;
1392 got_match = exact_match(state->has_wild,
1393 state->conn->case_sensitive,
1394 mangled_name, mask);
1395 state->got_exact_match = got_match;
1396 if (!got_match) {
1397 got_match = mask_match(mangled_name, mask,
1398 state->conn->case_sensitive);
1402 if (!got_match) {
1403 return false;
1406 *_fname = talloc_strdup(ctx, fname);
1407 if (*_fname == NULL) {
1408 return false;
1411 return true;
1414 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1415 void *private_data,
1416 struct smb_filename *smb_fname,
1417 uint32_t *_mode)
1419 struct smbd_dirptr_lanman2_state *state =
1420 (struct smbd_dirptr_lanman2_state *)private_data;
1421 bool ms_dfs_link = false;
1422 uint32_t mode = 0;
1424 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1425 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1426 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1427 "Couldn't lstat [%s] (%s)\n",
1428 smb_fname_str_dbg(smb_fname),
1429 strerror(errno)));
1430 return false;
1432 } else if (!VALID_STAT(smb_fname->st) &&
1433 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1434 /* Needed to show the msdfs symlinks as
1435 * directories */
1437 ms_dfs_link = check_msdfs_link(state->conn,
1438 smb_fname->base_name,
1439 &smb_fname->st);
1440 if (!ms_dfs_link) {
1441 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1442 "Couldn't stat [%s] (%s)\n",
1443 smb_fname_str_dbg(smb_fname),
1444 strerror(errno)));
1445 return false;
1449 if (ms_dfs_link) {
1450 mode = dos_mode_msdfs(state->conn, smb_fname);
1451 } else {
1452 mode = dos_mode(state->conn, smb_fname);
1455 *_mode = mode;
1456 return true;
1459 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1460 connection_struct *conn,
1461 uint16_t flags2,
1462 uint32_t info_level,
1463 struct ea_list *name_list,
1464 bool check_mangled_names,
1465 bool requires_resume_key,
1466 uint32_t mode,
1467 const char *fname,
1468 const struct smb_filename *smb_fname,
1469 uint64_t space_remaining,
1470 uint8_t align,
1471 bool do_pad,
1472 char *base_data,
1473 char **ppdata,
1474 char *end_data,
1475 bool *out_of_space,
1476 uint64_t *last_entry_off)
1478 char *p, *q, *pdata = *ppdata;
1479 uint32_t reskey=0;
1480 uint64_t file_size = 0;
1481 uint64_t allocation_size = 0;
1482 uint32_t len;
1483 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1484 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1485 time_t c_date = (time_t)0;
1486 char *nameptr;
1487 char *last_entry_ptr;
1488 bool was_8_3;
1489 uint32_t nt_extmode; /* Used for NT connections instead of mode */
1490 off_t off;
1491 off_t pad = 0;
1493 *out_of_space = false;
1495 ZERO_STRUCT(mdate_ts);
1496 ZERO_STRUCT(adate_ts);
1497 ZERO_STRUCT(create_date_ts);
1498 ZERO_STRUCT(cdate_ts);
1500 if (!(mode & aDIR)) {
1501 file_size = get_file_size_stat(&smb_fname->st);
1503 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1505 mdate_ts = smb_fname->st.st_ex_mtime;
1506 adate_ts = smb_fname->st.st_ex_atime;
1507 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1508 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1510 if (lp_dos_filetime_resolution(SNUM(conn))) {
1511 dos_filetime_timespec(&create_date_ts);
1512 dos_filetime_timespec(&mdate_ts);
1513 dos_filetime_timespec(&adate_ts);
1514 dos_filetime_timespec(&cdate_ts);
1517 create_date = convert_timespec_to_time_t(create_date_ts);
1518 mdate = convert_timespec_to_time_t(mdate_ts);
1519 adate = convert_timespec_to_time_t(adate_ts);
1520 c_date = convert_timespec_to_time_t(cdate_ts);
1522 /* align the record */
1523 off = PTR_DIFF(pdata, base_data);
1524 pad = (off + (align-1)) & ~(align-1);
1525 pad -= off;
1526 off += pad;
1527 /* initialize padding to 0 */
1528 if (pad) {
1529 memset(pdata, 0, pad);
1531 space_remaining -= pad;
1533 pdata += pad;
1534 p = pdata;
1535 last_entry_ptr = p;
1537 pad = 0;
1538 off = 0;
1540 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1542 switch (info_level) {
1543 case SMB_FIND_INFO_STANDARD:
1544 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1545 if(requires_resume_key) {
1546 SIVAL(p,0,reskey);
1547 p += 4;
1549 srv_put_dos_date2(p,0,create_date);
1550 srv_put_dos_date2(p,4,adate);
1551 srv_put_dos_date2(p,8,mdate);
1552 SIVAL(p,12,(uint32)file_size);
1553 SIVAL(p,16,(uint32)allocation_size);
1554 SSVAL(p,20,mode);
1555 p += 23;
1556 nameptr = p;
1557 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1558 p += ucs2_align(base_data, p, 0);
1560 len = srvstr_push(base_data, flags2, p,
1561 fname, PTR_DIFF(end_data, p),
1562 STR_TERMINATE);
1563 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1564 if (len > 2) {
1565 SCVAL(nameptr, -1, len - 2);
1566 } else {
1567 SCVAL(nameptr, -1, 0);
1569 } else {
1570 if (len > 1) {
1571 SCVAL(nameptr, -1, len - 1);
1572 } else {
1573 SCVAL(nameptr, -1, 0);
1576 p += len;
1577 break;
1579 case SMB_FIND_EA_SIZE:
1580 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1581 if (requires_resume_key) {
1582 SIVAL(p,0,reskey);
1583 p += 4;
1585 srv_put_dos_date2(p,0,create_date);
1586 srv_put_dos_date2(p,4,adate);
1587 srv_put_dos_date2(p,8,mdate);
1588 SIVAL(p,12,(uint32)file_size);
1589 SIVAL(p,16,(uint32)allocation_size);
1590 SSVAL(p,20,mode);
1592 unsigned int ea_size = estimate_ea_size(conn, NULL,
1593 smb_fname->base_name);
1594 SIVAL(p,22,ea_size); /* Extended attributes */
1596 p += 27;
1597 nameptr = p - 1;
1598 len = srvstr_push(base_data, flags2,
1599 p, fname, PTR_DIFF(end_data, p),
1600 STR_TERMINATE | STR_NOALIGN);
1601 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1602 if (len > 2) {
1603 len -= 2;
1604 } else {
1605 len = 0;
1607 } else {
1608 if (len > 1) {
1609 len -= 1;
1610 } else {
1611 len = 0;
1614 SCVAL(nameptr,0,len);
1615 p += len;
1616 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1617 break;
1619 case SMB_FIND_EA_LIST:
1621 struct ea_list *file_list = NULL;
1622 size_t ea_len = 0;
1624 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1625 if (!name_list) {
1626 return false;
1628 if (requires_resume_key) {
1629 SIVAL(p,0,reskey);
1630 p += 4;
1632 srv_put_dos_date2(p,0,create_date);
1633 srv_put_dos_date2(p,4,adate);
1634 srv_put_dos_date2(p,8,mdate);
1635 SIVAL(p,12,(uint32)file_size);
1636 SIVAL(p,16,(uint32)allocation_size);
1637 SSVAL(p,20,mode);
1638 p += 22; /* p now points to the EA area. */
1640 file_list = get_ea_list_from_file(ctx, conn, NULL,
1641 smb_fname->base_name,
1642 &ea_len);
1643 name_list = ea_list_union(name_list, file_list, &ea_len);
1645 /* We need to determine if this entry will fit in the space available. */
1646 /* Max string size is 255 bytes. */
1647 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1648 *out_of_space = true;
1649 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
1650 return False; /* Not finished - just out of space */
1653 /* Push the ea_data followed by the name. */
1654 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1655 nameptr = p;
1656 len = srvstr_push(base_data, flags2,
1657 p + 1, fname, PTR_DIFF(end_data, p+1),
1658 STR_TERMINATE | STR_NOALIGN);
1659 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1660 if (len > 2) {
1661 len -= 2;
1662 } else {
1663 len = 0;
1665 } else {
1666 if (len > 1) {
1667 len -= 1;
1668 } else {
1669 len = 0;
1672 SCVAL(nameptr,0,len);
1673 p += len + 1;
1674 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1675 break;
1678 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1679 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1680 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1681 p += 4;
1682 SIVAL(p,0,reskey); p += 4;
1683 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1684 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1685 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1686 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1687 SOFF_T(p,0,file_size); p += 8;
1688 SOFF_T(p,0,allocation_size); p += 8;
1689 SIVAL(p,0,nt_extmode); p += 4;
1690 q = p; p += 4; /* q is placeholder for name length. */
1692 unsigned int ea_size = estimate_ea_size(conn, NULL,
1693 smb_fname->base_name);
1694 SIVAL(p,0,ea_size); /* Extended attributes */
1695 p += 4;
1697 /* Clear the short name buffer. This is
1698 * IMPORTANT as not doing so will trigger
1699 * a Win2k client bug. JRA.
1701 if (!was_8_3 && check_mangled_names) {
1702 char mangled_name[13]; /* mangled 8.3 name. */
1703 if (!name_to_8_3(fname,mangled_name,True,
1704 conn->params)) {
1705 /* Error - mangle failed ! */
1706 memset(mangled_name,'\0',12);
1708 mangled_name[12] = 0;
1709 len = srvstr_push(base_data, flags2,
1710 p+2, mangled_name, 24,
1711 STR_UPPER|STR_UNICODE);
1712 if (len < 24) {
1713 memset(p + 2 + len,'\0',24 - len);
1715 SSVAL(p, 0, len);
1716 } else {
1717 memset(p,'\0',26);
1719 p += 2 + 24;
1720 len = srvstr_push(base_data, flags2, p,
1721 fname, PTR_DIFF(end_data, p),
1722 STR_TERMINATE_ASCII);
1723 SIVAL(q,0,len);
1724 p += len;
1726 len = PTR_DIFF(p, pdata);
1727 pad = (len + (align-1)) & ~(align-1);
1729 * offset to the next entry, the caller
1730 * will overwrite it for the last entry
1731 * that's why we always include the padding
1733 SIVAL(pdata,0,pad);
1735 * set padding to zero
1737 if (do_pad) {
1738 memset(p, 0, pad - len);
1739 p = pdata + pad;
1740 } else {
1741 p = pdata + len;
1743 break;
1745 case SMB_FIND_FILE_DIRECTORY_INFO:
1746 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1747 p += 4;
1748 SIVAL(p,0,reskey); p += 4;
1749 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1750 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1751 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1752 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1753 SOFF_T(p,0,file_size); p += 8;
1754 SOFF_T(p,0,allocation_size); p += 8;
1755 SIVAL(p,0,nt_extmode); p += 4;
1756 len = srvstr_push(base_data, flags2,
1757 p + 4, fname, PTR_DIFF(end_data, p+4),
1758 STR_TERMINATE_ASCII);
1759 SIVAL(p,0,len);
1760 p += 4 + len;
1762 len = PTR_DIFF(p, pdata);
1763 pad = (len + (align-1)) & ~(align-1);
1765 * offset to the next entry, the caller
1766 * will overwrite it for the last entry
1767 * that's why we always include the padding
1769 SIVAL(pdata,0,pad);
1771 * set padding to zero
1773 if (do_pad) {
1774 memset(p, 0, pad - len);
1775 p = pdata + pad;
1776 } else {
1777 p = pdata + len;
1779 break;
1781 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1782 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1783 p += 4;
1784 SIVAL(p,0,reskey); p += 4;
1785 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1786 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1787 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1788 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1789 SOFF_T(p,0,file_size); p += 8;
1790 SOFF_T(p,0,allocation_size); p += 8;
1791 SIVAL(p,0,nt_extmode); p += 4;
1792 q = p; p += 4; /* q is placeholder for name length. */
1794 unsigned int ea_size = estimate_ea_size(conn, NULL,
1795 smb_fname->base_name);
1796 SIVAL(p,0,ea_size); /* Extended attributes */
1797 p +=4;
1799 len = srvstr_push(base_data, flags2, p,
1800 fname, PTR_DIFF(end_data, p),
1801 STR_TERMINATE_ASCII);
1802 SIVAL(q, 0, len);
1803 p += len;
1805 len = PTR_DIFF(p, pdata);
1806 pad = (len + (align-1)) & ~(align-1);
1808 * offset to the next entry, the caller
1809 * will overwrite it for the last entry
1810 * that's why we always include the padding
1812 SIVAL(pdata,0,pad);
1814 * set padding to zero
1816 if (do_pad) {
1817 memset(p, 0, pad - len);
1818 p = pdata + pad;
1819 } else {
1820 p = pdata + len;
1822 break;
1824 case SMB_FIND_FILE_NAMES_INFO:
1825 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1826 p += 4;
1827 SIVAL(p,0,reskey); p += 4;
1828 p += 4;
1829 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1830 acl on a dir (tridge) */
1831 len = srvstr_push(base_data, flags2, p,
1832 fname, PTR_DIFF(end_data, p),
1833 STR_TERMINATE_ASCII);
1834 SIVAL(p, -4, len);
1835 p += len;
1837 len = PTR_DIFF(p, pdata);
1838 pad = (len + (align-1)) & ~(align-1);
1840 * offset to the next entry, the caller
1841 * will overwrite it for the last entry
1842 * that's why we always include the padding
1844 SIVAL(pdata,0,pad);
1846 * set padding to zero
1848 if (do_pad) {
1849 memset(p, 0, pad - len);
1850 p = pdata + pad;
1851 } else {
1852 p = pdata + len;
1854 break;
1856 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1857 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1858 p += 4;
1859 SIVAL(p,0,reskey); p += 4;
1860 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1861 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1862 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1863 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1864 SOFF_T(p,0,file_size); p += 8;
1865 SOFF_T(p,0,allocation_size); p += 8;
1866 SIVAL(p,0,nt_extmode); p += 4;
1867 q = p; p += 4; /* q is placeholder for name length. */
1869 unsigned int ea_size = estimate_ea_size(conn, NULL,
1870 smb_fname->base_name);
1871 SIVAL(p,0,ea_size); /* Extended attributes */
1872 p +=4;
1874 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1875 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1876 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1877 len = srvstr_push(base_data, flags2, p,
1878 fname, PTR_DIFF(end_data, p),
1879 STR_TERMINATE_ASCII);
1880 SIVAL(q, 0, len);
1881 p += len;
1883 len = PTR_DIFF(p, pdata);
1884 pad = (len + (align-1)) & ~(align-1);
1886 * offset to the next entry, the caller
1887 * will overwrite it for the last entry
1888 * that's why we always include the padding
1890 SIVAL(pdata,0,pad);
1892 * set padding to zero
1894 if (do_pad) {
1895 memset(p, 0, pad - len);
1896 p = pdata + pad;
1897 } else {
1898 p = pdata + len;
1900 break;
1902 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1903 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1904 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1905 p += 4;
1906 SIVAL(p,0,reskey); p += 4;
1907 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1908 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1909 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1910 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1911 SOFF_T(p,0,file_size); p += 8;
1912 SOFF_T(p,0,allocation_size); p += 8;
1913 SIVAL(p,0,nt_extmode); p += 4;
1914 q = p; p += 4; /* q is placeholder for name length */
1916 unsigned int ea_size = estimate_ea_size(conn, NULL,
1917 smb_fname->base_name);
1918 SIVAL(p,0,ea_size); /* Extended attributes */
1919 p +=4;
1921 /* Clear the short name buffer. This is
1922 * IMPORTANT as not doing so will trigger
1923 * a Win2k client bug. JRA.
1925 if (!was_8_3 && check_mangled_names) {
1926 char mangled_name[13]; /* mangled 8.3 name. */
1927 if (!name_to_8_3(fname,mangled_name,True,
1928 conn->params)) {
1929 /* Error - mangle failed ! */
1930 memset(mangled_name,'\0',12);
1932 mangled_name[12] = 0;
1933 len = srvstr_push(base_data, flags2,
1934 p+2, mangled_name, 24,
1935 STR_UPPER|STR_UNICODE);
1936 SSVAL(p, 0, len);
1937 if (len < 24) {
1938 memset(p + 2 + len,'\0',24 - len);
1940 SSVAL(p, 0, len);
1941 } else {
1942 memset(p,'\0',26);
1944 p += 26;
1945 SSVAL(p,0,0); p += 2; /* Reserved ? */
1946 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1947 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1948 len = srvstr_push(base_data, flags2, p,
1949 fname, PTR_DIFF(end_data, p),
1950 STR_TERMINATE_ASCII);
1951 SIVAL(q,0,len);
1952 p += len;
1954 len = PTR_DIFF(p, pdata);
1955 pad = (len + (align-1)) & ~(align-1);
1957 * offset to the next entry, the caller
1958 * will overwrite it for the last entry
1959 * that's why we always include the padding
1961 SIVAL(pdata,0,pad);
1963 * set padding to zero
1965 if (do_pad) {
1966 memset(p, 0, pad - len);
1967 p = pdata + pad;
1968 } else {
1969 p = pdata + len;
1971 break;
1973 /* CIFS UNIX Extension. */
1975 case SMB_FIND_FILE_UNIX:
1976 case SMB_FIND_FILE_UNIX_INFO2:
1977 p+= 4;
1978 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1980 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1982 if (info_level == SMB_FIND_FILE_UNIX) {
1983 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1984 p = store_file_unix_basic(conn, p,
1985 NULL, &smb_fname->st);
1986 len = srvstr_push(base_data, flags2, p,
1987 fname, PTR_DIFF(end_data, p),
1988 STR_TERMINATE);
1989 } else {
1990 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1991 p = store_file_unix_basic_info2(conn, p,
1992 NULL, &smb_fname->st);
1993 nameptr = p;
1994 p += 4;
1995 len = srvstr_push(base_data, flags2, p, fname,
1996 PTR_DIFF(end_data, p), 0);
1997 SIVAL(nameptr, 0, len);
2000 p += len;
2002 len = PTR_DIFF(p, pdata);
2003 pad = (len + (align-1)) & ~(align-1);
2005 * offset to the next entry, the caller
2006 * will overwrite it for the last entry
2007 * that's why we always include the padding
2009 SIVAL(pdata,0,pad);
2011 * set padding to zero
2013 if (do_pad) {
2014 memset(p, 0, pad - len);
2015 p = pdata + pad;
2016 } else {
2017 p = pdata + len;
2019 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2021 break;
2023 default:
2024 return false;
2027 if (PTR_DIFF(p,pdata) > space_remaining) {
2028 *out_of_space = true;
2029 DEBUG(9,("smbd_marshall_dir_entry: out of space\n"));
2030 return false; /* Not finished - just out of space */
2033 /* Setup the last entry pointer, as an offset from base_data */
2034 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2035 /* Advance the data pointer to the next slot */
2036 *ppdata = p;
2038 return true;
2041 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2042 connection_struct *conn,
2043 struct dptr_struct *dirptr,
2044 uint16 flags2,
2045 const char *path_mask,
2046 uint32 dirtype,
2047 int info_level,
2048 int requires_resume_key,
2049 bool dont_descend,
2050 bool ask_sharemode,
2051 uint8_t align,
2052 bool do_pad,
2053 char **ppdata,
2054 char *base_data,
2055 char *end_data,
2056 int space_remaining,
2057 bool *out_of_space,
2058 bool *got_exact_match,
2059 int *_last_entry_off,
2060 struct ea_list *name_list)
2062 const char *p;
2063 const char *mask = NULL;
2064 long prev_dirpos = 0;
2065 uint32_t mode = 0;
2066 char *fname = NULL;
2067 struct smb_filename *smb_fname = NULL;
2068 struct smbd_dirptr_lanman2_state state;
2069 bool ok;
2070 uint64_t last_entry_off = 0;
2072 ZERO_STRUCT(state);
2073 state.conn = conn;
2074 state.info_level = info_level;
2075 state.check_mangled_names = lp_manglednames(conn->params);
2076 state.has_wild = dptr_has_wild(dirptr);
2077 state.got_exact_match = false;
2079 *out_of_space = false;
2080 *got_exact_match = false;
2082 p = strrchr_m(path_mask,'/');
2083 if(p != NULL) {
2084 if(p[1] == '\0') {
2085 mask = "*.*";
2086 } else {
2087 mask = p+1;
2089 } else {
2090 mask = path_mask;
2093 ok = smbd_dirptr_get_entry(ctx,
2094 dirptr,
2095 mask,
2096 dirtype,
2097 dont_descend,
2098 ask_sharemode,
2099 smbd_dirptr_lanman2_match_fn,
2100 smbd_dirptr_lanman2_mode_fn,
2101 &state,
2102 &fname,
2103 &smb_fname,
2104 &mode,
2105 &prev_dirpos);
2106 if (!ok) {
2107 return false;
2110 *got_exact_match = state.got_exact_match;
2112 ok = smbd_marshall_dir_entry(ctx,
2113 conn,
2114 flags2,
2115 info_level,
2116 name_list,
2117 state.check_mangled_names,
2118 requires_resume_key,
2119 mode,
2120 fname,
2121 smb_fname,
2122 space_remaining,
2123 align,
2124 do_pad,
2125 base_data,
2126 ppdata,
2127 end_data,
2128 out_of_space,
2129 &last_entry_off);
2130 TALLOC_FREE(fname);
2131 TALLOC_FREE(smb_fname);
2132 if (*out_of_space) {
2133 dptr_SeekDir(dirptr, prev_dirpos);
2134 return false;
2136 if (!ok) {
2137 return false;
2140 *_last_entry_off = last_entry_off;
2141 return true;
2144 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2145 connection_struct *conn,
2146 struct dptr_struct *dirptr,
2147 uint16 flags2,
2148 const char *path_mask,
2149 uint32 dirtype,
2150 int info_level,
2151 bool requires_resume_key,
2152 bool dont_descend,
2153 bool ask_sharemode,
2154 char **ppdata,
2155 char *base_data,
2156 char *end_data,
2157 int space_remaining,
2158 bool *out_of_space,
2159 bool *got_exact_match,
2160 int *last_entry_off,
2161 struct ea_list *name_list)
2163 uint8_t align = 4;
2164 const bool do_pad = true;
2166 if (info_level >= 1 && info_level <= 3) {
2167 /* No alignment on earlier info levels. */
2168 align = 1;
2171 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2172 path_mask, dirtype, info_level,
2173 requires_resume_key, dont_descend, ask_sharemode,
2174 align, do_pad,
2175 ppdata, base_data, end_data,
2176 space_remaining,
2177 out_of_space, got_exact_match,
2178 last_entry_off, name_list);
2181 /****************************************************************************
2182 Reply to a TRANS2_FINDFIRST.
2183 ****************************************************************************/
2185 static void call_trans2findfirst(connection_struct *conn,
2186 struct smb_request *req,
2187 char **pparams, int total_params,
2188 char **ppdata, int total_data,
2189 unsigned int max_data_bytes)
2191 /* We must be careful here that we don't return more than the
2192 allowed number of data bytes. If this means returning fewer than
2193 maxentries then so be it. We assume that the redirector has
2194 enough room for the fixed number of parameter bytes it has
2195 requested. */
2196 struct smb_filename *smb_dname = NULL;
2197 char *params = *pparams;
2198 char *pdata = *ppdata;
2199 char *data_end;
2200 uint32 dirtype;
2201 int maxentries;
2202 uint16 findfirst_flags;
2203 bool close_after_first;
2204 bool close_if_end;
2205 bool requires_resume_key;
2206 int info_level;
2207 char *directory = NULL;
2208 char *mask = NULL;
2209 char *p;
2210 int last_entry_off=0;
2211 int dptr_num = -1;
2212 int numentries = 0;
2213 int i;
2214 bool finished = False;
2215 bool dont_descend = False;
2216 bool out_of_space = False;
2217 int space_remaining;
2218 bool mask_contains_wcard = False;
2219 struct ea_list *ea_list = NULL;
2220 NTSTATUS ntstatus = NT_STATUS_OK;
2221 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2222 TALLOC_CTX *ctx = talloc_tos();
2223 struct dptr_struct *dirptr = NULL;
2224 struct smbd_server_connection *sconn = smbd_server_conn;
2226 if (total_params < 13) {
2227 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2228 goto out;
2231 dirtype = SVAL(params,0);
2232 maxentries = SVAL(params,2);
2233 findfirst_flags = SVAL(params,4);
2234 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2235 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2236 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2237 info_level = SVAL(params,6);
2239 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2240 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2241 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2242 info_level, max_data_bytes));
2244 if (!maxentries) {
2245 /* W2K3 seems to treat zero as 1. */
2246 maxentries = 1;
2249 switch (info_level) {
2250 case SMB_FIND_INFO_STANDARD:
2251 case SMB_FIND_EA_SIZE:
2252 case SMB_FIND_EA_LIST:
2253 case SMB_FIND_FILE_DIRECTORY_INFO:
2254 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2255 case SMB_FIND_FILE_NAMES_INFO:
2256 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2257 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2258 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2259 break;
2260 case SMB_FIND_FILE_UNIX:
2261 case SMB_FIND_FILE_UNIX_INFO2:
2262 /* Always use filesystem for UNIX mtime query. */
2263 ask_sharemode = false;
2264 if (!lp_unix_extensions()) {
2265 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2266 goto out;
2268 break;
2269 default:
2270 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2271 goto out;
2274 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2275 params+12, total_params - 12,
2276 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2277 if (!NT_STATUS_IS_OK(ntstatus)) {
2278 reply_nterror(req, ntstatus);
2279 goto out;
2282 ntstatus = filename_convert(ctx, conn,
2283 req->flags2 & FLAGS2_DFS_PATHNAMES,
2284 directory,
2285 (UCF_SAVE_LCOMP |
2286 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2287 &mask_contains_wcard,
2288 &smb_dname);
2289 if (!NT_STATUS_IS_OK(ntstatus)) {
2290 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2291 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2292 ERRSRV, ERRbadpath);
2293 goto out;
2295 reply_nterror(req, ntstatus);
2296 goto out;
2299 mask = smb_dname->original_lcomp;
2301 directory = smb_dname->base_name;
2303 p = strrchr_m(directory,'/');
2304 if(p == NULL) {
2305 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2306 if((directory[0] == '.') && (directory[1] == '\0')) {
2307 mask = talloc_strdup(ctx,"*");
2308 if (!mask) {
2309 reply_nterror(req, NT_STATUS_NO_MEMORY);
2310 goto out;
2312 mask_contains_wcard = True;
2314 directory = talloc_strdup(talloc_tos(), "./");
2315 if (!directory) {
2316 reply_nterror(req, NT_STATUS_NO_MEMORY);
2317 goto out;
2319 } else {
2320 *p = 0;
2323 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2325 if (info_level == SMB_FIND_EA_LIST) {
2326 uint32 ea_size;
2328 if (total_data < 4) {
2329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2330 goto out;
2333 ea_size = IVAL(pdata,0);
2334 if (ea_size != total_data) {
2335 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2336 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2338 goto out;
2341 if (!lp_ea_support(SNUM(conn))) {
2342 reply_doserror(req, ERRDOS, ERReasnotsupported);
2343 goto out;
2346 /* Pull out the list of names. */
2347 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2348 if (!ea_list) {
2349 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2350 goto out;
2354 *ppdata = (char *)SMB_REALLOC(
2355 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2356 if(*ppdata == NULL ) {
2357 reply_nterror(req, NT_STATUS_NO_MEMORY);
2358 goto out;
2360 pdata = *ppdata;
2361 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2363 /* Realloc the params space */
2364 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2365 if (*pparams == NULL) {
2366 reply_nterror(req, NT_STATUS_NO_MEMORY);
2367 goto out;
2369 params = *pparams;
2371 /* Save the wildcard match and attribs we are using on this directory -
2372 needed as lanman2 assumes these are being saved between calls */
2374 ntstatus = dptr_create(conn,
2375 directory,
2376 False,
2377 True,
2378 req->smbpid,
2379 mask,
2380 mask_contains_wcard,
2381 dirtype,
2382 &dirptr);
2384 if (!NT_STATUS_IS_OK(ntstatus)) {
2385 reply_nterror(req, ntstatus);
2386 goto out;
2389 dptr_num = dptr_dnum(dirptr);
2390 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2392 /* Initialize per TRANS2_FIND_FIRST operation data */
2393 dptr_init_search_op(dirptr);
2395 /* We don't need to check for VOL here as this is returned by
2396 a different TRANS2 call. */
2398 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2399 directory,lp_dontdescend(SNUM(conn))));
2400 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2401 dont_descend = True;
2403 p = pdata;
2404 space_remaining = max_data_bytes;
2405 out_of_space = False;
2407 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2408 bool got_exact_match = False;
2410 /* this is a heuristic to avoid seeking the dirptr except when
2411 absolutely necessary. It allows for a filename of about 40 chars */
2412 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2413 out_of_space = True;
2414 finished = False;
2415 } else {
2416 finished = !get_lanman2_dir_entry(ctx,
2417 conn,
2418 dirptr,
2419 req->flags2,
2420 mask,dirtype,info_level,
2421 requires_resume_key,dont_descend,
2422 ask_sharemode,
2423 &p,pdata,data_end,
2424 space_remaining, &out_of_space,
2425 &got_exact_match,
2426 &last_entry_off, ea_list);
2429 if (finished && out_of_space)
2430 finished = False;
2432 if (!finished && !out_of_space)
2433 numentries++;
2436 * As an optimisation if we know we aren't looking
2437 * for a wildcard name (ie. the name matches the wildcard exactly)
2438 * then we can finish on any (first) match.
2439 * This speeds up large directory searches. JRA.
2442 if(got_exact_match)
2443 finished = True;
2445 /* Ensure space_remaining never goes -ve. */
2446 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2447 space_remaining = 0;
2448 out_of_space = true;
2449 } else {
2450 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2454 /* Check if we can close the dirptr */
2455 if(close_after_first || (finished && close_if_end)) {
2456 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2457 dptr_close(sconn, &dptr_num);
2461 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2462 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2463 * the protocol level is less than NT1. Tested with smbclient. JRA.
2464 * This should fix the OS/2 client bug #2335.
2467 if(numentries == 0) {
2468 dptr_close(sconn, &dptr_num);
2469 if (Protocol < PROTOCOL_NT1) {
2470 reply_doserror(req, ERRDOS, ERRnofiles);
2471 goto out;
2472 } else {
2473 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2474 ERRDOS, ERRbadfile);
2475 goto out;
2479 /* At this point pdata points to numentries directory entries. */
2481 /* Set up the return parameter block */
2482 SSVAL(params,0,dptr_num);
2483 SSVAL(params,2,numentries);
2484 SSVAL(params,4,finished);
2485 SSVAL(params,6,0); /* Never an EA error */
2486 SSVAL(params,8,last_entry_off);
2488 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2489 max_data_bytes);
2491 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2492 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2493 if (!directory) {
2494 reply_nterror(req, NT_STATUS_NO_MEMORY);
2498 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2499 smb_fn_name(req->cmd),
2500 mask, directory, dirtype, numentries ) );
2503 * Force a name mangle here to ensure that the
2504 * mask as an 8.3 name is top of the mangled cache.
2505 * The reasons for this are subtle. Don't remove
2506 * this code unless you know what you are doing
2507 * (see PR#13758). JRA.
2510 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2511 char mangled_name[13];
2512 name_to_8_3(mask, mangled_name, True, conn->params);
2514 out:
2515 TALLOC_FREE(smb_dname);
2516 return;
2519 /****************************************************************************
2520 Reply to a TRANS2_FINDNEXT.
2521 ****************************************************************************/
2523 static void call_trans2findnext(connection_struct *conn,
2524 struct smb_request *req,
2525 char **pparams, int total_params,
2526 char **ppdata, int total_data,
2527 unsigned int max_data_bytes)
2529 /* We must be careful here that we don't return more than the
2530 allowed number of data bytes. If this means returning fewer than
2531 maxentries then so be it. We assume that the redirector has
2532 enough room for the fixed number of parameter bytes it has
2533 requested. */
2534 char *params = *pparams;
2535 char *pdata = *ppdata;
2536 char *data_end;
2537 int dptr_num;
2538 int maxentries;
2539 uint16 info_level;
2540 uint32 resume_key;
2541 uint16 findnext_flags;
2542 bool close_after_request;
2543 bool close_if_end;
2544 bool requires_resume_key;
2545 bool continue_bit;
2546 bool mask_contains_wcard = False;
2547 char *resume_name = NULL;
2548 const char *mask = NULL;
2549 const char *directory = NULL;
2550 char *p = NULL;
2551 uint16 dirtype;
2552 int numentries = 0;
2553 int i, last_entry_off=0;
2554 bool finished = False;
2555 bool dont_descend = False;
2556 bool out_of_space = False;
2557 int space_remaining;
2558 struct ea_list *ea_list = NULL;
2559 NTSTATUS ntstatus = NT_STATUS_OK;
2560 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2561 TALLOC_CTX *ctx = talloc_tos();
2562 struct dptr_struct *dirptr;
2563 struct smbd_server_connection *sconn = smbd_server_conn;
2565 if (total_params < 13) {
2566 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2567 return;
2570 dptr_num = SVAL(params,0);
2571 maxentries = SVAL(params,2);
2572 info_level = SVAL(params,4);
2573 resume_key = IVAL(params,6);
2574 findnext_flags = SVAL(params,10);
2575 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2576 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2577 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2578 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2580 if (!continue_bit) {
2581 /* We only need resume_name if continue_bit is zero. */
2582 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2583 params+12,
2584 total_params - 12, STR_TERMINATE, &ntstatus,
2585 &mask_contains_wcard);
2586 if (!NT_STATUS_IS_OK(ntstatus)) {
2587 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2588 complain (it thinks we're asking for the directory above the shared
2589 path or an invalid name). Catch this as the resume name is only compared, never used in
2590 a file access. JRA. */
2591 srvstr_pull_talloc(ctx, params, req->flags2,
2592 &resume_name, params+12,
2593 total_params - 12,
2594 STR_TERMINATE);
2596 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2597 reply_nterror(req, ntstatus);
2598 return;
2603 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2604 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2605 resume_key = %d resume name = %s continue=%d level = %d\n",
2606 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2607 requires_resume_key, resume_key,
2608 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2610 if (!maxentries) {
2611 /* W2K3 seems to treat zero as 1. */
2612 maxentries = 1;
2615 switch (info_level) {
2616 case SMB_FIND_INFO_STANDARD:
2617 case SMB_FIND_EA_SIZE:
2618 case SMB_FIND_EA_LIST:
2619 case SMB_FIND_FILE_DIRECTORY_INFO:
2620 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2621 case SMB_FIND_FILE_NAMES_INFO:
2622 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2623 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2624 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2625 break;
2626 case SMB_FIND_FILE_UNIX:
2627 case SMB_FIND_FILE_UNIX_INFO2:
2628 /* Always use filesystem for UNIX mtime query. */
2629 ask_sharemode = false;
2630 if (!lp_unix_extensions()) {
2631 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2632 return;
2634 break;
2635 default:
2636 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2637 return;
2640 if (info_level == SMB_FIND_EA_LIST) {
2641 uint32 ea_size;
2643 if (total_data < 4) {
2644 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2645 return;
2648 ea_size = IVAL(pdata,0);
2649 if (ea_size != total_data) {
2650 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2651 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2652 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2653 return;
2656 if (!lp_ea_support(SNUM(conn))) {
2657 reply_doserror(req, ERRDOS, ERReasnotsupported);
2658 return;
2661 /* Pull out the list of names. */
2662 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2663 if (!ea_list) {
2664 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2665 return;
2669 *ppdata = (char *)SMB_REALLOC(
2670 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2671 if(*ppdata == NULL) {
2672 reply_nterror(req, NT_STATUS_NO_MEMORY);
2673 return;
2676 pdata = *ppdata;
2677 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2679 /* Realloc the params space */
2680 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2681 if(*pparams == NULL ) {
2682 reply_nterror(req, NT_STATUS_NO_MEMORY);
2683 return;
2686 params = *pparams;
2688 /* Check that the dptr is valid */
2689 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2690 reply_doserror(req, ERRDOS, ERRnofiles);
2691 return;
2694 directory = dptr_path(sconn, dptr_num);
2696 /* Get the wildcard mask from the dptr */
2697 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2698 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2699 reply_doserror(req, ERRDOS, ERRnofiles);
2700 return;
2703 mask = p;
2705 /* Get the attr mask from the dptr */
2706 dirtype = dptr_attr(sconn, dptr_num);
2708 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2709 dptr_num, mask, dirtype,
2710 (long)dirptr,
2711 dptr_TellDir(dirptr)));
2713 /* Initialize per TRANS2_FIND_NEXT operation data */
2714 dptr_init_search_op(dirptr);
2716 /* We don't need to check for VOL here as this is returned by
2717 a different TRANS2 call. */
2719 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2720 directory,lp_dontdescend(SNUM(conn))));
2721 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2722 dont_descend = True;
2724 p = pdata;
2725 space_remaining = max_data_bytes;
2726 out_of_space = False;
2729 * Seek to the correct position. We no longer use the resume key but
2730 * depend on the last file name instead.
2733 if(!continue_bit && resume_name && *resume_name) {
2734 SMB_STRUCT_STAT st;
2736 long current_pos = 0;
2738 * Remember, name_to_8_3 is called by
2739 * get_lanman2_dir_entry(), so the resume name
2740 * could be mangled. Ensure we check the unmangled name.
2743 if (mangle_is_mangled(resume_name, conn->params)) {
2744 char *new_resume_name = NULL;
2745 mangle_lookup_name_from_8_3(ctx,
2746 resume_name,
2747 &new_resume_name,
2748 conn->params);
2749 if (new_resume_name) {
2750 resume_name = new_resume_name;
2755 * Fix for NT redirector problem triggered by resume key indexes
2756 * changing between directory scans. We now return a resume key of 0
2757 * and instead look for the filename to continue from (also given
2758 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2759 * findfirst/findnext (as is usual) then the directory pointer
2760 * should already be at the correct place.
2763 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2764 } /* end if resume_name && !continue_bit */
2766 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2767 bool got_exact_match = False;
2769 /* this is a heuristic to avoid seeking the dirptr except when
2770 absolutely necessary. It allows for a filename of about 40 chars */
2771 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2772 out_of_space = True;
2773 finished = False;
2774 } else {
2775 finished = !get_lanman2_dir_entry(ctx,
2776 conn,
2777 dirptr,
2778 req->flags2,
2779 mask,dirtype,info_level,
2780 requires_resume_key,dont_descend,
2781 ask_sharemode,
2782 &p,pdata,data_end,
2783 space_remaining, &out_of_space,
2784 &got_exact_match,
2785 &last_entry_off, ea_list);
2788 if (finished && out_of_space)
2789 finished = False;
2791 if (!finished && !out_of_space)
2792 numentries++;
2795 * As an optimisation if we know we aren't looking
2796 * for a wildcard name (ie. the name matches the wildcard exactly)
2797 * then we can finish on any (first) match.
2798 * This speeds up large directory searches. JRA.
2801 if(got_exact_match)
2802 finished = True;
2804 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2807 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2808 smb_fn_name(req->cmd),
2809 mask, directory, dirtype, numentries ) );
2811 /* Check if we can close the dirptr */
2812 if(close_after_request || (finished && close_if_end)) {
2813 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2814 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2817 /* Set up the return parameter block */
2818 SSVAL(params,0,numentries);
2819 SSVAL(params,2,finished);
2820 SSVAL(params,4,0); /* Never an EA error */
2821 SSVAL(params,6,last_entry_off);
2823 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2824 max_data_bytes);
2826 return;
2829 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2831 E_md4hash(lp_servicename(SNUM(conn)),objid);
2832 return objid;
2835 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2837 SMB_ASSERT(extended_info != NULL);
2839 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2840 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2841 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2842 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2843 #ifdef SAMBA_VERSION_REVISION
2844 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2845 #endif
2846 extended_info->samba_subversion = 0;
2847 #ifdef SAMBA_VERSION_RC_RELEASE
2848 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2849 #else
2850 #ifdef SAMBA_VERSION_PRE_RELEASE
2851 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2852 #endif
2853 #endif
2854 #ifdef SAMBA_VERSION_VENDOR_PATCH
2855 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2856 #endif
2857 extended_info->samba_gitcommitdate = 0;
2858 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2859 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2860 #endif
2862 memset(extended_info->samba_version_string, 0,
2863 sizeof(extended_info->samba_version_string));
2865 snprintf (extended_info->samba_version_string,
2866 sizeof(extended_info->samba_version_string),
2867 "%s", samba_version_string());
2870 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2871 TALLOC_CTX *mem_ctx,
2872 uint16_t info_level,
2873 uint16_t flags2,
2874 unsigned int max_data_bytes,
2875 char **ppdata,
2876 int *ret_data_len)
2878 char *pdata, *end_data;
2879 int data_len = 0, len;
2880 const char *vname = volume_label(SNUM(conn));
2881 int snum = SNUM(conn);
2882 char *fstype = lp_fstype(SNUM(conn));
2883 uint32 additional_flags = 0;
2884 struct smb_filename *smb_fname_dot = NULL;
2885 SMB_STRUCT_STAT st;
2886 NTSTATUS status;
2888 if (IS_IPC(conn)) {
2889 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2890 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2891 "info level (0x%x) on IPC$.\n",
2892 (unsigned int)info_level));
2893 return NT_STATUS_ACCESS_DENIED;
2897 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2899 status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL,
2900 &smb_fname_dot);
2901 if (!NT_STATUS_IS_OK(status)) {
2902 return status;
2905 if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) {
2906 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2907 TALLOC_FREE(smb_fname_dot);
2908 return map_nt_error_from_unix(errno);
2911 st = smb_fname_dot->st;
2912 TALLOC_FREE(smb_fname_dot);
2914 *ppdata = (char *)SMB_REALLOC(
2915 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2916 if (*ppdata == NULL) {
2917 return NT_STATUS_NO_MEMORY;
2920 pdata = *ppdata;
2921 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2922 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2924 switch (info_level) {
2925 case SMB_INFO_ALLOCATION:
2927 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2928 data_len = 18;
2929 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2930 return map_nt_error_from_unix(errno);
2933 block_size = lp_block_size(snum);
2934 if (bsize < block_size) {
2935 uint64_t factor = block_size/bsize;
2936 bsize = block_size;
2937 dsize /= factor;
2938 dfree /= factor;
2940 if (bsize > block_size) {
2941 uint64_t factor = bsize/block_size;
2942 bsize = block_size;
2943 dsize *= factor;
2944 dfree *= factor;
2946 bytes_per_sector = 512;
2947 sectors_per_unit = bsize/bytes_per_sector;
2949 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2950 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2951 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2953 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2954 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2955 SIVAL(pdata,l1_cUnit,dsize);
2956 SIVAL(pdata,l1_cUnitAvail,dfree);
2957 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2958 break;
2961 case SMB_INFO_VOLUME:
2962 /* Return volume name */
2964 * Add volume serial number - hash of a combination of
2965 * the called hostname and the service name.
2967 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2969 * Win2k3 and previous mess this up by sending a name length
2970 * one byte short. I believe only older clients (OS/2 Win9x) use
2971 * this call so try fixing this by adding a terminating null to
2972 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2974 len = srvstr_push(
2975 pdata, flags2,
2976 pdata+l2_vol_szVolLabel, vname,
2977 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2978 STR_NOALIGN|STR_TERMINATE);
2979 SCVAL(pdata,l2_vol_cch,len);
2980 data_len = l2_vol_szVolLabel + len;
2981 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2982 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2983 len, vname));
2984 break;
2986 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2987 case SMB_FS_ATTRIBUTE_INFORMATION:
2989 additional_flags = 0;
2990 #if defined(HAVE_SYS_QUOTAS)
2991 additional_flags |= FILE_VOLUME_QUOTAS;
2992 #endif
2994 if(lp_nt_acl_support(SNUM(conn))) {
2995 additional_flags |= FILE_PERSISTENT_ACLS;
2998 /* Capabilities are filled in at connection time through STATVFS call */
2999 additional_flags |= conn->fs_capabilities;
3000 additional_flags |= lp_parm_int(conn->params->service,
3001 "share", "fake_fscaps",
3004 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3005 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3006 additional_flags); /* FS ATTRIBUTES */
3008 SIVAL(pdata,4,255); /* Max filename component length */
3009 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3010 and will think we can't do long filenames */
3011 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3012 PTR_DIFF(end_data, pdata+12),
3013 STR_UNICODE);
3014 SIVAL(pdata,8,len);
3015 data_len = 12 + len;
3016 break;
3018 case SMB_QUERY_FS_LABEL_INFO:
3019 case SMB_FS_LABEL_INFORMATION:
3020 len = srvstr_push(pdata, flags2, pdata+4, vname,
3021 PTR_DIFF(end_data, pdata+4), 0);
3022 data_len = 4 + len;
3023 SIVAL(pdata,0,len);
3024 break;
3026 case SMB_QUERY_FS_VOLUME_INFO:
3027 case SMB_FS_VOLUME_INFORMATION:
3030 * Add volume serial number - hash of a combination of
3031 * the called hostname and the service name.
3033 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3034 (str_checksum(get_local_machine_name())<<16));
3036 /* Max label len is 32 characters. */
3037 len = srvstr_push(pdata, flags2, pdata+18, vname,
3038 PTR_DIFF(end_data, pdata+18),
3039 STR_UNICODE);
3040 SIVAL(pdata,12,len);
3041 data_len = 18+len;
3043 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3044 (int)strlen(vname),vname, lp_servicename(snum)));
3045 break;
3047 case SMB_QUERY_FS_SIZE_INFO:
3048 case SMB_FS_SIZE_INFORMATION:
3050 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3051 data_len = 24;
3052 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3053 return map_nt_error_from_unix(errno);
3055 block_size = lp_block_size(snum);
3056 if (bsize < block_size) {
3057 uint64_t factor = block_size/bsize;
3058 bsize = block_size;
3059 dsize /= factor;
3060 dfree /= factor;
3062 if (bsize > block_size) {
3063 uint64_t factor = bsize/block_size;
3064 bsize = block_size;
3065 dsize *= factor;
3066 dfree *= factor;
3068 bytes_per_sector = 512;
3069 sectors_per_unit = bsize/bytes_per_sector;
3070 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3071 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3072 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3073 SBIG_UINT(pdata,0,dsize);
3074 SBIG_UINT(pdata,8,dfree);
3075 SIVAL(pdata,16,sectors_per_unit);
3076 SIVAL(pdata,20,bytes_per_sector);
3077 break;
3080 case SMB_FS_FULL_SIZE_INFORMATION:
3082 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3083 data_len = 32;
3084 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3085 return map_nt_error_from_unix(errno);
3087 block_size = lp_block_size(snum);
3088 if (bsize < block_size) {
3089 uint64_t factor = block_size/bsize;
3090 bsize = block_size;
3091 dsize /= factor;
3092 dfree /= factor;
3094 if (bsize > block_size) {
3095 uint64_t factor = bsize/block_size;
3096 bsize = block_size;
3097 dsize *= factor;
3098 dfree *= factor;
3100 bytes_per_sector = 512;
3101 sectors_per_unit = bsize/bytes_per_sector;
3102 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3103 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3104 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3105 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3106 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3107 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3108 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3109 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3110 break;
3113 case SMB_QUERY_FS_DEVICE_INFO:
3114 case SMB_FS_DEVICE_INFORMATION:
3115 data_len = 8;
3116 SIVAL(pdata,0,0); /* dev type */
3117 SIVAL(pdata,4,0); /* characteristics */
3118 break;
3120 #ifdef HAVE_SYS_QUOTAS
3121 case SMB_FS_QUOTA_INFORMATION:
3123 * what we have to send --metze:
3125 * Unknown1: 24 NULL bytes
3126 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3127 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3128 * Quota Flags: 2 byte :
3129 * Unknown3: 6 NULL bytes
3131 * 48 bytes total
3133 * details for Quota Flags:
3135 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3136 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3137 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3138 * 0x0001 Enable Quotas: enable quota for this fs
3142 /* we need to fake up a fsp here,
3143 * because its not send in this call
3145 files_struct fsp;
3146 SMB_NTQUOTA_STRUCT quotas;
3148 ZERO_STRUCT(fsp);
3149 ZERO_STRUCT(quotas);
3151 fsp.conn = conn;
3152 fsp.fnum = -1;
3154 /* access check */
3155 if (conn->server_info->utok.uid != sec_initial_uid()) {
3156 DEBUG(0,("set_user_quota: access_denied "
3157 "service [%s] user [%s]\n",
3158 lp_servicename(SNUM(conn)),
3159 conn->server_info->unix_name));
3160 return NT_STATUS_ACCESS_DENIED;
3163 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3164 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3165 return map_nt_error_from_unix(errno);
3168 data_len = 48;
3170 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3171 lp_servicename(SNUM(conn))));
3173 /* Unknown1 24 NULL bytes*/
3174 SBIG_UINT(pdata,0,(uint64_t)0);
3175 SBIG_UINT(pdata,8,(uint64_t)0);
3176 SBIG_UINT(pdata,16,(uint64_t)0);
3178 /* Default Soft Quota 8 bytes */
3179 SBIG_UINT(pdata,24,quotas.softlim);
3181 /* Default Hard Quota 8 bytes */
3182 SBIG_UINT(pdata,32,quotas.hardlim);
3184 /* Quota flag 2 bytes */
3185 SSVAL(pdata,40,quotas.qflags);
3187 /* Unknown3 6 NULL bytes */
3188 SSVAL(pdata,42,0);
3189 SIVAL(pdata,44,0);
3191 break;
3193 #endif /* HAVE_SYS_QUOTAS */
3194 case SMB_FS_OBJECTID_INFORMATION:
3196 unsigned char objid[16];
3197 struct smb_extended_info extended_info;
3198 memcpy(pdata,create_volume_objectid(conn, objid),16);
3199 samba_extended_info_version (&extended_info);
3200 SIVAL(pdata,16,extended_info.samba_magic);
3201 SIVAL(pdata,20,extended_info.samba_version);
3202 SIVAL(pdata,24,extended_info.samba_subversion);
3203 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3204 memcpy(pdata+36,extended_info.samba_version_string,28);
3205 data_len = 64;
3206 break;
3210 * Query the version and capabilities of the CIFS UNIX extensions
3211 * in use.
3214 case SMB_QUERY_CIFS_UNIX_INFO:
3216 bool large_write = lp_min_receive_file_size() &&
3217 !srv_is_signing_active(smbd_server_conn);
3218 bool large_read = !srv_is_signing_active(smbd_server_conn);
3219 int encrypt_caps = 0;
3221 if (!lp_unix_extensions()) {
3222 return NT_STATUS_INVALID_LEVEL;
3225 switch (conn->encrypt_level) {
3226 case 0:
3227 encrypt_caps = 0;
3228 break;
3229 case 1:
3230 case Auto:
3231 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3232 break;
3233 case Required:
3234 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3235 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3236 large_write = false;
3237 large_read = false;
3238 break;
3241 data_len = 12;
3242 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3243 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3245 /* We have POSIX ACLs, pathname, encryption,
3246 * large read/write, and locking capability. */
3248 SBIG_UINT(pdata,4,((uint64_t)(
3249 CIFS_UNIX_POSIX_ACLS_CAP|
3250 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3251 CIFS_UNIX_FCNTL_LOCKS_CAP|
3252 CIFS_UNIX_EXTATTR_CAP|
3253 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3254 encrypt_caps|
3255 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3256 (large_write ?
3257 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3258 break;
3261 case SMB_QUERY_POSIX_FS_INFO:
3263 int rc;
3264 vfs_statvfs_struct svfs;
3266 if (!lp_unix_extensions()) {
3267 return NT_STATUS_INVALID_LEVEL;
3270 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3272 if (!rc) {
3273 data_len = 56;
3274 SIVAL(pdata,0,svfs.OptimalTransferSize);
3275 SIVAL(pdata,4,svfs.BlockSize);
3276 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3277 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3278 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3279 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3280 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3281 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3282 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3283 #ifdef EOPNOTSUPP
3284 } else if (rc == EOPNOTSUPP) {
3285 return NT_STATUS_INVALID_LEVEL;
3286 #endif /* EOPNOTSUPP */
3287 } else {
3288 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3289 return NT_STATUS_DOS(ERRSRV, ERRerror);
3291 break;
3294 case SMB_QUERY_POSIX_WHOAMI:
3296 uint32_t flags = 0;
3297 uint32_t sid_bytes;
3298 int i;
3300 if (!lp_unix_extensions()) {
3301 return NT_STATUS_INVALID_LEVEL;
3304 if (max_data_bytes < 40) {
3305 return NT_STATUS_BUFFER_TOO_SMALL;
3308 /* We ARE guest if global_sid_Builtin_Guests is
3309 * in our list of SIDs.
3311 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3312 conn->server_info->ptok)) {
3313 flags |= SMB_WHOAMI_GUEST;
3316 /* We are NOT guest if global_sid_Authenticated_Users
3317 * is in our list of SIDs.
3319 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3320 conn->server_info->ptok)) {
3321 flags &= ~SMB_WHOAMI_GUEST;
3324 /* NOTE: 8 bytes for UID/GID, irrespective of native
3325 * platform size. This matches
3326 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3328 data_len = 4 /* flags */
3329 + 4 /* flag mask */
3330 + 8 /* uid */
3331 + 8 /* gid */
3332 + 4 /* ngroups */
3333 + 4 /* num_sids */
3334 + 4 /* SID bytes */
3335 + 4 /* pad/reserved */
3336 + (conn->server_info->utok.ngroups * 8)
3337 /* groups list */
3338 + (conn->server_info->ptok->num_sids *
3339 SID_MAX_SIZE)
3340 /* SID list */;
3342 SIVAL(pdata, 0, flags);
3343 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3344 SBIG_UINT(pdata, 8,
3345 (uint64_t)conn->server_info->utok.uid);
3346 SBIG_UINT(pdata, 16,
3347 (uint64_t)conn->server_info->utok.gid);
3350 if (data_len >= max_data_bytes) {
3351 /* Potential overflow, skip the GIDs and SIDs. */
3353 SIVAL(pdata, 24, 0); /* num_groups */
3354 SIVAL(pdata, 28, 0); /* num_sids */
3355 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3356 SIVAL(pdata, 36, 0); /* reserved */
3358 data_len = 40;
3359 break;
3362 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3363 SIVAL(pdata, 28, conn->server_info->num_sids);
3365 /* We walk the SID list twice, but this call is fairly
3366 * infrequent, and I don't expect that it's performance
3367 * sensitive -- jpeach
3369 for (i = 0, sid_bytes = 0;
3370 i < conn->server_info->ptok->num_sids; ++i) {
3371 sid_bytes += ndr_size_dom_sid(
3372 &conn->server_info->ptok->user_sids[i],
3373 NULL,
3377 /* SID list byte count */
3378 SIVAL(pdata, 32, sid_bytes);
3380 /* 4 bytes pad/reserved - must be zero */
3381 SIVAL(pdata, 36, 0);
3382 data_len = 40;
3384 /* GID list */
3385 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3386 SBIG_UINT(pdata, data_len,
3387 (uint64_t)conn->server_info->utok.groups[i]);
3388 data_len += 8;
3391 /* SID list */
3392 for (i = 0;
3393 i < conn->server_info->ptok->num_sids; ++i) {
3394 int sid_len = ndr_size_dom_sid(
3395 &conn->server_info->ptok->user_sids[i],
3396 NULL,
3399 sid_linearize(pdata + data_len, sid_len,
3400 &conn->server_info->ptok->user_sids[i]);
3401 data_len += sid_len;
3404 break;
3407 case SMB_MAC_QUERY_FS_INFO:
3409 * Thursby MAC extension... ONLY on NTFS filesystems
3410 * once we do streams then we don't need this
3412 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3413 data_len = 88;
3414 SIVAL(pdata,84,0x100); /* Don't support mac... */
3415 break;
3417 /* drop through */
3418 default:
3419 return NT_STATUS_INVALID_LEVEL;
3422 *ret_data_len = data_len;
3423 return NT_STATUS_OK;
3426 /****************************************************************************
3427 Reply to a TRANS2_QFSINFO (query filesystem info).
3428 ****************************************************************************/
3430 static void call_trans2qfsinfo(connection_struct *conn,
3431 struct smb_request *req,
3432 char **pparams, int total_params,
3433 char **ppdata, int total_data,
3434 unsigned int max_data_bytes)
3436 char *params = *pparams;
3437 uint16_t info_level;
3438 int data_len = 0;
3439 NTSTATUS status;
3441 if (total_params < 2) {
3442 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3443 return;
3446 info_level = SVAL(params,0);
3448 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3449 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3450 DEBUG(0,("call_trans2qfsinfo: encryption required "
3451 "and info level 0x%x sent.\n",
3452 (unsigned int)info_level));
3453 exit_server_cleanly("encryption required "
3454 "on connection");
3455 return;
3459 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3461 status = smbd_do_qfsinfo(conn, req,
3462 info_level,
3463 req->flags2,
3464 max_data_bytes,
3465 ppdata, &data_len);
3466 if (!NT_STATUS_IS_OK(status)) {
3467 reply_nterror(req, status);
3468 return;
3471 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3472 max_data_bytes);
3474 DEBUG( 4, ( "%s info_level = %d\n",
3475 smb_fn_name(req->cmd), info_level) );
3477 return;
3480 /****************************************************************************
3481 Reply to a TRANS2_SETFSINFO (set filesystem info).
3482 ****************************************************************************/
3484 static void call_trans2setfsinfo(connection_struct *conn,
3485 struct smb_request *req,
3486 char **pparams, int total_params,
3487 char **ppdata, int total_data,
3488 unsigned int max_data_bytes)
3490 char *pdata = *ppdata;
3491 char *params = *pparams;
3492 uint16 info_level;
3494 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3496 /* */
3497 if (total_params < 4) {
3498 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3499 total_params));
3500 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3501 return;
3504 info_level = SVAL(params,2);
3506 if (IS_IPC(conn)) {
3507 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3508 info_level != SMB_SET_CIFS_UNIX_INFO) {
3509 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3510 "info level (0x%x) on IPC$.\n",
3511 (unsigned int)info_level));
3512 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3513 return;
3517 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3518 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3519 DEBUG(0,("call_trans2setfsinfo: encryption required "
3520 "and info level 0x%x sent.\n",
3521 (unsigned int)info_level));
3522 exit_server_cleanly("encryption required "
3523 "on connection");
3524 return;
3528 switch(info_level) {
3529 case SMB_SET_CIFS_UNIX_INFO:
3531 uint16 client_unix_major;
3532 uint16 client_unix_minor;
3533 uint32 client_unix_cap_low;
3534 uint32 client_unix_cap_high;
3536 if (!lp_unix_extensions()) {
3537 reply_nterror(req,
3538 NT_STATUS_INVALID_LEVEL);
3539 return;
3542 /* There should be 12 bytes of capabilities set. */
3543 if (total_data < 8) {
3544 reply_nterror(
3545 req,
3546 NT_STATUS_INVALID_PARAMETER);
3547 return;
3549 client_unix_major = SVAL(pdata,0);
3550 client_unix_minor = SVAL(pdata,2);
3551 client_unix_cap_low = IVAL(pdata,4);
3552 client_unix_cap_high = IVAL(pdata,8);
3553 /* Just print these values for now. */
3554 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3555 cap_low = 0x%x, cap_high = 0x%x\n",
3556 (unsigned int)client_unix_major,
3557 (unsigned int)client_unix_minor,
3558 (unsigned int)client_unix_cap_low,
3559 (unsigned int)client_unix_cap_high ));
3561 /* Here is where we must switch to posix pathname processing... */
3562 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3563 lp_set_posix_pathnames();
3564 mangle_change_to_posix();
3567 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3568 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3569 /* Client that knows how to do posix locks,
3570 * but not posix open/mkdir operations. Set a
3571 * default type for read/write checks. */
3573 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3576 break;
3579 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3581 NTSTATUS status;
3582 size_t param_len = 0;
3583 size_t data_len = total_data;
3585 if (!lp_unix_extensions()) {
3586 reply_nterror(
3587 req,
3588 NT_STATUS_INVALID_LEVEL);
3589 return;
3592 if (lp_smb_encrypt(SNUM(conn)) == false) {
3593 reply_nterror(
3594 req,
3595 NT_STATUS_NOT_SUPPORTED);
3596 return;
3599 DEBUG( 4,("call_trans2setfsinfo: "
3600 "request transport encryption.\n"));
3602 status = srv_request_encryption_setup(conn,
3603 (unsigned char **)ppdata,
3604 &data_len,
3605 (unsigned char **)pparams,
3606 &param_len);
3608 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3609 !NT_STATUS_IS_OK(status)) {
3610 reply_nterror(req, status);
3611 return;
3614 send_trans2_replies(conn, req,
3615 *pparams,
3616 param_len,
3617 *ppdata,
3618 data_len,
3619 max_data_bytes);
3621 if (NT_STATUS_IS_OK(status)) {
3622 /* Server-side transport
3623 * encryption is now *on*. */
3624 status = srv_encryption_start(conn);
3625 if (!NT_STATUS_IS_OK(status)) {
3626 exit_server_cleanly(
3627 "Failure in setting "
3628 "up encrypted transport");
3631 return;
3634 case SMB_FS_QUOTA_INFORMATION:
3636 files_struct *fsp = NULL;
3637 SMB_NTQUOTA_STRUCT quotas;
3639 ZERO_STRUCT(quotas);
3641 /* access check */
3642 if ((conn->server_info->utok.uid != sec_initial_uid())
3643 ||!CAN_WRITE(conn)) {
3644 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3645 lp_servicename(SNUM(conn)),
3646 conn->server_info->unix_name));
3647 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3648 return;
3651 /* note: normaly there're 48 bytes,
3652 * but we didn't use the last 6 bytes for now
3653 * --metze
3655 fsp = file_fsp(req, SVAL(params,0));
3657 if (!check_fsp_ntquota_handle(conn, req,
3658 fsp)) {
3659 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3660 reply_nterror(
3661 req, NT_STATUS_INVALID_HANDLE);
3662 return;
3665 if (total_data < 42) {
3666 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3667 total_data));
3668 reply_nterror(
3669 req,
3670 NT_STATUS_INVALID_PARAMETER);
3671 return;
3674 /* unknown_1 24 NULL bytes in pdata*/
3676 /* the soft quotas 8 bytes (uint64_t)*/
3677 quotas.softlim = (uint64_t)IVAL(pdata,24);
3678 #ifdef LARGE_SMB_OFF_T
3679 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3680 #else /* LARGE_SMB_OFF_T */
3681 if ((IVAL(pdata,28) != 0)&&
3682 ((quotas.softlim != 0xFFFFFFFF)||
3683 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3684 /* more than 32 bits? */
3685 reply_nterror(
3686 req,
3687 NT_STATUS_INVALID_PARAMETER);
3688 return;
3690 #endif /* LARGE_SMB_OFF_T */
3692 /* the hard quotas 8 bytes (uint64_t)*/
3693 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3694 #ifdef LARGE_SMB_OFF_T
3695 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3696 #else /* LARGE_SMB_OFF_T */
3697 if ((IVAL(pdata,36) != 0)&&
3698 ((quotas.hardlim != 0xFFFFFFFF)||
3699 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3700 /* more than 32 bits? */
3701 reply_nterror(
3702 req,
3703 NT_STATUS_INVALID_PARAMETER);
3704 return;
3706 #endif /* LARGE_SMB_OFF_T */
3708 /* quota_flags 2 bytes **/
3709 quotas.qflags = SVAL(pdata,40);
3711 /* unknown_2 6 NULL bytes follow*/
3713 /* now set the quotas */
3714 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3715 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3716 reply_nterror(req, map_nt_error_from_unix(errno));
3717 return;
3720 break;
3722 default:
3723 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3724 info_level));
3725 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3726 return;
3727 break;
3731 * sending this reply works fine,
3732 * but I'm not sure it's the same
3733 * like windows do...
3734 * --metze
3736 reply_outbuf(req, 10, 0);
3739 #if defined(HAVE_POSIX_ACLS)
3740 /****************************************************************************
3741 Utility function to count the number of entries in a POSIX acl.
3742 ****************************************************************************/
3744 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3746 unsigned int ace_count = 0;
3747 int entry_id = SMB_ACL_FIRST_ENTRY;
3748 SMB_ACL_ENTRY_T entry;
3750 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3751 /* get_next... */
3752 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3753 entry_id = SMB_ACL_NEXT_ENTRY;
3755 ace_count++;
3757 return ace_count;
3760 /****************************************************************************
3761 Utility function to marshall a POSIX acl into wire format.
3762 ****************************************************************************/
3764 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3766 int entry_id = SMB_ACL_FIRST_ENTRY;
3767 SMB_ACL_ENTRY_T entry;
3769 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3770 SMB_ACL_TAG_T tagtype;
3771 SMB_ACL_PERMSET_T permset;
3772 unsigned char perms = 0;
3773 unsigned int own_grp;
3775 /* get_next... */
3776 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3777 entry_id = SMB_ACL_NEXT_ENTRY;
3780 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3781 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3782 return False;
3785 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3786 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3787 return False;
3790 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3791 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3792 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3794 SCVAL(pdata,1,perms);
3796 switch (tagtype) {
3797 case SMB_ACL_USER_OBJ:
3798 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3799 own_grp = (unsigned int)pst->st_ex_uid;
3800 SIVAL(pdata,2,own_grp);
3801 SIVAL(pdata,6,0);
3802 break;
3803 case SMB_ACL_USER:
3805 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3806 if (!puid) {
3807 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3808 return False;
3810 own_grp = (unsigned int)*puid;
3811 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3812 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3813 SIVAL(pdata,2,own_grp);
3814 SIVAL(pdata,6,0);
3815 break;
3817 case SMB_ACL_GROUP_OBJ:
3818 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3819 own_grp = (unsigned int)pst->st_ex_gid;
3820 SIVAL(pdata,2,own_grp);
3821 SIVAL(pdata,6,0);
3822 break;
3823 case SMB_ACL_GROUP:
3825 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3826 if (!pgid) {
3827 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3828 return False;
3830 own_grp = (unsigned int)*pgid;
3831 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3832 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3833 SIVAL(pdata,2,own_grp);
3834 SIVAL(pdata,6,0);
3835 break;
3837 case SMB_ACL_MASK:
3838 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3839 SIVAL(pdata,2,0xFFFFFFFF);
3840 SIVAL(pdata,6,0xFFFFFFFF);
3841 break;
3842 case SMB_ACL_OTHER:
3843 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3844 SIVAL(pdata,2,0xFFFFFFFF);
3845 SIVAL(pdata,6,0xFFFFFFFF);
3846 break;
3847 default:
3848 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3849 return False;
3851 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3854 return True;
3856 #endif
3858 /****************************************************************************
3859 Store the FILE_UNIX_BASIC info.
3860 ****************************************************************************/
3862 static char *store_file_unix_basic(connection_struct *conn,
3863 char *pdata,
3864 files_struct *fsp,
3865 const SMB_STRUCT_STAT *psbuf)
3867 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3868 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3870 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3871 pdata += 8;
3873 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3874 pdata += 8;
3876 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3877 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3878 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3879 pdata += 24;
3881 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3882 SIVAL(pdata,4,0);
3883 pdata += 8;
3885 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3886 SIVAL(pdata,4,0);
3887 pdata += 8;
3889 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3890 pdata += 4;
3892 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3893 SIVAL(pdata,4,0);
3894 pdata += 8;
3896 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3897 SIVAL(pdata,4,0);
3898 pdata += 8;
3900 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3901 pdata += 8;
3903 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3904 SIVAL(pdata,4,0);
3905 pdata += 8;
3907 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3908 SIVAL(pdata,4,0);
3909 pdata += 8;
3911 return pdata;
3914 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3915 * the chflags(2) (or equivalent) flags.
3917 * XXX: this really should be behind the VFS interface. To do this, we would
3918 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3919 * Each VFS module could then implement its own mapping as appropriate for the
3920 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3922 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3923 info2_flags_map[] =
3925 #ifdef UF_NODUMP
3926 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3927 #endif
3929 #ifdef UF_IMMUTABLE
3930 { UF_IMMUTABLE, EXT_IMMUTABLE },
3931 #endif
3933 #ifdef UF_APPEND
3934 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3935 #endif
3937 #ifdef UF_HIDDEN
3938 { UF_HIDDEN, EXT_HIDDEN },
3939 #endif
3941 /* Do not remove. We need to guarantee that this array has at least one
3942 * entry to build on HP-UX.
3944 { 0, 0 }
3948 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3949 uint32 *smb_fflags, uint32 *smb_fmask)
3951 int i;
3953 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3954 *smb_fmask |= info2_flags_map[i].smb_fflag;
3955 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3956 *smb_fflags |= info2_flags_map[i].smb_fflag;
3961 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3962 const uint32 smb_fflags,
3963 const uint32 smb_fmask,
3964 int *stat_fflags)
3966 uint32 max_fmask = 0;
3967 int i;
3969 *stat_fflags = psbuf->st_ex_flags;
3971 /* For each flags requested in smb_fmask, check the state of the
3972 * corresponding flag in smb_fflags and set or clear the matching
3973 * stat flag.
3976 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3977 max_fmask |= info2_flags_map[i].smb_fflag;
3978 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3979 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3980 *stat_fflags |= info2_flags_map[i].stat_fflag;
3981 } else {
3982 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3987 /* If smb_fmask is asking to set any bits that are not supported by
3988 * our flag mappings, we should fail.
3990 if ((smb_fmask & max_fmask) != smb_fmask) {
3991 return False;
3994 return True;
3998 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3999 * of file flags and birth (create) time.
4001 static char *store_file_unix_basic_info2(connection_struct *conn,
4002 char *pdata,
4003 files_struct *fsp,
4004 const SMB_STRUCT_STAT *psbuf)
4006 uint32 file_flags = 0;
4007 uint32 flags_mask = 0;
4009 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4011 /* Create (birth) time 64 bit */
4012 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4013 pdata += 8;
4015 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4016 SIVAL(pdata, 0, file_flags); /* flags */
4017 SIVAL(pdata, 4, flags_mask); /* mask */
4018 pdata += 8;
4020 return pdata;
4023 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4024 const struct stream_struct *streams,
4025 char *data,
4026 unsigned int max_data_bytes,
4027 unsigned int *data_size)
4029 unsigned int i;
4030 unsigned int ofs = 0;
4032 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4033 unsigned int next_offset;
4034 size_t namelen;
4035 smb_ucs2_t *namebuf;
4037 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4038 streams[i].name, &namelen) ||
4039 namelen <= 2)
4041 return NT_STATUS_INVALID_PARAMETER;
4045 * name_buf is now null-terminated, we need to marshall as not
4046 * terminated
4049 namelen -= 2;
4051 SIVAL(data, ofs+4, namelen);
4052 SOFF_T(data, ofs+8, streams[i].size);
4053 SOFF_T(data, ofs+16, streams[i].alloc_size);
4054 memcpy(data+ofs+24, namebuf, namelen);
4055 TALLOC_FREE(namebuf);
4057 next_offset = ofs + 24 + namelen;
4059 if (i == num_streams-1) {
4060 SIVAL(data, ofs, 0);
4062 else {
4063 unsigned int align = ndr_align_size(next_offset, 8);
4065 memset(data+next_offset, 0, align);
4066 next_offset += align;
4068 SIVAL(data, ofs, next_offset - ofs);
4069 ofs = next_offset;
4072 ofs = next_offset;
4075 *data_size = ofs;
4077 return NT_STATUS_OK;
4080 /****************************************************************************
4081 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4082 ****************************************************************************/
4084 static void call_trans2qpipeinfo(connection_struct *conn,
4085 struct smb_request *req,
4086 unsigned int tran_call,
4087 char **pparams, int total_params,
4088 char **ppdata, int total_data,
4089 unsigned int max_data_bytes)
4091 char *params = *pparams;
4092 char *pdata = *ppdata;
4093 unsigned int data_size = 0;
4094 unsigned int param_size = 2;
4095 uint16 info_level;
4096 files_struct *fsp;
4098 if (!params) {
4099 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4100 return;
4103 if (total_params < 4) {
4104 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4105 return;
4108 fsp = file_fsp(req, SVAL(params,0));
4109 if (!fsp_is_np(fsp)) {
4110 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4111 return;
4114 info_level = SVAL(params,2);
4116 *pparams = (char *)SMB_REALLOC(*pparams,2);
4117 if (*pparams == NULL) {
4118 reply_nterror(req, NT_STATUS_NO_MEMORY);
4119 return;
4121 params = *pparams;
4122 SSVAL(params,0,0);
4123 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4124 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4125 if (*ppdata == NULL ) {
4126 reply_nterror(req, NT_STATUS_NO_MEMORY);
4127 return;
4129 pdata = *ppdata;
4131 switch (info_level) {
4132 case SMB_FILE_STANDARD_INFORMATION:
4133 memset(pdata,0,24);
4134 SOFF_T(pdata,0,4096LL);
4135 SIVAL(pdata,16,1);
4136 SIVAL(pdata,20,1);
4137 data_size = 24;
4138 break;
4140 default:
4141 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4142 return;
4145 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4146 max_data_bytes);
4148 return;
4151 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4152 TALLOC_CTX *mem_ctx,
4153 uint16_t info_level,
4154 files_struct *fsp,
4155 struct smb_filename *smb_fname,
4156 bool delete_pending,
4157 struct timespec write_time_ts,
4158 bool ms_dfs_link,
4159 struct ea_list *ea_list,
4160 int lock_data_count,
4161 char *lock_data,
4162 uint16_t flags2,
4163 unsigned int max_data_bytes,
4164 char **ppdata,
4165 unsigned int *pdata_size)
4167 char *pdata = *ppdata;
4168 char *dstart, *dend;
4169 unsigned int data_size;
4170 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4171 time_t create_time, mtime, atime, c_time;
4172 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4173 char *p;
4174 char *base_name;
4175 char *dos_fname;
4176 int mode;
4177 int nlink;
4178 NTSTATUS status;
4179 uint64_t file_size = 0;
4180 uint64_t pos = 0;
4181 uint64_t allocation_size = 0;
4182 uint64_t file_index = 0;
4183 uint32_t access_mask = 0;
4185 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4186 return NT_STATUS_INVALID_LEVEL;
4189 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4190 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4191 info_level, max_data_bytes));
4193 if (ms_dfs_link) {
4194 mode = dos_mode_msdfs(conn, smb_fname);
4195 } else {
4196 mode = dos_mode(conn, smb_fname);
4198 if (!mode)
4199 mode = FILE_ATTRIBUTE_NORMAL;
4201 nlink = psbuf->st_ex_nlink;
4203 if (nlink && (mode&aDIR)) {
4204 nlink = 1;
4207 if ((nlink > 0) && delete_pending) {
4208 nlink -= 1;
4211 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4212 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4213 if (*ppdata == NULL) {
4214 return NT_STATUS_NO_MEMORY;
4216 pdata = *ppdata;
4217 dstart = pdata;
4218 dend = dstart + data_size - 1;
4220 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4221 update_stat_ex_mtime(psbuf, write_time_ts);
4224 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4225 mtime_ts = psbuf->st_ex_mtime;
4226 atime_ts = psbuf->st_ex_atime;
4227 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4229 if (lp_dos_filetime_resolution(SNUM(conn))) {
4230 dos_filetime_timespec(&create_time_ts);
4231 dos_filetime_timespec(&mtime_ts);
4232 dos_filetime_timespec(&atime_ts);
4233 dos_filetime_timespec(&ctime_ts);
4236 create_time = convert_timespec_to_time_t(create_time_ts);
4237 mtime = convert_timespec_to_time_t(mtime_ts);
4238 atime = convert_timespec_to_time_t(atime_ts);
4239 c_time = convert_timespec_to_time_t(ctime_ts);
4241 p = strrchr_m(smb_fname->base_name,'/');
4242 if (!p)
4243 base_name = smb_fname->base_name;
4244 else
4245 base_name = p+1;
4247 /* NT expects the name to be in an exact form of the *full*
4248 filename. See the trans2 torture test */
4249 if (ISDOT(base_name)) {
4250 dos_fname = talloc_strdup(mem_ctx, "\\");
4251 if (!dos_fname) {
4252 return NT_STATUS_NO_MEMORY;
4254 } else {
4255 dos_fname = talloc_asprintf(mem_ctx,
4256 "\\%s",
4257 smb_fname->base_name);
4258 if (!dos_fname) {
4259 return NT_STATUS_NO_MEMORY;
4261 if (is_ntfs_stream_smb_fname(smb_fname)) {
4262 dos_fname = talloc_asprintf(dos_fname, "%s",
4263 smb_fname->stream_name);
4264 if (!dos_fname) {
4265 return NT_STATUS_NO_MEMORY;
4269 string_replace(dos_fname, '/', '\\');
4272 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4274 if (!fsp) {
4275 /* Do we have this path open ? */
4276 files_struct *fsp1;
4277 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4278 fsp1 = file_find_di_first(fileid);
4279 if (fsp1 && fsp1->initial_allocation_size) {
4280 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4284 if (!(mode & aDIR)) {
4285 file_size = get_file_size_stat(psbuf);
4288 if (fsp) {
4289 pos = fsp->fh->position_information;
4292 if (fsp) {
4293 access_mask = fsp->access_mask;
4294 } else {
4295 /* GENERIC_EXECUTE mapping from Windows */
4296 access_mask = 0x12019F;
4299 /* This should be an index number - looks like
4300 dev/ino to me :-)
4302 I think this causes us to fail the IFSKIT
4303 BasicFileInformationTest. -tpot */
4304 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4305 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4307 switch (info_level) {
4308 case SMB_INFO_STANDARD:
4309 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4310 data_size = 22;
4311 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4312 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4313 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4314 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4315 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4316 SSVAL(pdata,l1_attrFile,mode);
4317 break;
4319 case SMB_INFO_QUERY_EA_SIZE:
4321 unsigned int ea_size =
4322 estimate_ea_size(conn, fsp,
4323 smb_fname->base_name);
4324 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4325 data_size = 26;
4326 srv_put_dos_date2(pdata,0,create_time);
4327 srv_put_dos_date2(pdata,4,atime);
4328 srv_put_dos_date2(pdata,8,mtime); /* write time */
4329 SIVAL(pdata,12,(uint32)file_size);
4330 SIVAL(pdata,16,(uint32)allocation_size);
4331 SSVAL(pdata,20,mode);
4332 SIVAL(pdata,22,ea_size);
4333 break;
4336 case SMB_INFO_IS_NAME_VALID:
4337 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4338 if (fsp) {
4339 /* os/2 needs this ? really ?*/
4340 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4342 /* This is only reached for qpathinfo */
4343 data_size = 0;
4344 break;
4346 case SMB_INFO_QUERY_EAS_FROM_LIST:
4348 size_t total_ea_len = 0;
4349 struct ea_list *ea_file_list = NULL;
4351 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4353 ea_file_list =
4354 get_ea_list_from_file(mem_ctx, conn, fsp,
4355 smb_fname->base_name,
4356 &total_ea_len);
4357 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4359 if (!ea_list || (total_ea_len > data_size)) {
4360 data_size = 4;
4361 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4362 break;
4365 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4366 break;
4369 case SMB_INFO_QUERY_ALL_EAS:
4371 /* We have data_size bytes to put EA's into. */
4372 size_t total_ea_len = 0;
4374 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4376 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4377 smb_fname->base_name,
4378 &total_ea_len);
4379 if (!ea_list || (total_ea_len > data_size)) {
4380 data_size = 4;
4381 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4382 break;
4385 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4386 break;
4389 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4391 /* This is FileFullEaInformation - 0xF which maps to
4392 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4394 /* We have data_size bytes to put EA's into. */
4395 size_t total_ea_len = 0;
4396 struct ea_list *ea_file_list = NULL;
4398 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4400 /*TODO: add filtering and index handling */
4402 ea_file_list =
4403 get_ea_list_from_file(mem_ctx, conn, fsp,
4404 smb_fname->base_name,
4405 &total_ea_len);
4406 if (!ea_file_list) {
4407 return NT_STATUS_NO_EAS_ON_FILE;
4410 status = fill_ea_chained_buffer(mem_ctx,
4411 pdata,
4412 data_size,
4413 &data_size,
4414 conn, ea_file_list);
4415 if (!NT_STATUS_IS_OK(status)) {
4416 return status;
4418 break;
4421 case SMB_FILE_BASIC_INFORMATION:
4422 case SMB_QUERY_FILE_BASIC_INFO:
4424 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4425 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4426 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4427 } else {
4428 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4429 data_size = 40;
4430 SIVAL(pdata,36,0);
4432 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4433 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4434 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4435 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4436 SIVAL(pdata,32,mode);
4438 DEBUG(5,("SMB_QFBI - "));
4439 DEBUG(5,("create: %s ", ctime(&create_time)));
4440 DEBUG(5,("access: %s ", ctime(&atime)));
4441 DEBUG(5,("write: %s ", ctime(&mtime)));
4442 DEBUG(5,("change: %s ", ctime(&c_time)));
4443 DEBUG(5,("mode: %x\n", mode));
4444 break;
4446 case SMB_FILE_STANDARD_INFORMATION:
4447 case SMB_QUERY_FILE_STANDARD_INFO:
4449 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4450 data_size = 24;
4451 SOFF_T(pdata,0,allocation_size);
4452 SOFF_T(pdata,8,file_size);
4453 SIVAL(pdata,16,nlink);
4454 SCVAL(pdata,20,delete_pending?1:0);
4455 SCVAL(pdata,21,(mode&aDIR)?1:0);
4456 SSVAL(pdata,22,0); /* Padding. */
4457 break;
4459 case SMB_FILE_EA_INFORMATION:
4460 case SMB_QUERY_FILE_EA_INFO:
4462 unsigned int ea_size =
4463 estimate_ea_size(conn, fsp, smb_fname->base_name);
4464 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4465 data_size = 4;
4466 SIVAL(pdata,0,ea_size);
4467 break;
4470 /* Get the 8.3 name - used if NT SMB was negotiated. */
4471 case SMB_QUERY_FILE_ALT_NAME_INFO:
4472 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4474 int len;
4475 char mangled_name[13];
4476 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4477 if (!name_to_8_3(base_name,mangled_name,
4478 True,conn->params)) {
4479 return NT_STATUS_NO_MEMORY;
4481 len = srvstr_push(dstart, flags2,
4482 pdata+4, mangled_name,
4483 PTR_DIFF(dend, pdata+4),
4484 STR_UNICODE);
4485 data_size = 4 + len;
4486 SIVAL(pdata,0,len);
4487 break;
4490 case SMB_QUERY_FILE_NAME_INFO:
4492 int len;
4494 this must be *exactly* right for ACLs on mapped drives to work
4496 len = srvstr_push(dstart, flags2,
4497 pdata+4, dos_fname,
4498 PTR_DIFF(dend, pdata+4),
4499 STR_UNICODE);
4500 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4501 data_size = 4 + len;
4502 SIVAL(pdata,0,len);
4503 break;
4506 case SMB_FILE_ALLOCATION_INFORMATION:
4507 case SMB_QUERY_FILE_ALLOCATION_INFO:
4508 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4509 data_size = 8;
4510 SOFF_T(pdata,0,allocation_size);
4511 break;
4513 case SMB_FILE_END_OF_FILE_INFORMATION:
4514 case SMB_QUERY_FILE_END_OF_FILEINFO:
4515 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4516 data_size = 8;
4517 SOFF_T(pdata,0,file_size);
4518 break;
4520 case SMB_QUERY_FILE_ALL_INFO:
4521 case SMB_FILE_ALL_INFORMATION:
4523 int len;
4524 unsigned int ea_size =
4525 estimate_ea_size(conn, fsp, smb_fname->base_name);
4526 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4527 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4528 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4529 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4530 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4531 SIVAL(pdata,32,mode);
4532 SIVAL(pdata,36,0); /* padding. */
4533 pdata += 40;
4534 SOFF_T(pdata,0,allocation_size);
4535 SOFF_T(pdata,8,file_size);
4536 SIVAL(pdata,16,nlink);
4537 SCVAL(pdata,20,delete_pending);
4538 SCVAL(pdata,21,(mode&aDIR)?1:0);
4539 SSVAL(pdata,22,0);
4540 pdata += 24;
4541 SIVAL(pdata,0,ea_size);
4542 pdata += 4; /* EA info */
4543 len = srvstr_push(dstart, flags2,
4544 pdata+4, dos_fname,
4545 PTR_DIFF(dend, pdata+4),
4546 STR_UNICODE);
4547 SIVAL(pdata,0,len);
4548 pdata += 4 + len;
4549 data_size = PTR_DIFF(pdata,(*ppdata));
4550 break;
4553 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4555 int len;
4556 unsigned int ea_size =
4557 estimate_ea_size(conn, fsp, smb_fname->base_name);
4558 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4559 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4560 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4561 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4562 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4563 SIVAL(pdata, 0x20, mode);
4564 SIVAL(pdata, 0x24, 0); /* padding. */
4565 SBVAL(pdata, 0x28, allocation_size);
4566 SBVAL(pdata, 0x30, file_size);
4567 SIVAL(pdata, 0x38, nlink);
4568 SCVAL(pdata, 0x3C, delete_pending);
4569 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4570 SSVAL(pdata, 0x3E, 0); /* padding */
4571 SBVAL(pdata, 0x40, file_index);
4572 SIVAL(pdata, 0x48, ea_size);
4573 SIVAL(pdata, 0x4C, access_mask);
4574 SBVAL(pdata, 0x50, pos);
4575 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4576 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4578 pdata += 0x60;
4580 len = srvstr_push(dstart, flags2,
4581 pdata+4, dos_fname,
4582 PTR_DIFF(dend, pdata+4),
4583 STR_UNICODE);
4584 SIVAL(pdata,0,len);
4585 pdata += 4 + len;
4586 data_size = PTR_DIFF(pdata,(*ppdata));
4587 break;
4589 case SMB_FILE_INTERNAL_INFORMATION:
4591 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4592 SBVAL(pdata, 0, file_index);
4593 data_size = 8;
4594 break;
4596 case SMB_FILE_ACCESS_INFORMATION:
4597 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4598 SIVAL(pdata, 0, access_mask);
4599 data_size = 4;
4600 break;
4602 case SMB_FILE_NAME_INFORMATION:
4603 /* Pathname with leading '\'. */
4605 size_t byte_len;
4606 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4607 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4608 SIVAL(pdata,0,byte_len);
4609 data_size = 4 + byte_len;
4610 break;
4613 case SMB_FILE_DISPOSITION_INFORMATION:
4614 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4615 data_size = 1;
4616 SCVAL(pdata,0,delete_pending);
4617 break;
4619 case SMB_FILE_POSITION_INFORMATION:
4620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4621 data_size = 8;
4622 SOFF_T(pdata,0,pos);
4623 break;
4625 case SMB_FILE_MODE_INFORMATION:
4626 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4627 SIVAL(pdata,0,mode);
4628 data_size = 4;
4629 break;
4631 case SMB_FILE_ALIGNMENT_INFORMATION:
4632 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4633 SIVAL(pdata,0,0); /* No alignment needed. */
4634 data_size = 4;
4635 break;
4638 * NT4 server just returns "invalid query" to this - if we try
4639 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4640 * want this. JRA.
4642 /* The first statement above is false - verified using Thursby
4643 * client against NT4 -- gcolley.
4645 case SMB_QUERY_FILE_STREAM_INFO:
4646 case SMB_FILE_STREAM_INFORMATION: {
4647 unsigned int num_streams;
4648 struct stream_struct *streams;
4650 DEBUG(10,("smbd_do_qfilepathinfo: "
4651 "SMB_FILE_STREAM_INFORMATION\n"));
4653 if (is_ntfs_stream_smb_fname(smb_fname)) {
4654 return NT_STATUS_INVALID_PARAMETER;
4657 status = SMB_VFS_STREAMINFO(
4658 conn, fsp, smb_fname->base_name, talloc_tos(),
4659 &num_streams, &streams);
4661 if (!NT_STATUS_IS_OK(status)) {
4662 DEBUG(10, ("could not get stream info: %s\n",
4663 nt_errstr(status)));
4664 return status;
4667 status = marshall_stream_info(num_streams, streams,
4668 pdata, max_data_bytes,
4669 &data_size);
4671 if (!NT_STATUS_IS_OK(status)) {
4672 DEBUG(10, ("marshall_stream_info failed: %s\n",
4673 nt_errstr(status)));
4674 return status;
4677 TALLOC_FREE(streams);
4679 break;
4681 case SMB_QUERY_COMPRESSION_INFO:
4682 case SMB_FILE_COMPRESSION_INFORMATION:
4683 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4684 SOFF_T(pdata,0,file_size);
4685 SIVAL(pdata,8,0); /* ??? */
4686 SIVAL(pdata,12,0); /* ??? */
4687 data_size = 16;
4688 break;
4690 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4691 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4692 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4693 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4694 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4695 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4696 SOFF_T(pdata,32,allocation_size);
4697 SOFF_T(pdata,40,file_size);
4698 SIVAL(pdata,48,mode);
4699 SIVAL(pdata,52,0); /* ??? */
4700 data_size = 56;
4701 break;
4703 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4704 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4705 SIVAL(pdata,0,mode);
4706 SIVAL(pdata,4,0);
4707 data_size = 8;
4708 break;
4711 * CIFS UNIX Extensions.
4714 case SMB_QUERY_FILE_UNIX_BASIC:
4716 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4717 data_size = PTR_DIFF(pdata,(*ppdata));
4720 int i;
4721 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4723 for (i=0; i<100; i++)
4724 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4725 DEBUG(4,("\n"));
4728 break;
4730 case SMB_QUERY_FILE_UNIX_INFO2:
4732 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4733 data_size = PTR_DIFF(pdata,(*ppdata));
4736 int i;
4737 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4739 for (i=0; i<100; i++)
4740 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4741 DEBUG(4,("\n"));
4744 break;
4746 case SMB_QUERY_FILE_UNIX_LINK:
4748 int len;
4749 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4751 if (!buffer) {
4752 return NT_STATUS_NO_MEMORY;
4755 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4756 #ifdef S_ISLNK
4757 if(!S_ISLNK(psbuf->st_ex_mode)) {
4758 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4760 #else
4761 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4762 #endif
4763 len = SMB_VFS_READLINK(conn,
4764 smb_fname->base_name,
4765 buffer, PATH_MAX);
4766 if (len == -1) {
4767 return map_nt_error_from_unix(errno);
4769 buffer[len] = 0;
4770 len = srvstr_push(dstart, flags2,
4771 pdata, buffer,
4772 PTR_DIFF(dend, pdata),
4773 STR_TERMINATE);
4774 pdata += len;
4775 data_size = PTR_DIFF(pdata,(*ppdata));
4777 break;
4780 #if defined(HAVE_POSIX_ACLS)
4781 case SMB_QUERY_POSIX_ACL:
4783 SMB_ACL_T file_acl = NULL;
4784 SMB_ACL_T def_acl = NULL;
4785 uint16 num_file_acls = 0;
4786 uint16 num_def_acls = 0;
4788 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4789 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4790 } else {
4791 file_acl =
4792 SMB_VFS_SYS_ACL_GET_FILE(conn,
4793 smb_fname->base_name,
4794 SMB_ACL_TYPE_ACCESS);
4797 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4798 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4799 "not implemented on "
4800 "filesystem containing %s\n",
4801 smb_fname->base_name));
4802 return NT_STATUS_NOT_IMPLEMENTED;
4805 if (S_ISDIR(psbuf->st_ex_mode)) {
4806 if (fsp && fsp->is_directory) {
4807 def_acl =
4808 SMB_VFS_SYS_ACL_GET_FILE(
4809 conn,
4810 fsp->fsp_name->base_name,
4811 SMB_ACL_TYPE_DEFAULT);
4812 } else {
4813 def_acl =
4814 SMB_VFS_SYS_ACL_GET_FILE(
4815 conn,
4816 smb_fname->base_name,
4817 SMB_ACL_TYPE_DEFAULT);
4819 def_acl = free_empty_sys_acl(conn, def_acl);
4822 num_file_acls = count_acl_entries(conn, file_acl);
4823 num_def_acls = count_acl_entries(conn, def_acl);
4825 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4826 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4827 data_size,
4828 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4829 SMB_POSIX_ACL_HEADER_SIZE) ));
4830 if (file_acl) {
4831 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4833 if (def_acl) {
4834 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4836 return NT_STATUS_BUFFER_TOO_SMALL;
4839 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4840 SSVAL(pdata,2,num_file_acls);
4841 SSVAL(pdata,4,num_def_acls);
4842 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4843 if (file_acl) {
4844 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4846 if (def_acl) {
4847 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4849 return NT_STATUS_INTERNAL_ERROR;
4851 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4852 if (file_acl) {
4853 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4855 if (def_acl) {
4856 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4858 return NT_STATUS_INTERNAL_ERROR;
4861 if (file_acl) {
4862 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4864 if (def_acl) {
4865 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4867 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4868 break;
4870 #endif
4873 case SMB_QUERY_POSIX_LOCK:
4875 uint64_t count;
4876 uint64_t offset;
4877 uint32 lock_pid;
4878 enum brl_type lock_type;
4880 /* We need an open file with a real fd for this. */
4881 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4882 return NT_STATUS_INVALID_LEVEL;
4885 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4886 return NT_STATUS_INVALID_PARAMETER;
4889 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4890 case POSIX_LOCK_TYPE_READ:
4891 lock_type = READ_LOCK;
4892 break;
4893 case POSIX_LOCK_TYPE_WRITE:
4894 lock_type = WRITE_LOCK;
4895 break;
4896 case POSIX_LOCK_TYPE_UNLOCK:
4897 default:
4898 /* There's no point in asking for an unlock... */
4899 return NT_STATUS_INVALID_PARAMETER;
4902 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4903 #if defined(HAVE_LONGLONG)
4904 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4905 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4906 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4907 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4908 #else /* HAVE_LONGLONG */
4909 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4910 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4911 #endif /* HAVE_LONGLONG */
4913 status = query_lock(fsp,
4914 &lock_pid,
4915 &count,
4916 &offset,
4917 &lock_type,
4918 POSIX_LOCK);
4920 if (ERROR_WAS_LOCK_DENIED(status)) {
4921 /* Here we need to report who has it locked... */
4922 data_size = POSIX_LOCK_DATA_SIZE;
4924 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4925 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4926 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4927 #if defined(HAVE_LONGLONG)
4928 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4929 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4930 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4931 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4932 #else /* HAVE_LONGLONG */
4933 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4934 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4935 #endif /* HAVE_LONGLONG */
4937 } else if (NT_STATUS_IS_OK(status)) {
4938 /* For success we just return a copy of what we sent
4939 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4940 data_size = POSIX_LOCK_DATA_SIZE;
4941 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4942 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4943 } else {
4944 return status;
4946 break;
4949 default:
4950 return NT_STATUS_INVALID_LEVEL;
4953 *pdata_size = data_size;
4954 return NT_STATUS_OK;
4957 /****************************************************************************
4958 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4959 file name or file id).
4960 ****************************************************************************/
4962 static void call_trans2qfilepathinfo(connection_struct *conn,
4963 struct smb_request *req,
4964 unsigned int tran_call,
4965 char **pparams, int total_params,
4966 char **ppdata, int total_data,
4967 unsigned int max_data_bytes)
4969 char *params = *pparams;
4970 char *pdata = *ppdata;
4971 uint16 info_level;
4972 unsigned int data_size = 0;
4973 unsigned int param_size = 2;
4974 struct smb_filename *smb_fname = NULL;
4975 bool delete_pending = False;
4976 struct timespec write_time_ts;
4977 files_struct *fsp = NULL;
4978 struct file_id fileid;
4979 struct ea_list *ea_list = NULL;
4980 int lock_data_count = 0;
4981 char *lock_data = NULL;
4982 bool ms_dfs_link = false;
4983 NTSTATUS status = NT_STATUS_OK;
4985 if (!params) {
4986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4987 return;
4990 ZERO_STRUCT(write_time_ts);
4992 if (tran_call == TRANSACT2_QFILEINFO) {
4993 if (total_params < 4) {
4994 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4995 return;
4998 if (IS_IPC(conn)) {
4999 call_trans2qpipeinfo(conn, req, tran_call,
5000 pparams, total_params,
5001 ppdata, total_data,
5002 max_data_bytes);
5003 return;
5006 fsp = file_fsp(req, SVAL(params,0));
5007 info_level = SVAL(params,2);
5009 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5011 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5012 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5013 return;
5016 /* Initial check for valid fsp ptr. */
5017 if (!check_fsp_open(conn, req, fsp)) {
5018 return;
5021 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5022 &smb_fname);
5023 if (!NT_STATUS_IS_OK(status)) {
5024 reply_nterror(req, status);
5025 return;
5028 if(fsp->fake_file_handle) {
5030 * This is actually for the QUOTA_FAKE_FILE --metze
5033 /* We know this name is ok, it's already passed the checks. */
5035 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5037 * This is actually a QFILEINFO on a directory
5038 * handle (returned from an NT SMB). NT5.0 seems
5039 * to do this call. JRA.
5042 if (INFO_LEVEL_IS_UNIX(info_level)) {
5043 /* Always do lstat for UNIX calls. */
5044 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5045 DEBUG(3,("call_trans2qfilepathinfo: "
5046 "SMB_VFS_LSTAT of %s failed "
5047 "(%s)\n",
5048 smb_fname_str_dbg(smb_fname),
5049 strerror(errno)));
5050 reply_nterror(req,
5051 map_nt_error_from_unix(errno));
5052 return;
5054 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5055 DEBUG(3,("call_trans2qfilepathinfo: "
5056 "SMB_VFS_STAT of %s failed (%s)\n",
5057 smb_fname_str_dbg(smb_fname),
5058 strerror(errno)));
5059 reply_nterror(req,
5060 map_nt_error_from_unix(errno));
5061 return;
5064 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5065 get_file_infos(fileid, &delete_pending, &write_time_ts);
5066 } else {
5068 * Original code - this is an open file.
5070 if (!check_fsp(conn, req, fsp)) {
5071 return;
5074 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5075 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5076 fsp->fnum, strerror(errno)));
5077 reply_nterror(req,
5078 map_nt_error_from_unix(errno));
5079 return;
5081 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5082 get_file_infos(fileid, &delete_pending, &write_time_ts);
5085 } else {
5086 char *fname = NULL;
5088 /* qpathinfo */
5089 if (total_params < 7) {
5090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5091 return;
5094 info_level = SVAL(params,0);
5096 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5098 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5099 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5100 return;
5103 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5104 total_params - 6,
5105 STR_TERMINATE, &status);
5106 if (!NT_STATUS_IS_OK(status)) {
5107 reply_nterror(req, status);
5108 return;
5111 status = filename_convert(req,
5112 conn,
5113 req->flags2 & FLAGS2_DFS_PATHNAMES,
5114 fname,
5116 NULL,
5117 &smb_fname);
5118 if (!NT_STATUS_IS_OK(status)) {
5119 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5120 reply_botherror(req,
5121 NT_STATUS_PATH_NOT_COVERED,
5122 ERRSRV, ERRbadpath);
5123 return;
5125 reply_nterror(req, status);
5126 return;
5129 /* If this is a stream, check if there is a delete_pending. */
5130 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5131 && is_ntfs_stream_smb_fname(smb_fname)) {
5132 struct smb_filename *smb_fname_base = NULL;
5134 /* Create an smb_filename with stream_name == NULL. */
5135 status =
5136 create_synthetic_smb_fname(talloc_tos(),
5137 smb_fname->base_name,
5138 NULL, NULL,
5139 &smb_fname_base);
5140 if (!NT_STATUS_IS_OK(status)) {
5141 reply_nterror(req, status);
5142 return;
5145 if (INFO_LEVEL_IS_UNIX(info_level)) {
5146 /* Always do lstat for UNIX calls. */
5147 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5148 DEBUG(3,("call_trans2qfilepathinfo: "
5149 "SMB_VFS_LSTAT of %s failed "
5150 "(%s)\n",
5151 smb_fname_str_dbg(smb_fname_base),
5152 strerror(errno)));
5153 TALLOC_FREE(smb_fname_base);
5154 reply_nterror(req,
5155 map_nt_error_from_unix(errno));
5156 return;
5158 } else {
5159 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5160 DEBUG(3,("call_trans2qfilepathinfo: "
5161 "fileinfo of %s failed "
5162 "(%s)\n",
5163 smb_fname_str_dbg(smb_fname_base),
5164 strerror(errno)));
5165 TALLOC_FREE(smb_fname_base);
5166 reply_nterror(req,
5167 map_nt_error_from_unix(errno));
5168 return;
5172 fileid = vfs_file_id_from_sbuf(conn,
5173 &smb_fname_base->st);
5174 TALLOC_FREE(smb_fname_base);
5175 get_file_infos(fileid, &delete_pending, NULL);
5176 if (delete_pending) {
5177 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5178 return;
5182 if (INFO_LEVEL_IS_UNIX(info_level)) {
5183 /* Always do lstat for UNIX calls. */
5184 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5185 DEBUG(3,("call_trans2qfilepathinfo: "
5186 "SMB_VFS_LSTAT of %s failed (%s)\n",
5187 smb_fname_str_dbg(smb_fname),
5188 strerror(errno)));
5189 reply_nterror(req,
5190 map_nt_error_from_unix(errno));
5191 return;
5194 } else if (!VALID_STAT(smb_fname->st) &&
5195 SMB_VFS_STAT(conn, smb_fname) &&
5196 (info_level != SMB_INFO_IS_NAME_VALID)) {
5197 ms_dfs_link = check_msdfs_link(conn,
5198 smb_fname->base_name,
5199 &smb_fname->st);
5201 if (!ms_dfs_link) {
5202 DEBUG(3,("call_trans2qfilepathinfo: "
5203 "SMB_VFS_STAT of %s failed (%s)\n",
5204 smb_fname_str_dbg(smb_fname),
5205 strerror(errno)));
5206 reply_nterror(req,
5207 map_nt_error_from_unix(errno));
5208 return;
5212 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5213 get_file_infos(fileid, &delete_pending, &write_time_ts);
5214 if (delete_pending) {
5215 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5216 return;
5220 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5221 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5222 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5224 /* Pull out any data sent here before we realloc. */
5225 switch (info_level) {
5226 case SMB_INFO_QUERY_EAS_FROM_LIST:
5228 /* Pull any EA list from the data portion. */
5229 uint32 ea_size;
5231 if (total_data < 4) {
5232 reply_nterror(
5233 req, NT_STATUS_INVALID_PARAMETER);
5234 return;
5236 ea_size = IVAL(pdata,0);
5238 if (total_data > 0 && ea_size != total_data) {
5239 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5240 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5241 reply_nterror(
5242 req, NT_STATUS_INVALID_PARAMETER);
5243 return;
5246 if (!lp_ea_support(SNUM(conn))) {
5247 reply_doserror(req, ERRDOS,
5248 ERReasnotsupported);
5249 return;
5252 /* Pull out the list of names. */
5253 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5254 if (!ea_list) {
5255 reply_nterror(
5256 req, NT_STATUS_INVALID_PARAMETER);
5257 return;
5259 break;
5262 case SMB_QUERY_POSIX_LOCK:
5264 if (fsp == NULL || fsp->fh->fd == -1) {
5265 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5266 return;
5269 if (total_data != POSIX_LOCK_DATA_SIZE) {
5270 reply_nterror(
5271 req, NT_STATUS_INVALID_PARAMETER);
5272 return;
5275 /* Copy the lock range data. */
5276 lock_data = (char *)TALLOC_MEMDUP(
5277 req, pdata, total_data);
5278 if (!lock_data) {
5279 reply_nterror(req, NT_STATUS_NO_MEMORY);
5280 return;
5282 lock_data_count = total_data;
5284 default:
5285 break;
5288 *pparams = (char *)SMB_REALLOC(*pparams,2);
5289 if (*pparams == NULL) {
5290 reply_nterror(req, NT_STATUS_NO_MEMORY);
5291 return;
5293 params = *pparams;
5294 SSVAL(params,0,0);
5297 * draft-leach-cifs-v1-spec-02.txt
5298 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5299 * says:
5301 * The requested information is placed in the Data portion of the
5302 * transaction response. For the information levels greater than 0x100,
5303 * the transaction response has 1 parameter word which should be
5304 * ignored by the client.
5306 * However Windows only follows this rule for the IS_NAME_VALID call.
5308 switch (info_level) {
5309 case SMB_INFO_IS_NAME_VALID:
5310 param_size = 0;
5311 break;
5314 if ((info_level & 0xFF00) == 0xFF00) {
5316 * We use levels that start with 0xFF00
5317 * internally to represent SMB2 specific levels
5319 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5320 return;
5323 status = smbd_do_qfilepathinfo(conn, req, info_level,
5324 fsp, smb_fname,
5325 delete_pending, write_time_ts,
5326 ms_dfs_link, ea_list,
5327 lock_data_count, lock_data,
5328 req->flags2, max_data_bytes,
5329 ppdata, &data_size);
5330 if (!NT_STATUS_IS_OK(status)) {
5331 reply_nterror(req, status);
5332 return;
5335 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5336 max_data_bytes);
5338 return;
5341 /****************************************************************************
5342 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5343 code.
5344 ****************************************************************************/
5346 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5347 connection_struct *conn,
5348 const struct smb_filename *smb_fname_old,
5349 const struct smb_filename *smb_fname_new)
5351 NTSTATUS status = NT_STATUS_OK;
5353 /* source must already exist. */
5354 if (!VALID_STAT(smb_fname_old->st)) {
5355 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5358 /* Disallow if newname already exists. */
5359 if (VALID_STAT(smb_fname_new->st)) {
5360 return NT_STATUS_OBJECT_NAME_COLLISION;
5363 /* No links from a directory. */
5364 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5365 return NT_STATUS_FILE_IS_A_DIRECTORY;
5368 /* Setting a hardlink to/from a stream isn't currently supported. */
5369 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5370 is_ntfs_stream_smb_fname(smb_fname_new)) {
5371 return NT_STATUS_INVALID_PARAMETER;
5374 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5375 smb_fname_old->base_name, smb_fname_new->base_name));
5377 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5378 smb_fname_new->base_name) != 0) {
5379 status = map_nt_error_from_unix(errno);
5380 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5381 nt_errstr(status), smb_fname_old->base_name,
5382 smb_fname_new->base_name));
5384 return status;
5387 /****************************************************************************
5388 Deal with setting the time from any of the setfilepathinfo functions.
5389 ****************************************************************************/
5391 NTSTATUS smb_set_file_time(connection_struct *conn,
5392 files_struct *fsp,
5393 const struct smb_filename *smb_fname,
5394 struct smb_file_time *ft,
5395 bool setting_write_time)
5397 struct smb_filename *smb_fname_base = NULL;
5398 uint32 action =
5399 FILE_NOTIFY_CHANGE_LAST_ACCESS
5400 |FILE_NOTIFY_CHANGE_LAST_WRITE
5401 |FILE_NOTIFY_CHANGE_CREATION;
5402 NTSTATUS status;
5404 if (!VALID_STAT(smb_fname->st)) {
5405 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5408 /* get some defaults (no modifications) if any info is zero or -1. */
5409 if (null_timespec(ft->create_time)) {
5410 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5413 if (null_timespec(ft->atime)) {
5414 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5417 if (null_timespec(ft->mtime)) {
5418 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5421 if (!setting_write_time) {
5422 /* ft->mtime comes from change time, not write time. */
5423 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5426 /* Ensure the resolution is the correct for
5427 * what we can store on this filesystem. */
5429 round_timespec(conn->ts_res, &ft->create_time);
5430 round_timespec(conn->ts_res, &ft->ctime);
5431 round_timespec(conn->ts_res, &ft->atime);
5432 round_timespec(conn->ts_res, &ft->mtime);
5434 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5435 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5436 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5437 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5438 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5439 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5440 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5441 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5443 if (setting_write_time) {
5445 * This was a Windows setfileinfo on an open file.
5446 * NT does this a lot. We also need to
5447 * set the time here, as it can be read by
5448 * FindFirst/FindNext and with the patch for bug #2045
5449 * in smbd/fileio.c it ensures that this timestamp is
5450 * kept sticky even after a write. We save the request
5451 * away and will set it on file close and after a write. JRA.
5454 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5455 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5457 if (fsp != NULL) {
5458 if (fsp->base_fsp) {
5459 set_sticky_write_time_fsp(fsp->base_fsp,
5460 ft->mtime);
5461 } else {
5462 set_sticky_write_time_fsp(fsp, ft->mtime);
5464 } else {
5465 set_sticky_write_time_path(
5466 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5467 ft->mtime);
5471 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5473 /* Always call ntimes on the base, even if a stream was passed in. */
5474 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5475 NULL, &smb_fname->st,
5476 &smb_fname_base);
5477 if (!NT_STATUS_IS_OK(status)) {
5478 return status;
5481 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5482 TALLOC_FREE(smb_fname_base);
5483 return map_nt_error_from_unix(errno);
5485 TALLOC_FREE(smb_fname_base);
5487 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5488 smb_fname->base_name);
5489 return NT_STATUS_OK;
5492 /****************************************************************************
5493 Deal with setting the dosmode from any of the setfilepathinfo functions.
5494 ****************************************************************************/
5496 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5497 const struct smb_filename *smb_fname,
5498 uint32 dosmode)
5500 struct smb_filename *smb_fname_base = NULL;
5501 NTSTATUS status;
5503 if (!VALID_STAT(smb_fname->st)) {
5504 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5507 /* Always operate on the base_name, even if a stream was passed in. */
5508 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5509 NULL, &smb_fname->st,
5510 &smb_fname_base);
5511 if (!NT_STATUS_IS_OK(status)) {
5512 return status;
5515 if (dosmode) {
5516 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5517 dosmode |= aDIR;
5518 } else {
5519 dosmode &= ~aDIR;
5523 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5525 /* check the mode isn't different, before changing it */
5526 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5527 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5528 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5529 (unsigned int)dosmode));
5531 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5532 false)) {
5533 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5534 "%s failed (%s)\n",
5535 smb_fname_str_dbg(smb_fname_base),
5536 strerror(errno)));
5537 status = map_nt_error_from_unix(errno);
5538 goto out;
5541 status = NT_STATUS_OK;
5542 out:
5543 TALLOC_FREE(smb_fname_base);
5544 return status;
5547 /****************************************************************************
5548 Deal with setting the size from any of the setfilepathinfo functions.
5549 ****************************************************************************/
5551 static NTSTATUS smb_set_file_size(connection_struct *conn,
5552 struct smb_request *req,
5553 files_struct *fsp,
5554 const struct smb_filename *smb_fname,
5555 const SMB_STRUCT_STAT *psbuf,
5556 SMB_OFF_T size)
5558 NTSTATUS status = NT_STATUS_OK;
5559 struct smb_filename *smb_fname_tmp = NULL;
5560 files_struct *new_fsp = NULL;
5562 if (!VALID_STAT(*psbuf)) {
5563 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5566 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5568 if (size == get_file_size_stat(psbuf)) {
5569 return NT_STATUS_OK;
5572 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5573 smb_fname_str_dbg(smb_fname), (double)size));
5575 if (fsp && fsp->fh->fd != -1) {
5576 /* Handle based call. */
5577 if (vfs_set_filelen(fsp, size) == -1) {
5578 return map_nt_error_from_unix(errno);
5580 trigger_write_time_update_immediate(fsp);
5581 return NT_STATUS_OK;
5584 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5585 if (!NT_STATUS_IS_OK(status)) {
5586 return status;
5589 smb_fname_tmp->st = *psbuf;
5591 status = SMB_VFS_CREATE_FILE(
5592 conn, /* conn */
5593 req, /* req */
5594 0, /* root_dir_fid */
5595 smb_fname_tmp, /* fname */
5596 FILE_WRITE_ATTRIBUTES, /* access_mask */
5597 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5598 FILE_SHARE_DELETE),
5599 FILE_OPEN, /* create_disposition*/
5600 0, /* create_options */
5601 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5602 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5603 0, /* allocation_size */
5604 NULL, /* sd */
5605 NULL, /* ea_list */
5606 &new_fsp, /* result */
5607 NULL); /* pinfo */
5609 TALLOC_FREE(smb_fname_tmp);
5611 if (!NT_STATUS_IS_OK(status)) {
5612 /* NB. We check for open_was_deferred in the caller. */
5613 return status;
5616 if (vfs_set_filelen(new_fsp, size) == -1) {
5617 status = map_nt_error_from_unix(errno);
5618 close_file(req, new_fsp,NORMAL_CLOSE);
5619 return status;
5622 trigger_write_time_update_immediate(new_fsp);
5623 close_file(req, new_fsp,NORMAL_CLOSE);
5624 return NT_STATUS_OK;
5627 /****************************************************************************
5628 Deal with SMB_INFO_SET_EA.
5629 ****************************************************************************/
5631 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5632 const char *pdata,
5633 int total_data,
5634 files_struct *fsp,
5635 const struct smb_filename *smb_fname)
5637 struct ea_list *ea_list = NULL;
5638 TALLOC_CTX *ctx = NULL;
5639 NTSTATUS status = NT_STATUS_OK;
5641 if (total_data < 10) {
5643 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5644 length. They seem to have no effect. Bug #3212. JRA */
5646 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5647 /* We're done. We only get EA info in this call. */
5648 return NT_STATUS_OK;
5651 return NT_STATUS_INVALID_PARAMETER;
5654 if (IVAL(pdata,0) > total_data) {
5655 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5656 IVAL(pdata,0), (unsigned int)total_data));
5657 return NT_STATUS_INVALID_PARAMETER;
5660 ctx = talloc_tos();
5661 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5662 if (!ea_list) {
5663 return NT_STATUS_INVALID_PARAMETER;
5665 status = set_ea(conn, fsp, smb_fname, ea_list);
5667 return status;
5670 /****************************************************************************
5671 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5672 ****************************************************************************/
5674 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5675 const char *pdata,
5676 int total_data,
5677 files_struct *fsp)
5679 struct ea_list *ea_list = NULL;
5680 NTSTATUS status;
5682 if (!fsp) {
5683 return NT_STATUS_INVALID_HANDLE;
5686 if (!lp_ea_support(SNUM(conn))) {
5687 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5688 "EA's not supported.\n",
5689 (unsigned int)total_data));
5690 return NT_STATUS_EAS_NOT_SUPPORTED;
5693 if (total_data < 10) {
5694 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5695 "too small.\n",
5696 (unsigned int)total_data));
5697 return NT_STATUS_INVALID_PARAMETER;
5700 ea_list = read_nttrans_ea_list(talloc_tos(),
5701 pdata,
5702 total_data);
5704 if (!ea_list) {
5705 return NT_STATUS_INVALID_PARAMETER;
5707 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5709 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5710 smb_fname_str_dbg(fsp->fsp_name),
5711 nt_errstr(status) ));
5713 return status;
5717 /****************************************************************************
5718 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5719 ****************************************************************************/
5721 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5722 const char *pdata,
5723 int total_data,
5724 files_struct *fsp,
5725 const struct smb_filename *smb_fname)
5727 NTSTATUS status = NT_STATUS_OK;
5728 bool delete_on_close;
5729 uint32 dosmode = 0;
5731 if (total_data < 1) {
5732 return NT_STATUS_INVALID_PARAMETER;
5735 if (fsp == NULL) {
5736 return NT_STATUS_INVALID_HANDLE;
5739 delete_on_close = (CVAL(pdata,0) ? True : False);
5740 dosmode = dos_mode(conn, smb_fname);
5742 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5743 "delete_on_close = %u\n",
5744 smb_fname_str_dbg(smb_fname),
5745 (unsigned int)dosmode,
5746 (unsigned int)delete_on_close ));
5748 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5750 if (!NT_STATUS_IS_OK(status)) {
5751 return status;
5754 /* The set is across all open files on this dev/inode pair. */
5755 if (!set_delete_on_close(fsp, delete_on_close,
5756 &conn->server_info->utok)) {
5757 return NT_STATUS_ACCESS_DENIED;
5759 return NT_STATUS_OK;
5762 /****************************************************************************
5763 Deal with SMB_FILE_POSITION_INFORMATION.
5764 ****************************************************************************/
5766 static NTSTATUS smb_file_position_information(connection_struct *conn,
5767 const char *pdata,
5768 int total_data,
5769 files_struct *fsp)
5771 uint64_t position_information;
5773 if (total_data < 8) {
5774 return NT_STATUS_INVALID_PARAMETER;
5777 if (fsp == NULL) {
5778 /* Ignore on pathname based set. */
5779 return NT_STATUS_OK;
5782 position_information = (uint64_t)IVAL(pdata,0);
5783 #ifdef LARGE_SMB_OFF_T
5784 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5785 #else /* LARGE_SMB_OFF_T */
5786 if (IVAL(pdata,4) != 0) {
5787 /* more than 32 bits? */
5788 return NT_STATUS_INVALID_PARAMETER;
5790 #endif /* LARGE_SMB_OFF_T */
5792 DEBUG(10,("smb_file_position_information: Set file position "
5793 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5794 (double)position_information));
5795 fsp->fh->position_information = position_information;
5796 return NT_STATUS_OK;
5799 /****************************************************************************
5800 Deal with SMB_FILE_MODE_INFORMATION.
5801 ****************************************************************************/
5803 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5804 const char *pdata,
5805 int total_data)
5807 uint32 mode;
5809 if (total_data < 4) {
5810 return NT_STATUS_INVALID_PARAMETER;
5812 mode = IVAL(pdata,0);
5813 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5814 return NT_STATUS_INVALID_PARAMETER;
5816 return NT_STATUS_OK;
5819 /****************************************************************************
5820 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5821 ****************************************************************************/
5823 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5824 struct smb_request *req,
5825 const char *pdata,
5826 int total_data,
5827 const struct smb_filename *smb_fname)
5829 char *link_target = NULL;
5830 const char *newname = smb_fname->base_name;
5831 NTSTATUS status = NT_STATUS_OK;
5832 TALLOC_CTX *ctx = talloc_tos();
5834 /* Set a symbolic link. */
5835 /* Don't allow this if follow links is false. */
5837 if (total_data == 0) {
5838 return NT_STATUS_INVALID_PARAMETER;
5841 if (!lp_symlinks(SNUM(conn))) {
5842 return NT_STATUS_ACCESS_DENIED;
5845 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5846 total_data, STR_TERMINATE);
5848 if (!link_target) {
5849 return NT_STATUS_INVALID_PARAMETER;
5852 /* !widelinks forces the target path to be within the share. */
5853 /* This means we can interpret the target as a pathname. */
5854 if (!lp_widelinks(SNUM(conn))) {
5855 char *rel_name = NULL;
5856 char *last_dirp = NULL;
5858 if (*link_target == '/') {
5859 /* No absolute paths allowed. */
5860 return NT_STATUS_ACCESS_DENIED;
5862 rel_name = talloc_strdup(ctx,newname);
5863 if (!rel_name) {
5864 return NT_STATUS_NO_MEMORY;
5866 last_dirp = strrchr_m(rel_name, '/');
5867 if (last_dirp) {
5868 last_dirp[1] = '\0';
5869 } else {
5870 rel_name = talloc_strdup(ctx,"./");
5871 if (!rel_name) {
5872 return NT_STATUS_NO_MEMORY;
5875 rel_name = talloc_asprintf_append(rel_name,
5876 "%s",
5877 link_target);
5878 if (!rel_name) {
5879 return NT_STATUS_NO_MEMORY;
5882 status = check_name(conn, rel_name);
5883 if (!NT_STATUS_IS_OK(status)) {
5884 return status;
5888 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5889 newname, link_target ));
5891 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5892 return map_nt_error_from_unix(errno);
5895 return NT_STATUS_OK;
5898 /****************************************************************************
5899 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5900 ****************************************************************************/
5902 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5903 struct smb_request *req,
5904 const char *pdata, int total_data,
5905 const struct smb_filename *smb_fname_new)
5907 char *oldname = NULL;
5908 struct smb_filename *smb_fname_old = NULL;
5909 TALLOC_CTX *ctx = talloc_tos();
5910 NTSTATUS status = NT_STATUS_OK;
5912 /* Set a hard link. */
5913 if (total_data == 0) {
5914 return NT_STATUS_INVALID_PARAMETER;
5917 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5918 total_data, STR_TERMINATE, &status);
5919 if (!NT_STATUS_IS_OK(status)) {
5920 return status;
5923 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5924 smb_fname_str_dbg(smb_fname_new), oldname));
5926 status = filename_convert(ctx,
5927 conn,
5928 req->flags2 & FLAGS2_DFS_PATHNAMES,
5929 oldname,
5931 NULL,
5932 &smb_fname_old);
5933 if (!NT_STATUS_IS_OK(status)) {
5934 return status;
5937 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5940 /****************************************************************************
5941 Deal with SMB_FILE_RENAME_INFORMATION.
5942 ****************************************************************************/
5944 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5945 struct smb_request *req,
5946 const char *pdata,
5947 int total_data,
5948 files_struct *fsp,
5949 struct smb_filename *smb_fname_src)
5951 bool overwrite;
5952 uint32 root_fid;
5953 uint32 len;
5954 char *newname = NULL;
5955 struct smb_filename *smb_fname_dst = NULL;
5956 bool dest_has_wcard = False;
5957 NTSTATUS status = NT_STATUS_OK;
5958 char *p;
5959 TALLOC_CTX *ctx = talloc_tos();
5961 if (total_data < 13) {
5962 return NT_STATUS_INVALID_PARAMETER;
5965 overwrite = (CVAL(pdata,0) ? True : False);
5966 root_fid = IVAL(pdata,4);
5967 len = IVAL(pdata,8);
5969 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5970 return NT_STATUS_INVALID_PARAMETER;
5973 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5974 len, 0, &status,
5975 &dest_has_wcard);
5976 if (!NT_STATUS_IS_OK(status)) {
5977 return status;
5980 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5981 newname));
5983 status = resolve_dfspath_wcard(ctx, conn,
5984 req->flags2 & FLAGS2_DFS_PATHNAMES,
5985 newname,
5986 &newname,
5987 &dest_has_wcard);
5988 if (!NT_STATUS_IS_OK(status)) {
5989 return status;
5992 /* Check the new name has no '/' characters. */
5993 if (strchr_m(newname, '/')) {
5994 return NT_STATUS_NOT_SUPPORTED;
5997 if (fsp && fsp->base_fsp) {
5998 /* newname must be a stream name. */
5999 if (newname[0] != ':') {
6000 return NT_STATUS_NOT_SUPPORTED;
6003 /* Create an smb_fname to call rename_internals_fsp() with. */
6004 status = create_synthetic_smb_fname(talloc_tos(),
6005 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6006 &smb_fname_dst);
6007 if (!NT_STATUS_IS_OK(status)) {
6008 goto out;
6012 * Set the original last component, since
6013 * rename_internals_fsp() requires it.
6015 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6016 newname);
6017 if (smb_fname_dst->original_lcomp == NULL) {
6018 status = NT_STATUS_NO_MEMORY;
6019 goto out;
6022 } else {
6024 * Build up an smb_fname_dst based on the filename passed in.
6025 * We basically just strip off the last component, and put on
6026 * the newname instead.
6028 char *base_name = NULL;
6030 /* newname must *not* be a stream name. */
6031 if (newname[0] == ':') {
6032 return NT_STATUS_NOT_SUPPORTED;
6036 * Strip off the last component (filename) of the path passed
6037 * in.
6039 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6040 if (!base_name) {
6041 return NT_STATUS_NO_MEMORY;
6043 p = strrchr_m(base_name, '/');
6044 if (p) {
6045 p[1] = '\0';
6046 } else {
6047 base_name = talloc_strdup(ctx, "./");
6048 if (!base_name) {
6049 return NT_STATUS_NO_MEMORY;
6052 /* Append the new name. */
6053 base_name = talloc_asprintf_append(base_name,
6054 "%s",
6055 newname);
6056 if (!base_name) {
6057 return NT_STATUS_NO_MEMORY;
6060 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6061 (UCF_SAVE_LCOMP |
6062 (dest_has_wcard ?
6063 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6064 0)));
6066 /* If an error we expect this to be
6067 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6069 if (!NT_STATUS_IS_OK(status)) {
6070 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6071 status)) {
6072 goto out;
6074 /* Create an smb_fname to call rename_internals_fsp() */
6075 status = create_synthetic_smb_fname(ctx,
6076 base_name, NULL,
6077 NULL,
6078 &smb_fname_dst);
6079 if (!NT_STATUS_IS_OK(status)) {
6080 goto out;
6085 if (fsp) {
6086 DEBUG(10,("smb_file_rename_information: "
6087 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6088 fsp->fnum, fsp_str_dbg(fsp),
6089 smb_fname_str_dbg(smb_fname_dst)));
6090 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6091 overwrite);
6092 } else {
6093 DEBUG(10,("smb_file_rename_information: "
6094 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6095 smb_fname_str_dbg(smb_fname_src),
6096 smb_fname_str_dbg(smb_fname_dst)));
6097 status = rename_internals(ctx, conn, req, smb_fname_src,
6098 smb_fname_dst, 0, overwrite, false,
6099 dest_has_wcard,
6100 FILE_WRITE_ATTRIBUTES);
6102 out:
6103 TALLOC_FREE(smb_fname_dst);
6104 return status;
6107 /****************************************************************************
6108 Deal with SMB_SET_POSIX_ACL.
6109 ****************************************************************************/
6111 #if defined(HAVE_POSIX_ACLS)
6112 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6113 const char *pdata,
6114 int total_data,
6115 files_struct *fsp,
6116 const struct smb_filename *smb_fname)
6118 uint16 posix_acl_version;
6119 uint16 num_file_acls;
6120 uint16 num_def_acls;
6121 bool valid_file_acls = True;
6122 bool valid_def_acls = True;
6124 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6125 return NT_STATUS_INVALID_PARAMETER;
6127 posix_acl_version = SVAL(pdata,0);
6128 num_file_acls = SVAL(pdata,2);
6129 num_def_acls = SVAL(pdata,4);
6131 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6132 valid_file_acls = False;
6133 num_file_acls = 0;
6136 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6137 valid_def_acls = False;
6138 num_def_acls = 0;
6141 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6142 return NT_STATUS_INVALID_PARAMETER;
6145 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6146 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6147 return NT_STATUS_INVALID_PARAMETER;
6150 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6151 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6152 (unsigned int)num_file_acls,
6153 (unsigned int)num_def_acls));
6155 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6156 smb_fname->base_name, num_file_acls,
6157 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6158 return map_nt_error_from_unix(errno);
6161 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6162 smb_fname->base_name, &smb_fname->st, num_def_acls,
6163 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6164 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6165 return map_nt_error_from_unix(errno);
6167 return NT_STATUS_OK;
6169 #endif
6171 /****************************************************************************
6172 Deal with SMB_SET_POSIX_LOCK.
6173 ****************************************************************************/
6175 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6176 struct smb_request *req,
6177 const char *pdata,
6178 int total_data,
6179 files_struct *fsp)
6181 uint64_t count;
6182 uint64_t offset;
6183 uint32 lock_pid;
6184 bool blocking_lock = False;
6185 enum brl_type lock_type;
6187 NTSTATUS status = NT_STATUS_OK;
6189 if (fsp == NULL || fsp->fh->fd == -1) {
6190 return NT_STATUS_INVALID_HANDLE;
6193 if (total_data != POSIX_LOCK_DATA_SIZE) {
6194 return NT_STATUS_INVALID_PARAMETER;
6197 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6198 case POSIX_LOCK_TYPE_READ:
6199 lock_type = READ_LOCK;
6200 break;
6201 case POSIX_LOCK_TYPE_WRITE:
6202 /* Return the right POSIX-mappable error code for files opened read-only. */
6203 if (!fsp->can_write) {
6204 return NT_STATUS_INVALID_HANDLE;
6206 lock_type = WRITE_LOCK;
6207 break;
6208 case POSIX_LOCK_TYPE_UNLOCK:
6209 lock_type = UNLOCK_LOCK;
6210 break;
6211 default:
6212 return NT_STATUS_INVALID_PARAMETER;
6215 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6216 blocking_lock = False;
6217 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6218 blocking_lock = True;
6219 } else {
6220 return NT_STATUS_INVALID_PARAMETER;
6223 if (!lp_blocking_locks(SNUM(conn))) {
6224 blocking_lock = False;
6227 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6228 #if defined(HAVE_LONGLONG)
6229 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6230 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6231 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6232 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6233 #else /* HAVE_LONGLONG */
6234 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6235 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6236 #endif /* HAVE_LONGLONG */
6238 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6239 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6240 fsp_str_dbg(fsp),
6241 (unsigned int)lock_type,
6242 (unsigned int)lock_pid,
6243 (double)count,
6244 (double)offset ));
6246 if (lock_type == UNLOCK_LOCK) {
6247 status = do_unlock(smbd_messaging_context(),
6248 fsp,
6249 lock_pid,
6250 count,
6251 offset,
6252 POSIX_LOCK);
6253 } else {
6254 uint32 block_smbpid;
6256 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6257 fsp,
6258 lock_pid,
6259 count,
6260 offset,
6261 lock_type,
6262 POSIX_LOCK,
6263 blocking_lock,
6264 &status,
6265 &block_smbpid,
6266 NULL);
6268 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6270 * A blocking lock was requested. Package up
6271 * this smb into a queued request and push it
6272 * onto the blocking lock queue.
6274 if(push_blocking_lock_request(br_lck,
6275 req,
6276 fsp,
6277 -1, /* infinite timeout. */
6279 lock_pid,
6280 lock_type,
6281 POSIX_LOCK,
6282 offset,
6283 count,
6284 block_smbpid)) {
6285 TALLOC_FREE(br_lck);
6286 return status;
6289 TALLOC_FREE(br_lck);
6292 return status;
6295 /****************************************************************************
6296 Deal with SMB_SET_FILE_BASIC_INFO.
6297 ****************************************************************************/
6299 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6300 const char *pdata,
6301 int total_data,
6302 files_struct *fsp,
6303 const struct smb_filename *smb_fname)
6305 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6306 struct smb_file_time ft;
6307 uint32 dosmode = 0;
6308 NTSTATUS status = NT_STATUS_OK;
6310 ZERO_STRUCT(ft);
6312 if (total_data < 36) {
6313 return NT_STATUS_INVALID_PARAMETER;
6316 /* Set the attributes */
6317 dosmode = IVAL(pdata,32);
6318 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6319 if (!NT_STATUS_IS_OK(status)) {
6320 return status;
6323 /* create time */
6324 ft.create_time = interpret_long_date(pdata);
6326 /* access time */
6327 ft.atime = interpret_long_date(pdata+8);
6329 /* write time. */
6330 ft.mtime = interpret_long_date(pdata+16);
6332 /* change time. */
6333 ft.ctime = interpret_long_date(pdata+24);
6335 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6336 smb_fname_str_dbg(smb_fname)));
6338 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6339 true);
6342 /****************************************************************************
6343 Deal with SMB_INFO_STANDARD.
6344 ****************************************************************************/
6346 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6347 const char *pdata,
6348 int total_data,
6349 files_struct *fsp,
6350 const struct smb_filename *smb_fname)
6352 struct smb_file_time ft;
6354 ZERO_STRUCT(ft);
6356 if (total_data < 12) {
6357 return NT_STATUS_INVALID_PARAMETER;
6360 /* create time */
6361 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6362 /* access time */
6363 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6364 /* write time */
6365 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6367 DEBUG(10,("smb_set_info_standard: file %s\n",
6368 smb_fname_str_dbg(smb_fname)));
6370 return smb_set_file_time(conn,
6371 fsp,
6372 smb_fname,
6373 &ft,
6374 true);
6377 /****************************************************************************
6378 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6379 ****************************************************************************/
6381 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6382 struct smb_request *req,
6383 const char *pdata,
6384 int total_data,
6385 files_struct *fsp,
6386 struct smb_filename *smb_fname)
6388 uint64_t allocation_size = 0;
6389 NTSTATUS status = NT_STATUS_OK;
6390 files_struct *new_fsp = NULL;
6392 if (!VALID_STAT(smb_fname->st)) {
6393 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6396 if (total_data < 8) {
6397 return NT_STATUS_INVALID_PARAMETER;
6400 allocation_size = (uint64_t)IVAL(pdata,0);
6401 #ifdef LARGE_SMB_OFF_T
6402 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6403 #else /* LARGE_SMB_OFF_T */
6404 if (IVAL(pdata,4) != 0) {
6405 /* more than 32 bits? */
6406 return NT_STATUS_INVALID_PARAMETER;
6408 #endif /* LARGE_SMB_OFF_T */
6410 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6411 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6412 (double)allocation_size));
6414 if (allocation_size) {
6415 allocation_size = smb_roundup(conn, allocation_size);
6418 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6419 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6420 (double)allocation_size));
6422 if (fsp && fsp->fh->fd != -1) {
6423 /* Open file handle. */
6424 /* Only change if needed. */
6425 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6426 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6427 return map_nt_error_from_unix(errno);
6430 /* But always update the time. */
6432 * This is equivalent to a write. Ensure it's seen immediately
6433 * if there are no pending writes.
6435 trigger_write_time_update_immediate(fsp);
6436 return NT_STATUS_OK;
6439 /* Pathname or stat or directory file. */
6440 status = SMB_VFS_CREATE_FILE(
6441 conn, /* conn */
6442 req, /* req */
6443 0, /* root_dir_fid */
6444 smb_fname, /* fname */
6445 FILE_WRITE_DATA, /* access_mask */
6446 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6447 FILE_SHARE_DELETE),
6448 FILE_OPEN, /* create_disposition*/
6449 0, /* create_options */
6450 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6451 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6452 0, /* allocation_size */
6453 NULL, /* sd */
6454 NULL, /* ea_list */
6455 &new_fsp, /* result */
6456 NULL); /* pinfo */
6458 if (!NT_STATUS_IS_OK(status)) {
6459 /* NB. We check for open_was_deferred in the caller. */
6460 return status;
6463 /* Only change if needed. */
6464 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6465 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6466 status = map_nt_error_from_unix(errno);
6467 close_file(req, new_fsp, NORMAL_CLOSE);
6468 return status;
6472 /* Changing the allocation size should set the last mod time. */
6474 * This is equivalent to a write. Ensure it's seen immediately
6475 * if there are no pending writes.
6477 trigger_write_time_update_immediate(new_fsp);
6479 close_file(req, new_fsp, NORMAL_CLOSE);
6480 return NT_STATUS_OK;
6483 /****************************************************************************
6484 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6485 ****************************************************************************/
6487 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6488 struct smb_request *req,
6489 const char *pdata,
6490 int total_data,
6491 files_struct *fsp,
6492 const struct smb_filename *smb_fname)
6494 SMB_OFF_T size;
6496 if (total_data < 8) {
6497 return NT_STATUS_INVALID_PARAMETER;
6500 size = IVAL(pdata,0);
6501 #ifdef LARGE_SMB_OFF_T
6502 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6503 #else /* LARGE_SMB_OFF_T */
6504 if (IVAL(pdata,4) != 0) {
6505 /* more than 32 bits? */
6506 return NT_STATUS_INVALID_PARAMETER;
6508 #endif /* LARGE_SMB_OFF_T */
6509 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6510 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6511 (double)size));
6513 return smb_set_file_size(conn, req,
6514 fsp,
6515 smb_fname,
6516 &smb_fname->st,
6517 size);
6520 /****************************************************************************
6521 Allow a UNIX info mknod.
6522 ****************************************************************************/
6524 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6525 const char *pdata,
6526 int total_data,
6527 const struct smb_filename *smb_fname)
6529 uint32 file_type = IVAL(pdata,56);
6530 #if defined(HAVE_MAKEDEV)
6531 uint32 dev_major = IVAL(pdata,60);
6532 uint32 dev_minor = IVAL(pdata,68);
6533 #endif
6534 SMB_DEV_T dev = (SMB_DEV_T)0;
6535 uint32 raw_unixmode = IVAL(pdata,84);
6536 NTSTATUS status;
6537 mode_t unixmode;
6539 if (total_data < 100) {
6540 return NT_STATUS_INVALID_PARAMETER;
6543 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6544 PERM_NEW_FILE, &unixmode);
6545 if (!NT_STATUS_IS_OK(status)) {
6546 return status;
6549 #if defined(HAVE_MAKEDEV)
6550 dev = makedev(dev_major, dev_minor);
6551 #endif
6553 switch (file_type) {
6554 #if defined(S_IFIFO)
6555 case UNIX_TYPE_FIFO:
6556 unixmode |= S_IFIFO;
6557 break;
6558 #endif
6559 #if defined(S_IFSOCK)
6560 case UNIX_TYPE_SOCKET:
6561 unixmode |= S_IFSOCK;
6562 break;
6563 #endif
6564 #if defined(S_IFCHR)
6565 case UNIX_TYPE_CHARDEV:
6566 unixmode |= S_IFCHR;
6567 break;
6568 #endif
6569 #if defined(S_IFBLK)
6570 case UNIX_TYPE_BLKDEV:
6571 unixmode |= S_IFBLK;
6572 break;
6573 #endif
6574 default:
6575 return NT_STATUS_INVALID_PARAMETER;
6578 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6579 "%.0f mode 0%o for file %s\n", (double)dev,
6580 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6582 /* Ok - do the mknod. */
6583 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6584 return map_nt_error_from_unix(errno);
6587 /* If any of the other "set" calls fail we
6588 * don't want to end up with a half-constructed mknod.
6591 if (lp_inherit_perms(SNUM(conn))) {
6592 char *parent;
6593 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6594 &parent, NULL)) {
6595 return NT_STATUS_NO_MEMORY;
6597 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6598 unixmode);
6599 TALLOC_FREE(parent);
6602 return NT_STATUS_OK;
6605 /****************************************************************************
6606 Deal with SMB_SET_FILE_UNIX_BASIC.
6607 ****************************************************************************/
6609 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6610 struct smb_request *req,
6611 const char *pdata,
6612 int total_data,
6613 files_struct *fsp,
6614 const struct smb_filename *smb_fname)
6616 struct smb_file_time ft;
6617 uint32 raw_unixmode;
6618 mode_t unixmode;
6619 SMB_OFF_T size = 0;
6620 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6621 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6622 NTSTATUS status = NT_STATUS_OK;
6623 bool delete_on_fail = False;
6624 enum perm_type ptype;
6625 files_struct *all_fsps = NULL;
6626 bool modify_mtime = true;
6627 struct file_id id;
6628 SMB_STRUCT_STAT sbuf;
6630 ZERO_STRUCT(ft);
6632 if (total_data < 100) {
6633 return NT_STATUS_INVALID_PARAMETER;
6636 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6637 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6638 size=IVAL(pdata,0); /* first 8 Bytes are size */
6639 #ifdef LARGE_SMB_OFF_T
6640 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6641 #else /* LARGE_SMB_OFF_T */
6642 if (IVAL(pdata,4) != 0) {
6643 /* more than 32 bits? */
6644 return NT_STATUS_INVALID_PARAMETER;
6646 #endif /* LARGE_SMB_OFF_T */
6649 ft.atime = interpret_long_date(pdata+24); /* access_time */
6650 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6651 set_owner = (uid_t)IVAL(pdata,40);
6652 set_grp = (gid_t)IVAL(pdata,48);
6653 raw_unixmode = IVAL(pdata,84);
6655 if (VALID_STAT(smb_fname->st)) {
6656 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6657 ptype = PERM_EXISTING_DIR;
6658 } else {
6659 ptype = PERM_EXISTING_FILE;
6661 } else {
6662 ptype = PERM_NEW_FILE;
6665 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6666 ptype, &unixmode);
6667 if (!NT_STATUS_IS_OK(status)) {
6668 return status;
6671 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6672 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6673 smb_fname_str_dbg(smb_fname), (double)size,
6674 (unsigned int)set_owner, (unsigned int)set_grp,
6675 (int)raw_unixmode));
6677 sbuf = smb_fname->st;
6679 if (!VALID_STAT(sbuf)) {
6680 struct smb_filename *smb_fname_tmp = NULL;
6682 * The only valid use of this is to create character and block
6683 * devices, and named pipes. This is deprecated (IMHO) and
6684 * a new info level should be used for mknod. JRA.
6687 status = smb_unix_mknod(conn,
6688 pdata,
6689 total_data,
6690 smb_fname);
6691 if (!NT_STATUS_IS_OK(status)) {
6692 return status;
6695 status = copy_smb_filename(talloc_tos(), smb_fname,
6696 &smb_fname_tmp);
6697 if (!NT_STATUS_IS_OK(status)) {
6698 return status;
6701 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6702 status = map_nt_error_from_unix(errno);
6703 TALLOC_FREE(smb_fname_tmp);
6704 SMB_VFS_UNLINK(conn, smb_fname);
6705 return status;
6708 sbuf = smb_fname_tmp->st;
6709 TALLOC_FREE(smb_fname_tmp);
6711 /* Ensure we don't try and change anything else. */
6712 raw_unixmode = SMB_MODE_NO_CHANGE;
6713 size = get_file_size_stat(&sbuf);
6714 ft.atime = sbuf.st_ex_atime;
6715 ft.mtime = sbuf.st_ex_mtime;
6717 * We continue here as we might want to change the
6718 * owner uid/gid.
6720 delete_on_fail = True;
6723 #if 1
6724 /* Horrible backwards compatibility hack as an old server bug
6725 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6726 * */
6728 if (!size) {
6729 size = get_file_size_stat(&sbuf);
6731 #endif
6734 * Deal with the UNIX specific mode set.
6737 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6738 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6739 "setting mode 0%o for file %s\n",
6740 (unsigned int)unixmode,
6741 smb_fname_str_dbg(smb_fname)));
6742 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6743 return map_nt_error_from_unix(errno);
6748 * Deal with the UNIX specific uid set.
6751 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6752 (sbuf.st_ex_uid != set_owner)) {
6753 int ret;
6755 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6756 "changing owner %u for path %s\n",
6757 (unsigned int)set_owner,
6758 smb_fname_str_dbg(smb_fname)));
6760 if (S_ISLNK(sbuf.st_ex_mode)) {
6761 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6762 set_owner, (gid_t)-1);
6763 } else {
6764 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6765 set_owner, (gid_t)-1);
6768 if (ret != 0) {
6769 status = map_nt_error_from_unix(errno);
6770 if (delete_on_fail) {
6771 SMB_VFS_UNLINK(conn, smb_fname);
6773 return status;
6778 * Deal with the UNIX specific gid set.
6781 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6782 (sbuf.st_ex_gid != set_grp)) {
6783 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6784 "changing group %u for file %s\n",
6785 (unsigned int)set_owner,
6786 smb_fname_str_dbg(smb_fname)));
6787 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6788 set_grp) != 0) {
6789 status = map_nt_error_from_unix(errno);
6790 if (delete_on_fail) {
6791 SMB_VFS_UNLINK(conn, smb_fname);
6793 return status;
6797 /* Deal with any size changes. */
6799 status = smb_set_file_size(conn, req,
6800 fsp,
6801 smb_fname,
6802 &sbuf,
6803 size);
6804 if (!NT_STATUS_IS_OK(status)) {
6805 return status;
6808 /* Deal with any time changes. */
6809 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6810 /* No change, don't cancel anything. */
6811 return status;
6814 id = vfs_file_id_from_sbuf(conn, &sbuf);
6815 for(all_fsps = file_find_di_first(id); all_fsps;
6816 all_fsps = file_find_di_next(all_fsps)) {
6818 * We're setting the time explicitly for UNIX.
6819 * Cancel any pending changes over all handles.
6821 all_fsps->update_write_time_on_close = false;
6822 TALLOC_FREE(all_fsps->update_write_time_event);
6826 * Override the "setting_write_time"
6827 * parameter here as it almost does what
6828 * we need. Just remember if we modified
6829 * mtime and send the notify ourselves.
6831 if (null_timespec(ft.mtime)) {
6832 modify_mtime = false;
6835 status = smb_set_file_time(conn,
6836 fsp,
6837 smb_fname,
6838 &ft,
6839 false);
6840 if (modify_mtime) {
6841 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6842 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6844 return status;
6847 /****************************************************************************
6848 Deal with SMB_SET_FILE_UNIX_INFO2.
6849 ****************************************************************************/
6851 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6852 struct smb_request *req,
6853 const char *pdata,
6854 int total_data,
6855 files_struct *fsp,
6856 const struct smb_filename *smb_fname)
6858 NTSTATUS status;
6859 uint32 smb_fflags;
6860 uint32 smb_fmask;
6862 if (total_data < 116) {
6863 return NT_STATUS_INVALID_PARAMETER;
6866 /* Start by setting all the fields that are common between UNIX_BASIC
6867 * and UNIX_INFO2.
6869 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6870 fsp, smb_fname);
6871 if (!NT_STATUS_IS_OK(status)) {
6872 return status;
6875 smb_fflags = IVAL(pdata, 108);
6876 smb_fmask = IVAL(pdata, 112);
6878 /* NB: We should only attempt to alter the file flags if the client
6879 * sends a non-zero mask.
6881 if (smb_fmask != 0) {
6882 int stat_fflags = 0;
6884 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6885 smb_fmask, &stat_fflags)) {
6886 /* Client asked to alter a flag we don't understand. */
6887 return NT_STATUS_INVALID_PARAMETER;
6890 if (fsp && fsp->fh->fd != -1) {
6891 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6892 return NT_STATUS_NOT_SUPPORTED;
6893 } else {
6894 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6895 stat_fflags) != 0) {
6896 return map_nt_error_from_unix(errno);
6901 /* XXX: need to add support for changing the create_time here. You
6902 * can do this for paths on Darwin with setattrlist(2). The right way
6903 * to hook this up is probably by extending the VFS utimes interface.
6906 return NT_STATUS_OK;
6909 /****************************************************************************
6910 Create a directory with POSIX semantics.
6911 ****************************************************************************/
6913 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6914 struct smb_request *req,
6915 char **ppdata,
6916 int total_data,
6917 struct smb_filename *smb_fname,
6918 int *pdata_return_size)
6920 NTSTATUS status = NT_STATUS_OK;
6921 uint32 raw_unixmode = 0;
6922 uint32 mod_unixmode = 0;
6923 mode_t unixmode = (mode_t)0;
6924 files_struct *fsp = NULL;
6925 uint16 info_level_return = 0;
6926 int info;
6927 char *pdata = *ppdata;
6929 if (total_data < 18) {
6930 return NT_STATUS_INVALID_PARAMETER;
6933 raw_unixmode = IVAL(pdata,8);
6934 /* Next 4 bytes are not yet defined. */
6936 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6937 PERM_NEW_DIR, &unixmode);
6938 if (!NT_STATUS_IS_OK(status)) {
6939 return status;
6942 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6944 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6945 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6947 status = SMB_VFS_CREATE_FILE(
6948 conn, /* conn */
6949 req, /* req */
6950 0, /* root_dir_fid */
6951 smb_fname, /* fname */
6952 FILE_READ_ATTRIBUTES, /* access_mask */
6953 FILE_SHARE_NONE, /* share_access */
6954 FILE_CREATE, /* create_disposition*/
6955 FILE_DIRECTORY_FILE, /* create_options */
6956 mod_unixmode, /* file_attributes */
6957 0, /* oplock_request */
6958 0, /* allocation_size */
6959 NULL, /* sd */
6960 NULL, /* ea_list */
6961 &fsp, /* result */
6962 &info); /* pinfo */
6964 if (NT_STATUS_IS_OK(status)) {
6965 close_file(req, fsp, NORMAL_CLOSE);
6968 info_level_return = SVAL(pdata,16);
6970 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6971 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6972 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6973 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6974 } else {
6975 *pdata_return_size = 12;
6978 /* Realloc the data size */
6979 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6980 if (*ppdata == NULL) {
6981 *pdata_return_size = 0;
6982 return NT_STATUS_NO_MEMORY;
6984 pdata = *ppdata;
6986 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6987 SSVAL(pdata,2,0); /* No fnum. */
6988 SIVAL(pdata,4,info); /* Was directory created. */
6990 switch (info_level_return) {
6991 case SMB_QUERY_FILE_UNIX_BASIC:
6992 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6993 SSVAL(pdata,10,0); /* Padding. */
6994 store_file_unix_basic(conn, pdata + 12, fsp,
6995 &smb_fname->st);
6996 break;
6997 case SMB_QUERY_FILE_UNIX_INFO2:
6998 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6999 SSVAL(pdata,10,0); /* Padding. */
7000 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7001 &smb_fname->st);
7002 break;
7003 default:
7004 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7005 SSVAL(pdata,10,0); /* Padding. */
7006 break;
7009 return status;
7012 /****************************************************************************
7013 Open/Create a file with POSIX semantics.
7014 ****************************************************************************/
7016 static NTSTATUS smb_posix_open(connection_struct *conn,
7017 struct smb_request *req,
7018 char **ppdata,
7019 int total_data,
7020 struct smb_filename *smb_fname,
7021 int *pdata_return_size)
7023 bool extended_oplock_granted = False;
7024 char *pdata = *ppdata;
7025 uint32 flags = 0;
7026 uint32 wire_open_mode = 0;
7027 uint32 raw_unixmode = 0;
7028 uint32 mod_unixmode = 0;
7029 uint32 create_disp = 0;
7030 uint32 access_mask = 0;
7031 uint32 create_options = 0;
7032 NTSTATUS status = NT_STATUS_OK;
7033 mode_t unixmode = (mode_t)0;
7034 files_struct *fsp = NULL;
7035 int oplock_request = 0;
7036 int info = 0;
7037 uint16 info_level_return = 0;
7039 if (total_data < 18) {
7040 return NT_STATUS_INVALID_PARAMETER;
7043 flags = IVAL(pdata,0);
7044 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7045 if (oplock_request) {
7046 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7049 wire_open_mode = IVAL(pdata,4);
7051 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7052 return smb_posix_mkdir(conn, req,
7053 ppdata,
7054 total_data,
7055 smb_fname,
7056 pdata_return_size);
7059 switch (wire_open_mode & SMB_ACCMODE) {
7060 case SMB_O_RDONLY:
7061 access_mask = FILE_READ_DATA;
7062 break;
7063 case SMB_O_WRONLY:
7064 access_mask = FILE_WRITE_DATA;
7065 break;
7066 case SMB_O_RDWR:
7067 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7068 break;
7069 default:
7070 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7071 (unsigned int)wire_open_mode ));
7072 return NT_STATUS_INVALID_PARAMETER;
7075 wire_open_mode &= ~SMB_ACCMODE;
7077 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7078 create_disp = FILE_CREATE;
7079 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7080 create_disp = FILE_OVERWRITE_IF;
7081 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7082 create_disp = FILE_OPEN_IF;
7083 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7084 create_disp = FILE_OPEN;
7085 } else {
7086 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7087 (unsigned int)wire_open_mode ));
7088 return NT_STATUS_INVALID_PARAMETER;
7091 raw_unixmode = IVAL(pdata,8);
7092 /* Next 4 bytes are not yet defined. */
7094 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7095 (VALID_STAT(smb_fname->st) ?
7096 PERM_EXISTING_FILE : PERM_NEW_FILE),
7097 &unixmode);
7099 if (!NT_STATUS_IS_OK(status)) {
7100 return status;
7103 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7105 if (wire_open_mode & SMB_O_SYNC) {
7106 create_options |= FILE_WRITE_THROUGH;
7108 if (wire_open_mode & SMB_O_APPEND) {
7109 access_mask |= FILE_APPEND_DATA;
7111 if (wire_open_mode & SMB_O_DIRECT) {
7112 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7115 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7116 smb_fname_str_dbg(smb_fname),
7117 (unsigned int)wire_open_mode,
7118 (unsigned int)unixmode ));
7120 status = SMB_VFS_CREATE_FILE(
7121 conn, /* conn */
7122 req, /* req */
7123 0, /* root_dir_fid */
7124 smb_fname, /* fname */
7125 access_mask, /* access_mask */
7126 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7127 FILE_SHARE_DELETE),
7128 create_disp, /* create_disposition*/
7129 FILE_NON_DIRECTORY_FILE, /* create_options */
7130 mod_unixmode, /* file_attributes */
7131 oplock_request, /* oplock_request */
7132 0, /* allocation_size */
7133 NULL, /* sd */
7134 NULL, /* ea_list */
7135 &fsp, /* result */
7136 &info); /* pinfo */
7138 if (!NT_STATUS_IS_OK(status)) {
7139 return status;
7142 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7143 extended_oplock_granted = True;
7146 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7147 extended_oplock_granted = True;
7150 info_level_return = SVAL(pdata,16);
7152 /* Allocate the correct return size. */
7154 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7155 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7156 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7157 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7158 } else {
7159 *pdata_return_size = 12;
7162 /* Realloc the data size */
7163 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7164 if (*ppdata == NULL) {
7165 close_file(req, fsp, ERROR_CLOSE);
7166 *pdata_return_size = 0;
7167 return NT_STATUS_NO_MEMORY;
7169 pdata = *ppdata;
7171 if (extended_oplock_granted) {
7172 if (flags & REQUEST_BATCH_OPLOCK) {
7173 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7174 } else {
7175 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7177 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7178 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7179 } else {
7180 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7183 SSVAL(pdata,2,fsp->fnum);
7184 SIVAL(pdata,4,info); /* Was file created etc. */
7186 switch (info_level_return) {
7187 case SMB_QUERY_FILE_UNIX_BASIC:
7188 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7189 SSVAL(pdata,10,0); /* padding. */
7190 store_file_unix_basic(conn, pdata + 12, fsp,
7191 &smb_fname->st);
7192 break;
7193 case SMB_QUERY_FILE_UNIX_INFO2:
7194 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7195 SSVAL(pdata,10,0); /* padding. */
7196 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7197 &smb_fname->st);
7198 break;
7199 default:
7200 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7201 SSVAL(pdata,10,0); /* padding. */
7202 break;
7204 return NT_STATUS_OK;
7207 /****************************************************************************
7208 Delete a file with POSIX semantics.
7209 ****************************************************************************/
7211 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7212 struct smb_request *req,
7213 const char *pdata,
7214 int total_data,
7215 struct smb_filename *smb_fname)
7217 NTSTATUS status = NT_STATUS_OK;
7218 files_struct *fsp = NULL;
7219 uint16 flags = 0;
7220 char del = 1;
7221 int info = 0;
7222 int create_options = 0;
7223 int i;
7224 struct share_mode_lock *lck = NULL;
7226 if (total_data < 2) {
7227 return NT_STATUS_INVALID_PARAMETER;
7230 flags = SVAL(pdata,0);
7232 if (!VALID_STAT(smb_fname->st)) {
7233 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7236 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7237 !VALID_STAT_OF_DIR(smb_fname->st)) {
7238 return NT_STATUS_NOT_A_DIRECTORY;
7241 DEBUG(10,("smb_posix_unlink: %s %s\n",
7242 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7243 smb_fname_str_dbg(smb_fname)));
7245 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7246 create_options |= FILE_DIRECTORY_FILE;
7249 status = SMB_VFS_CREATE_FILE(
7250 conn, /* conn */
7251 req, /* req */
7252 0, /* root_dir_fid */
7253 smb_fname, /* fname */
7254 DELETE_ACCESS, /* access_mask */
7255 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7256 FILE_SHARE_DELETE),
7257 FILE_OPEN, /* create_disposition*/
7258 create_options, /* create_options */
7259 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7260 0, /* oplock_request */
7261 0, /* allocation_size */
7262 NULL, /* sd */
7263 NULL, /* ea_list */
7264 &fsp, /* result */
7265 &info); /* pinfo */
7267 if (!NT_STATUS_IS_OK(status)) {
7268 return status;
7272 * Don't lie to client. If we can't really delete due to
7273 * non-POSIX opens return SHARING_VIOLATION.
7276 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7277 NULL);
7278 if (lck == NULL) {
7279 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7280 "lock for file %s\n", fsp_str_dbg(fsp)));
7281 close_file(req, fsp, NORMAL_CLOSE);
7282 return NT_STATUS_INVALID_PARAMETER;
7286 * See if others still have the file open. If this is the case, then
7287 * don't delete. If all opens are POSIX delete we can set the delete
7288 * on close disposition.
7290 for (i=0; i<lck->num_share_modes; i++) {
7291 struct share_mode_entry *e = &lck->share_modes[i];
7292 if (is_valid_share_mode_entry(e)) {
7293 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7294 continue;
7296 /* Fail with sharing violation. */
7297 close_file(req, fsp, NORMAL_CLOSE);
7298 TALLOC_FREE(lck);
7299 return NT_STATUS_SHARING_VIOLATION;
7304 * Set the delete on close.
7306 status = smb_set_file_disposition_info(conn,
7307 &del,
7309 fsp,
7310 smb_fname);
7312 if (!NT_STATUS_IS_OK(status)) {
7313 close_file(req, fsp, NORMAL_CLOSE);
7314 TALLOC_FREE(lck);
7315 return status;
7317 TALLOC_FREE(lck);
7318 return close_file(req, fsp, NORMAL_CLOSE);
7321 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7322 struct smb_request *req,
7323 TALLOC_CTX *mem_ctx,
7324 uint16_t info_level,
7325 files_struct *fsp,
7326 struct smb_filename *smb_fname,
7327 char **ppdata, int total_data,
7328 int *ret_data_size)
7330 char *pdata = *ppdata;
7331 NTSTATUS status = NT_STATUS_OK;
7332 int data_return_size = 0;
7334 *ret_data_size = 0;
7336 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7337 return NT_STATUS_INVALID_LEVEL;
7340 if (!CAN_WRITE(conn)) {
7341 /* Allow POSIX opens. The open path will deny
7342 * any non-readonly opens. */
7343 if (info_level != SMB_POSIX_PATH_OPEN) {
7344 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7348 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7349 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7350 fsp ? fsp->fnum : -1, info_level, total_data));
7352 switch (info_level) {
7354 case SMB_INFO_STANDARD:
7356 status = smb_set_info_standard(conn,
7357 pdata,
7358 total_data,
7359 fsp,
7360 smb_fname);
7361 break;
7364 case SMB_INFO_SET_EA:
7366 status = smb_info_set_ea(conn,
7367 pdata,
7368 total_data,
7369 fsp,
7370 smb_fname);
7371 break;
7374 case SMB_SET_FILE_BASIC_INFO:
7375 case SMB_FILE_BASIC_INFORMATION:
7377 status = smb_set_file_basic_info(conn,
7378 pdata,
7379 total_data,
7380 fsp,
7381 smb_fname);
7382 break;
7385 case SMB_FILE_ALLOCATION_INFORMATION:
7386 case SMB_SET_FILE_ALLOCATION_INFO:
7388 status = smb_set_file_allocation_info(conn, req,
7389 pdata,
7390 total_data,
7391 fsp,
7392 smb_fname);
7393 break;
7396 case SMB_FILE_END_OF_FILE_INFORMATION:
7397 case SMB_SET_FILE_END_OF_FILE_INFO:
7399 status = smb_set_file_end_of_file_info(conn, req,
7400 pdata,
7401 total_data,
7402 fsp,
7403 smb_fname);
7404 break;
7407 case SMB_FILE_DISPOSITION_INFORMATION:
7408 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7410 #if 0
7411 /* JRA - We used to just ignore this on a path ?
7412 * Shouldn't this be invalid level on a pathname
7413 * based call ?
7415 if (tran_call != TRANSACT2_SETFILEINFO) {
7416 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7418 #endif
7419 status = smb_set_file_disposition_info(conn,
7420 pdata,
7421 total_data,
7422 fsp,
7423 smb_fname);
7424 break;
7427 case SMB_FILE_POSITION_INFORMATION:
7429 status = smb_file_position_information(conn,
7430 pdata,
7431 total_data,
7432 fsp);
7433 break;
7436 case SMB_FILE_FULL_EA_INFORMATION:
7438 status = smb_set_file_full_ea_info(conn,
7439 pdata,
7440 total_data,
7441 fsp);
7442 break;
7445 /* From tridge Samba4 :
7446 * MODE_INFORMATION in setfileinfo (I have no
7447 * idea what "mode information" on a file is - it takes a value of 0,
7448 * 2, 4 or 6. What could it be?).
7451 case SMB_FILE_MODE_INFORMATION:
7453 status = smb_file_mode_information(conn,
7454 pdata,
7455 total_data);
7456 break;
7460 * CIFS UNIX extensions.
7463 case SMB_SET_FILE_UNIX_BASIC:
7465 status = smb_set_file_unix_basic(conn, req,
7466 pdata,
7467 total_data,
7468 fsp,
7469 smb_fname);
7470 break;
7473 case SMB_SET_FILE_UNIX_INFO2:
7475 status = smb_set_file_unix_info2(conn, req,
7476 pdata,
7477 total_data,
7478 fsp,
7479 smb_fname);
7480 break;
7483 case SMB_SET_FILE_UNIX_LINK:
7485 if (fsp) {
7486 /* We must have a pathname for this. */
7487 return NT_STATUS_INVALID_LEVEL;
7489 status = smb_set_file_unix_link(conn, req, pdata,
7490 total_data, smb_fname);
7491 break;
7494 case SMB_SET_FILE_UNIX_HLINK:
7496 if (fsp) {
7497 /* We must have a pathname for this. */
7498 return NT_STATUS_INVALID_LEVEL;
7500 status = smb_set_file_unix_hlink(conn, req,
7501 pdata, total_data,
7502 smb_fname);
7503 break;
7506 case SMB_FILE_RENAME_INFORMATION:
7508 status = smb_file_rename_information(conn, req,
7509 pdata, total_data,
7510 fsp, smb_fname);
7511 break;
7514 #if defined(HAVE_POSIX_ACLS)
7515 case SMB_SET_POSIX_ACL:
7517 status = smb_set_posix_acl(conn,
7518 pdata,
7519 total_data,
7520 fsp,
7521 smb_fname);
7522 break;
7524 #endif
7526 case SMB_SET_POSIX_LOCK:
7528 if (!fsp) {
7529 return NT_STATUS_INVALID_LEVEL;
7531 status = smb_set_posix_lock(conn, req,
7532 pdata, total_data, fsp);
7533 break;
7536 case SMB_POSIX_PATH_OPEN:
7538 if (fsp) {
7539 /* We must have a pathname for this. */
7540 return NT_STATUS_INVALID_LEVEL;
7543 status = smb_posix_open(conn, req,
7544 ppdata,
7545 total_data,
7546 smb_fname,
7547 &data_return_size);
7548 break;
7551 case SMB_POSIX_PATH_UNLINK:
7553 if (fsp) {
7554 /* We must have a pathname for this. */
7555 return NT_STATUS_INVALID_LEVEL;
7558 status = smb_posix_unlink(conn, req,
7559 pdata,
7560 total_data,
7561 smb_fname);
7562 break;
7565 default:
7566 return NT_STATUS_INVALID_LEVEL;
7569 if (!NT_STATUS_IS_OK(status)) {
7570 return status;
7573 *ret_data_size = data_return_size;
7574 return NT_STATUS_OK;
7577 /****************************************************************************
7578 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7579 ****************************************************************************/
7581 static void call_trans2setfilepathinfo(connection_struct *conn,
7582 struct smb_request *req,
7583 unsigned int tran_call,
7584 char **pparams, int total_params,
7585 char **ppdata, int total_data,
7586 unsigned int max_data_bytes)
7588 char *params = *pparams;
7589 char *pdata = *ppdata;
7590 uint16 info_level;
7591 struct smb_filename *smb_fname = NULL;
7592 files_struct *fsp = NULL;
7593 NTSTATUS status = NT_STATUS_OK;
7594 int data_return_size = 0;
7596 if (!params) {
7597 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7598 return;
7601 if (tran_call == TRANSACT2_SETFILEINFO) {
7602 if (total_params < 4) {
7603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7604 return;
7607 fsp = file_fsp(req, SVAL(params,0));
7608 /* Basic check for non-null fsp. */
7609 if (!check_fsp_open(conn, req, fsp)) {
7610 return;
7612 info_level = SVAL(params,2);
7614 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7615 &smb_fname);
7616 if (!NT_STATUS_IS_OK(status)) {
7617 reply_nterror(req, status);
7618 return;
7621 if(fsp->is_directory || fsp->fh->fd == -1) {
7623 * This is actually a SETFILEINFO on a directory
7624 * handle (returned from an NT SMB). NT5.0 seems
7625 * to do this call. JRA.
7627 if (INFO_LEVEL_IS_UNIX(info_level)) {
7628 /* Always do lstat for UNIX calls. */
7629 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7630 DEBUG(3,("call_trans2setfilepathinfo: "
7631 "SMB_VFS_LSTAT of %s failed "
7632 "(%s)\n",
7633 smb_fname_str_dbg(smb_fname),
7634 strerror(errno)));
7635 reply_nterror(req, map_nt_error_from_unix(errno));
7636 return;
7638 } else {
7639 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7640 DEBUG(3,("call_trans2setfilepathinfo: "
7641 "fileinfo of %s failed (%s)\n",
7642 smb_fname_str_dbg(smb_fname),
7643 strerror(errno)));
7644 reply_nterror(req, map_nt_error_from_unix(errno));
7645 return;
7648 } else if (fsp->print_file) {
7650 * Doing a DELETE_ON_CLOSE should cancel a print job.
7652 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7653 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7655 DEBUG(3,("call_trans2setfilepathinfo: "
7656 "Cancelling print job (%s)\n",
7657 fsp_str_dbg(fsp)));
7659 SSVAL(params,0,0);
7660 send_trans2_replies(conn, req, params, 2,
7661 *ppdata, 0,
7662 max_data_bytes);
7663 return;
7664 } else {
7665 reply_doserror(req, ERRDOS, ERRbadpath);
7666 return;
7668 } else {
7670 * Original code - this is an open file.
7672 if (!check_fsp(conn, req, fsp)) {
7673 return;
7676 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7677 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7678 "of fnum %d failed (%s)\n", fsp->fnum,
7679 strerror(errno)));
7680 reply_nterror(req, map_nt_error_from_unix(errno));
7681 return;
7684 } else {
7685 char *fname = NULL;
7687 /* set path info */
7688 if (total_params < 7) {
7689 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7690 return;
7693 info_level = SVAL(params,0);
7694 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7695 total_params - 6, STR_TERMINATE,
7696 &status);
7697 if (!NT_STATUS_IS_OK(status)) {
7698 reply_nterror(req, status);
7699 return;
7702 status = filename_convert(req, conn,
7703 req->flags2 & FLAGS2_DFS_PATHNAMES,
7704 fname,
7706 NULL,
7707 &smb_fname);
7708 if (!NT_STATUS_IS_OK(status)) {
7709 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7710 reply_botherror(req,
7711 NT_STATUS_PATH_NOT_COVERED,
7712 ERRSRV, ERRbadpath);
7713 return;
7715 reply_nterror(req, status);
7716 return;
7719 if (INFO_LEVEL_IS_UNIX(info_level)) {
7721 * For CIFS UNIX extensions the target name may not exist.
7724 /* Always do lstat for UNIX calls. */
7725 SMB_VFS_LSTAT(conn, smb_fname);
7727 } else if (!VALID_STAT(smb_fname->st) &&
7728 SMB_VFS_STAT(conn, smb_fname)) {
7729 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7730 "%s failed (%s)\n",
7731 smb_fname_str_dbg(smb_fname),
7732 strerror(errno)));
7733 reply_nterror(req, map_nt_error_from_unix(errno));
7734 return;
7738 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7739 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7740 fsp ? fsp->fnum : -1, info_level,total_data));
7742 /* Realloc the parameter size */
7743 *pparams = (char *)SMB_REALLOC(*pparams,2);
7744 if (*pparams == NULL) {
7745 reply_nterror(req, NT_STATUS_NO_MEMORY);
7746 return;
7748 params = *pparams;
7750 SSVAL(params,0,0);
7752 status = smbd_do_setfilepathinfo(conn, req, req,
7753 info_level,
7754 fsp,
7755 smb_fname,
7756 ppdata, total_data,
7757 &data_return_size);
7758 if (!NT_STATUS_IS_OK(status)) {
7759 if (open_was_deferred(req->mid)) {
7760 /* We have re-scheduled this call. */
7761 return;
7763 if (blocking_lock_was_deferred(req->mid)) {
7764 /* We have re-scheduled this call. */
7765 return;
7767 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7768 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7769 ERRSRV, ERRbadpath);
7770 return;
7772 if (info_level == SMB_POSIX_PATH_OPEN) {
7773 reply_openerror(req, status);
7774 return;
7777 reply_nterror(req, status);
7778 return;
7781 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7782 max_data_bytes);
7784 return;
7787 /****************************************************************************
7788 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7789 ****************************************************************************/
7791 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7792 char **pparams, int total_params,
7793 char **ppdata, int total_data,
7794 unsigned int max_data_bytes)
7796 struct smb_filename *smb_dname = NULL;
7797 char *params = *pparams;
7798 char *pdata = *ppdata;
7799 char *directory = NULL;
7800 NTSTATUS status = NT_STATUS_OK;
7801 struct ea_list *ea_list = NULL;
7802 TALLOC_CTX *ctx = talloc_tos();
7804 if (!CAN_WRITE(conn)) {
7805 reply_doserror(req, ERRSRV, ERRaccess);
7806 return;
7809 if (total_params < 5) {
7810 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7811 return;
7814 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7815 total_params - 4, STR_TERMINATE,
7816 &status);
7817 if (!NT_STATUS_IS_OK(status)) {
7818 reply_nterror(req, status);
7819 return;
7822 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7824 status = filename_convert(ctx,
7825 conn,
7826 req->flags2 & FLAGS2_DFS_PATHNAMES,
7827 directory,
7829 NULL,
7830 &smb_dname);
7832 if (!NT_STATUS_IS_OK(status)) {
7833 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7834 reply_botherror(req,
7835 NT_STATUS_PATH_NOT_COVERED,
7836 ERRSRV, ERRbadpath);
7837 return;
7839 reply_nterror(req, status);
7840 return;
7843 /* Any data in this call is an EA list. */
7844 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7845 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7846 goto out;
7850 * OS/2 workplace shell seems to send SET_EA requests of "null"
7851 * length (4 bytes containing IVAL 4).
7852 * They seem to have no effect. Bug #3212. JRA.
7855 if (total_data != 4) {
7856 if (total_data < 10) {
7857 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7858 goto out;
7861 if (IVAL(pdata,0) > total_data) {
7862 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7863 IVAL(pdata,0), (unsigned int)total_data));
7864 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7865 goto out;
7868 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7869 total_data - 4);
7870 if (!ea_list) {
7871 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7872 goto out;
7875 /* If total_data == 4 Windows doesn't care what values
7876 * are placed in that field, it just ignores them.
7877 * The System i QNTC IBM SMB client puts bad values here,
7878 * so ignore them. */
7880 status = create_directory(conn, req, smb_dname);
7882 if (!NT_STATUS_IS_OK(status)) {
7883 reply_nterror(req, status);
7884 goto out;
7887 /* Try and set any given EA. */
7888 if (ea_list) {
7889 status = set_ea(conn, NULL, smb_dname, ea_list);
7890 if (!NT_STATUS_IS_OK(status)) {
7891 reply_nterror(req, status);
7892 goto out;
7896 /* Realloc the parameter and data sizes */
7897 *pparams = (char *)SMB_REALLOC(*pparams,2);
7898 if(*pparams == NULL) {
7899 reply_nterror(req, NT_STATUS_NO_MEMORY);
7900 goto out;
7902 params = *pparams;
7904 SSVAL(params,0,0);
7906 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7908 out:
7909 TALLOC_FREE(smb_dname);
7910 return;
7913 /****************************************************************************
7914 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7915 We don't actually do this - we just send a null response.
7916 ****************************************************************************/
7918 static void call_trans2findnotifyfirst(connection_struct *conn,
7919 struct smb_request *req,
7920 char **pparams, int total_params,
7921 char **ppdata, int total_data,
7922 unsigned int max_data_bytes)
7924 char *params = *pparams;
7925 uint16 info_level;
7927 if (total_params < 6) {
7928 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7929 return;
7932 info_level = SVAL(params,4);
7933 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7935 switch (info_level) {
7936 case 1:
7937 case 2:
7938 break;
7939 default:
7940 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7941 return;
7944 /* Realloc the parameter and data sizes */
7945 *pparams = (char *)SMB_REALLOC(*pparams,6);
7946 if (*pparams == NULL) {
7947 reply_nterror(req, NT_STATUS_NO_MEMORY);
7948 return;
7950 params = *pparams;
7952 SSVAL(params,0,fnf_handle);
7953 SSVAL(params,2,0); /* No changes */
7954 SSVAL(params,4,0); /* No EA errors */
7956 fnf_handle++;
7958 if(fnf_handle == 0)
7959 fnf_handle = 257;
7961 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7963 return;
7966 /****************************************************************************
7967 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7968 changes). Currently this does nothing.
7969 ****************************************************************************/
7971 static void call_trans2findnotifynext(connection_struct *conn,
7972 struct smb_request *req,
7973 char **pparams, int total_params,
7974 char **ppdata, int total_data,
7975 unsigned int max_data_bytes)
7977 char *params = *pparams;
7979 DEBUG(3,("call_trans2findnotifynext\n"));
7981 /* Realloc the parameter and data sizes */
7982 *pparams = (char *)SMB_REALLOC(*pparams,4);
7983 if (*pparams == NULL) {
7984 reply_nterror(req, NT_STATUS_NO_MEMORY);
7985 return;
7987 params = *pparams;
7989 SSVAL(params,0,0); /* No changes */
7990 SSVAL(params,2,0); /* No EA errors */
7992 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7994 return;
7997 /****************************************************************************
7998 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7999 ****************************************************************************/
8001 static void call_trans2getdfsreferral(connection_struct *conn,
8002 struct smb_request *req,
8003 char **pparams, int total_params,
8004 char **ppdata, int total_data,
8005 unsigned int max_data_bytes)
8007 char *params = *pparams;
8008 char *pathname = NULL;
8009 int reply_size = 0;
8010 int max_referral_level;
8011 NTSTATUS status = NT_STATUS_OK;
8012 TALLOC_CTX *ctx = talloc_tos();
8014 DEBUG(10,("call_trans2getdfsreferral\n"));
8016 if (total_params < 3) {
8017 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8018 return;
8021 max_referral_level = SVAL(params,0);
8023 if(!lp_host_msdfs()) {
8024 reply_doserror(req, ERRDOS, ERRbadfunc);
8025 return;
8028 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
8029 total_params - 2, STR_TERMINATE);
8030 if (!pathname) {
8031 reply_nterror(req, NT_STATUS_NOT_FOUND);
8032 return;
8034 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8035 ppdata,&status)) < 0) {
8036 reply_nterror(req, status);
8037 return;
8040 SSVAL(req->inbuf, smb_flg2,
8041 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8042 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8044 return;
8047 #define LMCAT_SPL 0x53
8048 #define LMFUNC_GETJOBID 0x60
8050 /****************************************************************************
8051 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8052 ****************************************************************************/
8054 static void call_trans2ioctl(connection_struct *conn,
8055 struct smb_request *req,
8056 char **pparams, int total_params,
8057 char **ppdata, int total_data,
8058 unsigned int max_data_bytes)
8060 char *pdata = *ppdata;
8061 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8063 /* check for an invalid fid before proceeding */
8065 if (!fsp) {
8066 reply_doserror(req, ERRDOS, ERRbadfid);
8067 return;
8070 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8071 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8072 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8073 if (*ppdata == NULL) {
8074 reply_nterror(req, NT_STATUS_NO_MEMORY);
8075 return;
8077 pdata = *ppdata;
8079 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8080 CAN ACCEPT THIS IN UNICODE. JRA. */
8082 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8083 srvstr_push(pdata, req->flags2, pdata + 2,
8084 global_myname(), 15,
8085 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8086 srvstr_push(pdata, req->flags2, pdata+18,
8087 lp_servicename(SNUM(conn)), 13,
8088 STR_ASCII|STR_TERMINATE); /* Service name */
8089 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8090 max_data_bytes);
8091 return;
8094 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8095 reply_doserror(req, ERRSRV, ERRerror);
8098 /****************************************************************************
8099 Reply to a SMBfindclose (stop trans2 directory search).
8100 ****************************************************************************/
8102 void reply_findclose(struct smb_request *req)
8104 int dptr_num;
8105 struct smbd_server_connection *sconn = smbd_server_conn;
8107 START_PROFILE(SMBfindclose);
8109 if (req->wct < 1) {
8110 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8111 END_PROFILE(SMBfindclose);
8112 return;
8115 dptr_num = SVALS(req->vwv+0, 0);
8117 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8119 dptr_close(sconn, &dptr_num);
8121 reply_outbuf(req, 0, 0);
8123 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8125 END_PROFILE(SMBfindclose);
8126 return;
8129 /****************************************************************************
8130 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8131 ****************************************************************************/
8133 void reply_findnclose(struct smb_request *req)
8135 int dptr_num;
8137 START_PROFILE(SMBfindnclose);
8139 if (req->wct < 1) {
8140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8141 END_PROFILE(SMBfindnclose);
8142 return;
8145 dptr_num = SVAL(req->vwv+0, 0);
8147 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8149 /* We never give out valid handles for a
8150 findnotifyfirst - so any dptr_num is ok here.
8151 Just ignore it. */
8153 reply_outbuf(req, 0, 0);
8155 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8157 END_PROFILE(SMBfindnclose);
8158 return;
8161 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8162 struct trans_state *state)
8164 if (Protocol >= PROTOCOL_NT1) {
8165 req->flags2 |= 0x40; /* IS_LONG_NAME */
8166 SSVAL(req->inbuf,smb_flg2,req->flags2);
8169 if (conn->encrypt_level == Required && !req->encrypted) {
8170 if (state->call != TRANSACT2_QFSINFO &&
8171 state->call != TRANSACT2_SETFSINFO) {
8172 DEBUG(0,("handle_trans2: encryption required "
8173 "with call 0x%x\n",
8174 (unsigned int)state->call));
8175 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8176 return;
8180 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8182 /* Now we must call the relevant TRANS2 function */
8183 switch(state->call) {
8184 case TRANSACT2_OPEN:
8186 START_PROFILE(Trans2_open);
8187 call_trans2open(conn, req,
8188 &state->param, state->total_param,
8189 &state->data, state->total_data,
8190 state->max_data_return);
8191 END_PROFILE(Trans2_open);
8192 break;
8195 case TRANSACT2_FINDFIRST:
8197 START_PROFILE(Trans2_findfirst);
8198 call_trans2findfirst(conn, req,
8199 &state->param, state->total_param,
8200 &state->data, state->total_data,
8201 state->max_data_return);
8202 END_PROFILE(Trans2_findfirst);
8203 break;
8206 case TRANSACT2_FINDNEXT:
8208 START_PROFILE(Trans2_findnext);
8209 call_trans2findnext(conn, req,
8210 &state->param, state->total_param,
8211 &state->data, state->total_data,
8212 state->max_data_return);
8213 END_PROFILE(Trans2_findnext);
8214 break;
8217 case TRANSACT2_QFSINFO:
8219 START_PROFILE(Trans2_qfsinfo);
8220 call_trans2qfsinfo(conn, req,
8221 &state->param, state->total_param,
8222 &state->data, state->total_data,
8223 state->max_data_return);
8224 END_PROFILE(Trans2_qfsinfo);
8225 break;
8228 case TRANSACT2_SETFSINFO:
8230 START_PROFILE(Trans2_setfsinfo);
8231 call_trans2setfsinfo(conn, req,
8232 &state->param, state->total_param,
8233 &state->data, state->total_data,
8234 state->max_data_return);
8235 END_PROFILE(Trans2_setfsinfo);
8236 break;
8239 case TRANSACT2_QPATHINFO:
8240 case TRANSACT2_QFILEINFO:
8242 START_PROFILE(Trans2_qpathinfo);
8243 call_trans2qfilepathinfo(conn, req, state->call,
8244 &state->param, state->total_param,
8245 &state->data, state->total_data,
8246 state->max_data_return);
8247 END_PROFILE(Trans2_qpathinfo);
8248 break;
8251 case TRANSACT2_SETPATHINFO:
8252 case TRANSACT2_SETFILEINFO:
8254 START_PROFILE(Trans2_setpathinfo);
8255 call_trans2setfilepathinfo(conn, req, state->call,
8256 &state->param, state->total_param,
8257 &state->data, state->total_data,
8258 state->max_data_return);
8259 END_PROFILE(Trans2_setpathinfo);
8260 break;
8263 case TRANSACT2_FINDNOTIFYFIRST:
8265 START_PROFILE(Trans2_findnotifyfirst);
8266 call_trans2findnotifyfirst(conn, req,
8267 &state->param, state->total_param,
8268 &state->data, state->total_data,
8269 state->max_data_return);
8270 END_PROFILE(Trans2_findnotifyfirst);
8271 break;
8274 case TRANSACT2_FINDNOTIFYNEXT:
8276 START_PROFILE(Trans2_findnotifynext);
8277 call_trans2findnotifynext(conn, req,
8278 &state->param, state->total_param,
8279 &state->data, state->total_data,
8280 state->max_data_return);
8281 END_PROFILE(Trans2_findnotifynext);
8282 break;
8285 case TRANSACT2_MKDIR:
8287 START_PROFILE(Trans2_mkdir);
8288 call_trans2mkdir(conn, req,
8289 &state->param, state->total_param,
8290 &state->data, state->total_data,
8291 state->max_data_return);
8292 END_PROFILE(Trans2_mkdir);
8293 break;
8296 case TRANSACT2_GET_DFS_REFERRAL:
8298 START_PROFILE(Trans2_get_dfs_referral);
8299 call_trans2getdfsreferral(conn, req,
8300 &state->param, state->total_param,
8301 &state->data, state->total_data,
8302 state->max_data_return);
8303 END_PROFILE(Trans2_get_dfs_referral);
8304 break;
8307 case TRANSACT2_IOCTL:
8309 START_PROFILE(Trans2_ioctl);
8310 call_trans2ioctl(conn, req,
8311 &state->param, state->total_param,
8312 &state->data, state->total_data,
8313 state->max_data_return);
8314 END_PROFILE(Trans2_ioctl);
8315 break;
8318 default:
8319 /* Error in request */
8320 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8321 reply_doserror(req, ERRSRV,ERRerror);
8325 /****************************************************************************
8326 Reply to a SMBtrans2.
8327 ****************************************************************************/
8329 void reply_trans2(struct smb_request *req)
8331 connection_struct *conn = req->conn;
8332 unsigned int dsoff;
8333 unsigned int dscnt;
8334 unsigned int psoff;
8335 unsigned int pscnt;
8336 unsigned int tran_call;
8337 struct trans_state *state;
8338 NTSTATUS result;
8340 START_PROFILE(SMBtrans2);
8342 if (req->wct < 14) {
8343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8344 END_PROFILE(SMBtrans2);
8345 return;
8348 dsoff = SVAL(req->vwv+12, 0);
8349 dscnt = SVAL(req->vwv+11, 0);
8350 psoff = SVAL(req->vwv+10, 0);
8351 pscnt = SVAL(req->vwv+9, 0);
8352 tran_call = SVAL(req->vwv+14, 0);
8354 result = allow_new_trans(conn->pending_trans, req->mid);
8355 if (!NT_STATUS_IS_OK(result)) {
8356 DEBUG(2, ("Got invalid trans2 request: %s\n",
8357 nt_errstr(result)));
8358 reply_nterror(req, result);
8359 END_PROFILE(SMBtrans2);
8360 return;
8363 if (IS_IPC(conn)) {
8364 switch (tran_call) {
8365 /* List the allowed trans2 calls on IPC$ */
8366 case TRANSACT2_OPEN:
8367 case TRANSACT2_GET_DFS_REFERRAL:
8368 case TRANSACT2_QFILEINFO:
8369 case TRANSACT2_QFSINFO:
8370 case TRANSACT2_SETFSINFO:
8371 break;
8372 default:
8373 reply_doserror(req, ERRSRV, ERRaccess);
8374 END_PROFILE(SMBtrans2);
8375 return;
8379 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8380 DEBUG(0, ("talloc failed\n"));
8381 reply_nterror(req, NT_STATUS_NO_MEMORY);
8382 END_PROFILE(SMBtrans2);
8383 return;
8386 state->cmd = SMBtrans2;
8388 state->mid = req->mid;
8389 state->vuid = req->vuid;
8390 state->setup_count = SVAL(req->vwv+13, 0);
8391 state->setup = NULL;
8392 state->total_param = SVAL(req->vwv+0, 0);
8393 state->param = NULL;
8394 state->total_data = SVAL(req->vwv+1, 0);
8395 state->data = NULL;
8396 state->max_param_return = SVAL(req->vwv+2, 0);
8397 state->max_data_return = SVAL(req->vwv+3, 0);
8398 state->max_setup_return = SVAL(req->vwv+4, 0);
8399 state->close_on_completion = BITSETW(req->vwv+5, 0);
8400 state->one_way = BITSETW(req->vwv+5, 1);
8402 state->call = tran_call;
8404 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8405 is so as a sanity check */
8406 if (state->setup_count != 1) {
8408 * Need to have rc=0 for ioctl to get job id for OS/2.
8409 * Network printing will fail if function is not successful.
8410 * Similar function in reply.c will be used if protocol
8411 * is LANMAN1.0 instead of LM1.2X002.
8412 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8413 * outbuf doesn't have to be set(only job id is used).
8415 if ( (state->setup_count == 4)
8416 && (tran_call == TRANSACT2_IOCTL)
8417 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8418 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8419 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8420 } else {
8421 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8422 DEBUG(2,("Transaction is %d\n",tran_call));
8423 TALLOC_FREE(state);
8424 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8425 END_PROFILE(SMBtrans2);
8426 return;
8430 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8431 goto bad_param;
8433 if (state->total_data) {
8435 if (trans_oob(state->total_data, 0, dscnt)
8436 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8437 goto bad_param;
8440 /* Can't use talloc here, the core routines do realloc on the
8441 * params and data. */
8442 state->data = (char *)SMB_MALLOC(state->total_data);
8443 if (state->data == NULL) {
8444 DEBUG(0,("reply_trans2: data malloc fail for %u "
8445 "bytes !\n", (unsigned int)state->total_data));
8446 TALLOC_FREE(state);
8447 reply_nterror(req, NT_STATUS_NO_MEMORY);
8448 END_PROFILE(SMBtrans2);
8449 return;
8452 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8455 if (state->total_param) {
8457 if (trans_oob(state->total_param, 0, pscnt)
8458 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8459 goto bad_param;
8462 /* Can't use talloc here, the core routines do realloc on the
8463 * params and data. */
8464 state->param = (char *)SMB_MALLOC(state->total_param);
8465 if (state->param == NULL) {
8466 DEBUG(0,("reply_trans: param malloc fail for %u "
8467 "bytes !\n", (unsigned int)state->total_param));
8468 SAFE_FREE(state->data);
8469 TALLOC_FREE(state);
8470 reply_nterror(req, NT_STATUS_NO_MEMORY);
8471 END_PROFILE(SMBtrans2);
8472 return;
8475 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8478 state->received_data = dscnt;
8479 state->received_param = pscnt;
8481 if ((state->received_param == state->total_param) &&
8482 (state->received_data == state->total_data)) {
8484 handle_trans2(conn, req, state);
8486 SAFE_FREE(state->data);
8487 SAFE_FREE(state->param);
8488 TALLOC_FREE(state);
8489 END_PROFILE(SMBtrans2);
8490 return;
8493 DLIST_ADD(conn->pending_trans, state);
8495 /* We need to send an interim response then receive the rest
8496 of the parameter/data bytes */
8497 reply_outbuf(req, 0, 0);
8498 show_msg((char *)req->outbuf);
8499 END_PROFILE(SMBtrans2);
8500 return;
8502 bad_param:
8504 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8505 SAFE_FREE(state->data);
8506 SAFE_FREE(state->param);
8507 TALLOC_FREE(state);
8508 END_PROFILE(SMBtrans2);
8509 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8513 /****************************************************************************
8514 Reply to a SMBtranss2
8515 ****************************************************************************/
8517 void reply_transs2(struct smb_request *req)
8519 connection_struct *conn = req->conn;
8520 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8521 struct trans_state *state;
8523 START_PROFILE(SMBtranss2);
8525 show_msg((char *)req->inbuf);
8527 if (req->wct < 8) {
8528 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8529 END_PROFILE(SMBtranss2);
8530 return;
8533 for (state = conn->pending_trans; state != NULL;
8534 state = state->next) {
8535 if (state->mid == req->mid) {
8536 break;
8540 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8541 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8542 END_PROFILE(SMBtranss2);
8543 return;
8546 /* Revise state->total_param and state->total_data in case they have
8547 changed downwards */
8549 if (SVAL(req->vwv+0, 0) < state->total_param)
8550 state->total_param = SVAL(req->vwv+0, 0);
8551 if (SVAL(req->vwv+1, 0) < state->total_data)
8552 state->total_data = SVAL(req->vwv+1, 0);
8554 pcnt = SVAL(req->vwv+2, 0);
8555 poff = SVAL(req->vwv+3, 0);
8556 pdisp = SVAL(req->vwv+4, 0);
8558 dcnt = SVAL(req->vwv+5, 0);
8559 doff = SVAL(req->vwv+6, 0);
8560 ddisp = SVAL(req->vwv+7, 0);
8562 state->received_param += pcnt;
8563 state->received_data += dcnt;
8565 if ((state->received_data > state->total_data) ||
8566 (state->received_param > state->total_param))
8567 goto bad_param;
8569 if (pcnt) {
8570 if (trans_oob(state->total_param, pdisp, pcnt)
8571 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8572 goto bad_param;
8574 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8577 if (dcnt) {
8578 if (trans_oob(state->total_data, ddisp, dcnt)
8579 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8580 goto bad_param;
8582 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8585 if ((state->received_param < state->total_param) ||
8586 (state->received_data < state->total_data)) {
8587 END_PROFILE(SMBtranss2);
8588 return;
8591 handle_trans2(conn, req, state);
8593 DLIST_REMOVE(conn->pending_trans, state);
8594 SAFE_FREE(state->data);
8595 SAFE_FREE(state->param);
8596 TALLOC_FREE(state);
8598 END_PROFILE(SMBtranss2);
8599 return;
8601 bad_param:
8603 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8604 DLIST_REMOVE(conn->pending_trans, state);
8605 SAFE_FREE(state->data);
8606 SAFE_FREE(state->param);
8607 TALLOC_FREE(state);
8608 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8609 END_PROFILE(SMBtranss2);
8610 return;