Fix bug 6494 - Incorrect FileStatus returned in NT_CREATE_ANDX.
[Samba/bb.git] / source3 / smbd / trans2.c
blobf2c025b6c103e168027f3c41cbac898be1814a32
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 NULL
79 int i;
81 for (i = 0; prohibited_ea_names[i]; i++) {
82 if (strequal( prohibited_ea_names[i], unix_ea_name))
83 return true;
85 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
86 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
87 return true;
89 return false;
92 /****************************************************************************
93 Get one EA value. Fill in a struct ea_struct.
94 ****************************************************************************/
96 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
97 files_struct *fsp, const char *fname,
98 const char *ea_name, struct ea_struct *pea)
100 /* Get the value of this xattr. Max size is 64k. */
101 size_t attr_size = 256;
102 char *val = NULL;
103 ssize_t sizeret;
105 again:
107 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
108 if (!val) {
109 return NT_STATUS_NO_MEMORY;
112 if (fsp && fsp->fh->fd != -1) {
113 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
114 } else {
115 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
118 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
119 attr_size = 65536;
120 goto again;
123 if (sizeret == -1) {
124 return map_nt_error_from_unix(errno);
127 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
128 dump_data(10, (uint8 *)val, sizeret);
130 pea->flags = 0;
131 if (strnequal(ea_name, "user.", 5)) {
132 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
133 } else {
134 pea->name = talloc_strdup(mem_ctx, ea_name);
136 if (pea->name == NULL) {
137 TALLOC_FREE(val);
138 return NT_STATUS_NO_MEMORY;
140 pea->value.data = (unsigned char *)val;
141 pea->value.length = (size_t)sizeret;
142 return NT_STATUS_OK;
145 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
146 files_struct *fsp, const char *fname,
147 char ***pnames, size_t *pnum_names)
149 /* Get a list of all xattrs. Max namesize is 64k. */
150 size_t ea_namelist_size = 1024;
151 char *ea_namelist = NULL;
153 char *p;
154 char **names, **tmp;
155 size_t num_names;
156 ssize_t sizeret = -1;
158 if (!lp_ea_support(SNUM(conn))) {
159 *pnames = NULL;
160 *pnum_names = 0;
161 return NT_STATUS_OK;
165 * TALLOC the result early to get the talloc hierarchy right.
168 names = TALLOC_ARRAY(mem_ctx, char *, 1);
169 if (names == NULL) {
170 DEBUG(0, ("talloc failed\n"));
171 return NT_STATUS_NO_MEMORY;
174 while (ea_namelist_size <= 65536) {
176 ea_namelist = TALLOC_REALLOC_ARRAY(
177 names, ea_namelist, char, ea_namelist_size);
178 if (ea_namelist == NULL) {
179 DEBUG(0, ("talloc failed\n"));
180 TALLOC_FREE(names);
181 return NT_STATUS_NO_MEMORY;
184 if (fsp && fsp->fh->fd != -1) {
185 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
186 ea_namelist_size);
187 } else {
188 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
189 ea_namelist_size);
192 if ((sizeret == -1) && (errno == ERANGE)) {
193 ea_namelist_size *= 2;
195 else {
196 break;
200 if (sizeret == -1) {
201 TALLOC_FREE(names);
202 return map_nt_error_from_unix(errno);
205 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
206 (unsigned int)sizeret));
208 if (sizeret == 0) {
209 TALLOC_FREE(names);
210 if (pnames) {
211 *pnames = NULL;
213 *pnum_names = 0;
214 return NT_STATUS_OK;
218 * Ensure the result is 0-terminated
221 if (ea_namelist[sizeret-1] != '\0') {
222 TALLOC_FREE(names);
223 return NT_STATUS_INTERNAL_ERROR;
227 * count the names
229 num_names = 0;
231 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
232 num_names += 1;
235 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
236 if (tmp == NULL) {
237 DEBUG(0, ("talloc failed\n"));
238 TALLOC_FREE(names);
239 return NT_STATUS_NO_MEMORY;
242 names = tmp;
243 num_names = 0;
245 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
246 names[num_names++] = p;
249 if (pnames) {
250 *pnames = names;
251 } else {
252 TALLOC_FREE(names);
254 *pnum_names = num_names;
255 return NT_STATUS_OK;
258 /****************************************************************************
259 Return a linked list of the total EA's. Plus the total size
260 ****************************************************************************/
262 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
263 const char *fname, size_t *pea_total_len)
265 /* Get a list of all xattrs. Max namesize is 64k. */
266 size_t i, num_names;
267 char **names;
268 struct ea_list *ea_list_head = NULL;
269 NTSTATUS status;
271 *pea_total_len = 0;
273 if (!lp_ea_support(SNUM(conn))) {
274 return NULL;
277 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
278 &names, &num_names);
280 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
281 return NULL;
284 for (i=0; i<num_names; i++) {
285 struct ea_list *listp;
286 fstring dos_ea_name;
288 if (strnequal(names[i], "system.", 7)
289 || samba_private_attr_name(names[i]))
290 continue;
292 listp = TALLOC_P(mem_ctx, struct ea_list);
293 if (listp == NULL) {
294 return NULL;
297 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
298 fname, names[i],
299 &listp->ea))) {
300 return NULL;
303 push_ascii_fstring(dos_ea_name, listp->ea.name);
305 *pea_total_len +=
306 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
308 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
309 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
310 (unsigned int)listp->ea.value.length));
312 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
316 /* Add on 4 for total length. */
317 if (*pea_total_len) {
318 *pea_total_len += 4;
321 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
322 (unsigned int)*pea_total_len));
324 return ea_list_head;
327 /****************************************************************************
328 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
329 that was filled.
330 ****************************************************************************/
332 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
333 connection_struct *conn, struct ea_list *ea_list)
335 unsigned int ret_data_size = 4;
336 char *p = pdata;
338 SMB_ASSERT(total_data_size >= 4);
340 if (!lp_ea_support(SNUM(conn))) {
341 SIVAL(pdata,4,0);
342 return 4;
345 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
346 size_t dos_namelen;
347 fstring dos_ea_name;
348 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
349 dos_namelen = strlen(dos_ea_name);
350 if (dos_namelen > 255 || dos_namelen == 0) {
351 break;
353 if (ea_list->ea.value.length > 65535) {
354 break;
356 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
357 break;
360 /* We know we have room. */
361 SCVAL(p,0,ea_list->ea.flags);
362 SCVAL(p,1,dos_namelen);
363 SSVAL(p,2,ea_list->ea.value.length);
364 fstrcpy(p+4, dos_ea_name);
365 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
367 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
368 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
371 ret_data_size = PTR_DIFF(p, pdata);
372 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
373 SIVAL(pdata,0,ret_data_size);
374 return ret_data_size;
377 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
378 char *pdata,
379 unsigned int total_data_size,
380 unsigned int *ret_data_size,
381 connection_struct *conn,
382 struct ea_list *ea_list)
384 uint8_t *p = (uint8_t *)pdata;
385 uint8_t *last_start = NULL;
387 *ret_data_size = 0;
389 if (!lp_ea_support(SNUM(conn))) {
390 return NT_STATUS_NO_EAS_ON_FILE;
393 for (; ea_list; ea_list = ea_list->next) {
394 size_t dos_namelen;
395 fstring dos_ea_name;
396 size_t this_size;
398 if (last_start) {
399 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
401 last_start = p;
403 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
404 dos_namelen = strlen(dos_ea_name);
405 if (dos_namelen > 255 || dos_namelen == 0) {
406 return NT_STATUS_INTERNAL_ERROR;
408 if (ea_list->ea.value.length > 65535) {
409 return NT_STATUS_INTERNAL_ERROR;
412 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
414 if (ea_list->next) {
415 size_t pad = 4 - (this_size % 4);
416 this_size += pad;
419 if (this_size > total_data_size) {
420 return NT_STATUS_INFO_LENGTH_MISMATCH;
423 /* We know we have room. */
424 SIVAL(p, 0x00, 0); /* next offset */
425 SCVAL(p, 0x04, ea_list->ea.flags);
426 SCVAL(p, 0x05, dos_namelen);
427 SSVAL(p, 0x06, ea_list->ea.value.length);
428 fstrcpy((char *)(p+0x08), dos_ea_name);
429 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
431 total_data_size -= this_size;
432 p += this_size;
435 *ret_data_size = PTR_DIFF(p, pdata);
436 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
437 return NT_STATUS_OK;
440 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
442 size_t total_ea_len = 0;
443 TALLOC_CTX *mem_ctx = NULL;
445 if (!lp_ea_support(SNUM(conn))) {
446 return 0;
448 mem_ctx = talloc_tos();
449 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
450 return total_ea_len;
453 /****************************************************************************
454 Ensure the EA name is case insensitive by matching any existing EA name.
455 ****************************************************************************/
457 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
459 size_t total_ea_len;
460 TALLOC_CTX *mem_ctx = talloc_tos();
461 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
463 for (; ea_list; ea_list = ea_list->next) {
464 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
465 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
466 &unix_ea_name[5], ea_list->ea.name));
467 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
468 break;
473 /****************************************************************************
474 Set or delete an extended attribute.
475 ****************************************************************************/
477 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
478 const struct smb_filename *smb_fname, struct ea_list *ea_list)
480 char *fname = NULL;
482 if (!lp_ea_support(SNUM(conn))) {
483 return NT_STATUS_EAS_NOT_SUPPORTED;
486 /* For now setting EAs on streams isn't supported. */
487 fname = smb_fname->base_name;
489 for (;ea_list; ea_list = ea_list->next) {
490 int ret;
491 fstring unix_ea_name;
493 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
494 fstrcat(unix_ea_name, ea_list->ea.name);
496 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
498 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
500 if (samba_private_attr_name(unix_ea_name)) {
501 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
502 return NT_STATUS_ACCESS_DENIED;
505 if (ea_list->ea.value.length == 0) {
506 /* Remove the attribute. */
507 if (fsp && (fsp->fh->fd != -1)) {
508 DEBUG(10,("set_ea: deleting ea name %s on "
509 "file %s by file descriptor.\n",
510 unix_ea_name, fsp_str_dbg(fsp)));
511 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
512 } else {
513 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
514 unix_ea_name, fname));
515 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
517 #ifdef ENOATTR
518 /* Removing a non existent attribute always succeeds. */
519 if (ret == -1 && errno == ENOATTR) {
520 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
521 unix_ea_name));
522 ret = 0;
524 #endif
525 } else {
526 if (fsp && (fsp->fh->fd != -1)) {
527 DEBUG(10,("set_ea: setting ea name %s on file "
528 "%s by file descriptor.\n",
529 unix_ea_name, fsp_str_dbg(fsp)));
530 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
531 ea_list->ea.value.data, ea_list->ea.value.length, 0);
532 } else {
533 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
534 unix_ea_name, fname));
535 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
536 ea_list->ea.value.data, ea_list->ea.value.length, 0);
540 if (ret == -1) {
541 #ifdef ENOTSUP
542 if (errno == ENOTSUP) {
543 return NT_STATUS_EAS_NOT_SUPPORTED;
545 #endif
546 return map_nt_error_from_unix(errno);
550 return NT_STATUS_OK;
552 /****************************************************************************
553 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
554 ****************************************************************************/
556 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
558 struct ea_list *ea_list_head = NULL;
559 size_t converted_size, offset = 0;
561 while (offset + 2 < data_size) {
562 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
563 unsigned int namelen = CVAL(pdata,offset);
565 offset++; /* Go past the namelen byte. */
567 /* integer wrap paranioa. */
568 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
569 (offset > data_size) || (namelen > data_size) ||
570 (offset + namelen >= data_size)) {
571 break;
573 /* Ensure the name is null terminated. */
574 if (pdata[offset + namelen] != '\0') {
575 return NULL;
577 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
578 &converted_size)) {
579 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
580 "failed: %s", strerror(errno)));
582 if (!eal->ea.name) {
583 return NULL;
586 offset += (namelen + 1); /* Go past the name + terminating zero. */
587 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
588 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
591 return ea_list_head;
594 /****************************************************************************
595 Read one EA list entry from the buffer.
596 ****************************************************************************/
598 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
600 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
601 uint16 val_len;
602 unsigned int namelen;
603 size_t converted_size;
605 if (!eal) {
606 return NULL;
609 if (data_size < 6) {
610 return NULL;
613 eal->ea.flags = CVAL(pdata,0);
614 namelen = CVAL(pdata,1);
615 val_len = SVAL(pdata,2);
617 if (4 + namelen + 1 + val_len > data_size) {
618 return NULL;
621 /* Ensure the name is null terminated. */
622 if (pdata[namelen + 4] != '\0') {
623 return NULL;
625 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
626 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
627 strerror(errno)));
629 if (!eal->ea.name) {
630 return NULL;
633 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
634 if (!eal->ea.value.data) {
635 return NULL;
638 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
640 /* Ensure we're null terminated just in case we print the value. */
641 eal->ea.value.data[val_len] = '\0';
642 /* But don't count the null. */
643 eal->ea.value.length--;
645 if (pbytes_used) {
646 *pbytes_used = 4 + namelen + 1 + val_len;
649 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
650 dump_data(10, eal->ea.value.data, eal->ea.value.length);
652 return eal;
655 /****************************************************************************
656 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
657 ****************************************************************************/
659 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
661 struct ea_list *ea_list_head = NULL;
662 size_t offset = 0;
663 size_t bytes_used = 0;
665 while (offset < data_size) {
666 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
668 if (!eal) {
669 return NULL;
672 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
673 offset += bytes_used;
676 return ea_list_head;
679 /****************************************************************************
680 Count the total EA size needed.
681 ****************************************************************************/
683 static size_t ea_list_size(struct ea_list *ealist)
685 fstring dos_ea_name;
686 struct ea_list *listp;
687 size_t ret = 0;
689 for (listp = ealist; listp; listp = listp->next) {
690 push_ascii_fstring(dos_ea_name, listp->ea.name);
691 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
693 /* Add on 4 for total length. */
694 if (ret) {
695 ret += 4;
698 return ret;
701 /****************************************************************************
702 Return a union of EA's from a file list and a list of names.
703 The TALLOC context for the two lists *MUST* be identical as we steal
704 memory from one list to add to another. JRA.
705 ****************************************************************************/
707 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
709 struct ea_list *nlistp, *flistp;
711 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
712 for (flistp = file_list; flistp; flistp = flistp->next) {
713 if (strequal(nlistp->ea.name, flistp->ea.name)) {
714 break;
718 if (flistp) {
719 /* Copy the data from this entry. */
720 nlistp->ea.flags = flistp->ea.flags;
721 nlistp->ea.value = flistp->ea.value;
722 } else {
723 /* Null entry. */
724 nlistp->ea.flags = 0;
725 ZERO_STRUCT(nlistp->ea.value);
729 *total_ea_len = ea_list_size(name_list);
730 return name_list;
733 /****************************************************************************
734 Send the required number of replies back.
735 We assume all fields other than the data fields are
736 set correctly for the type of call.
737 HACK ! Always assumes smb_setup field is zero.
738 ****************************************************************************/
740 void send_trans2_replies(connection_struct *conn,
741 struct smb_request *req,
742 const char *params,
743 int paramsize,
744 const char *pdata,
745 int datasize,
746 int max_data_bytes)
748 /* As we are using a protocol > LANMAN1 then the max_send
749 variable must have been set in the sessetupX call.
750 This takes precedence over the max_xmit field in the
751 global struct. These different max_xmit variables should
752 be merged as this is now too confusing */
754 int data_to_send = datasize;
755 int params_to_send = paramsize;
756 int useable_space;
757 const char *pp = params;
758 const char *pd = pdata;
759 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
760 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
761 int data_alignment_offset = 0;
762 bool overflow = False;
763 struct smbd_server_connection *sconn = smbd_server_conn;
764 int max_send = sconn->smb1.sessions.max_send;
766 /* Modify the data_to_send and datasize and set the error if
767 we're trying to send more than max_data_bytes. We still send
768 the part of the packet(s) that fit. Strange, but needed
769 for OS/2. */
771 if (max_data_bytes > 0 && datasize > max_data_bytes) {
772 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
773 max_data_bytes, datasize ));
774 datasize = data_to_send = max_data_bytes;
775 overflow = True;
778 /* If there genuinely are no parameters or data to send just send the empty packet */
780 if(params_to_send == 0 && data_to_send == 0) {
781 reply_outbuf(req, 10, 0);
782 show_msg((char *)req->outbuf);
783 if (!srv_send_smb(smbd_server_fd(),
784 (char *)req->outbuf,
785 true, req->seqnum+1,
786 IS_CONN_ENCRYPTED(conn),
787 &req->pcd)) {
788 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
790 TALLOC_FREE(req->outbuf);
791 return;
794 /* When sending params and data ensure that both are nicely aligned */
795 /* Only do this alignment when there is also data to send - else
796 can cause NT redirector problems. */
798 if (((params_to_send % 4) != 0) && (data_to_send != 0))
799 data_alignment_offset = 4 - (params_to_send % 4);
801 /* Space is bufsize minus Netbios over TCP header minus SMB header */
802 /* The alignment_offset is to align the param bytes on an even byte
803 boundary. NT 4.0 Beta needs this to work correctly. */
805 useable_space = max_send - (smb_size
806 + 2 * 10 /* wct */
807 + alignment_offset
808 + data_alignment_offset);
810 if (useable_space < 0) {
811 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
812 "= %d!!!", useable_space));
813 exit_server_cleanly("send_trans2_replies: Not enough space");
816 while (params_to_send || data_to_send) {
817 /* Calculate whether we will totally or partially fill this packet */
819 total_sent_thistime = params_to_send + data_to_send;
821 /* We can never send more than useable_space */
823 * Note that 'useable_space' does not include the alignment offsets,
824 * but we must include the alignment offsets in the calculation of
825 * the length of the data we send over the wire, as the alignment offsets
826 * are sent here. Fix from Marc_Jacobsen@hp.com.
829 total_sent_thistime = MIN(total_sent_thistime, useable_space);
831 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
832 + data_alignment_offset);
835 * We might have SMBtrans2s in req which was transferred to
836 * the outbuf, fix that.
838 SCVAL(req->outbuf, smb_com, SMBtrans2);
840 /* Set total params and data to be sent */
841 SSVAL(req->outbuf,smb_tprcnt,paramsize);
842 SSVAL(req->outbuf,smb_tdrcnt,datasize);
844 /* Calculate how many parameters and data we can fit into
845 * this packet. Parameters get precedence
848 params_sent_thistime = MIN(params_to_send,useable_space);
849 data_sent_thistime = useable_space - params_sent_thistime;
850 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
852 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
854 /* smb_proff is the offset from the start of the SMB header to the
855 parameter bytes, however the first 4 bytes of outbuf are
856 the Netbios over TCP header. Thus use smb_base() to subtract
857 them from the calculation */
859 SSVAL(req->outbuf,smb_proff,
860 ((smb_buf(req->outbuf)+alignment_offset)
861 - smb_base(req->outbuf)));
863 if(params_sent_thistime == 0)
864 SSVAL(req->outbuf,smb_prdisp,0);
865 else
866 /* Absolute displacement of param bytes sent in this packet */
867 SSVAL(req->outbuf,smb_prdisp,pp - params);
869 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
870 if(data_sent_thistime == 0) {
871 SSVAL(req->outbuf,smb_droff,0);
872 SSVAL(req->outbuf,smb_drdisp, 0);
873 } else {
874 /* The offset of the data bytes is the offset of the
875 parameter bytes plus the number of parameters being sent this time */
876 SSVAL(req->outbuf, smb_droff,
877 ((smb_buf(req->outbuf)+alignment_offset)
878 - smb_base(req->outbuf))
879 + params_sent_thistime + data_alignment_offset);
880 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
883 /* Initialize the padding for alignment */
885 if (alignment_offset != 0) {
886 memset(smb_buf(req->outbuf), 0, alignment_offset);
889 /* Copy the param bytes into the packet */
891 if(params_sent_thistime) {
892 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
893 params_sent_thistime);
896 /* Copy in the data bytes */
897 if(data_sent_thistime) {
898 if (data_alignment_offset != 0) {
899 memset((smb_buf(req->outbuf)+alignment_offset+
900 params_sent_thistime), 0,
901 data_alignment_offset);
903 memcpy(smb_buf(req->outbuf)+alignment_offset
904 +params_sent_thistime+data_alignment_offset,
905 pd,data_sent_thistime);
908 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
909 params_sent_thistime, data_sent_thistime, useable_space));
910 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
911 params_to_send, data_to_send, paramsize, datasize));
913 if (overflow) {
914 error_packet_set((char *)req->outbuf,
915 ERRDOS,ERRbufferoverflow,
916 STATUS_BUFFER_OVERFLOW,
917 __LINE__,__FILE__);
920 /* Send the packet */
921 show_msg((char *)req->outbuf);
922 if (!srv_send_smb(smbd_server_fd(),
923 (char *)req->outbuf,
924 true, req->seqnum+1,
925 IS_CONN_ENCRYPTED(conn),
926 &req->pcd))
927 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
929 TALLOC_FREE(req->outbuf);
931 pp += params_sent_thistime;
932 pd += data_sent_thistime;
934 params_to_send -= params_sent_thistime;
935 data_to_send -= data_sent_thistime;
937 /* Sanity check */
938 if(params_to_send < 0 || data_to_send < 0) {
939 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
940 params_to_send, data_to_send));
941 return;
945 return;
948 /****************************************************************************
949 Reply to a TRANSACT2_OPEN.
950 ****************************************************************************/
952 static void call_trans2open(connection_struct *conn,
953 struct smb_request *req,
954 char **pparams, int total_params,
955 char **ppdata, int total_data,
956 unsigned int max_data_bytes)
958 struct smb_filename *smb_fname = NULL;
959 char *params = *pparams;
960 char *pdata = *ppdata;
961 int deny_mode;
962 int32 open_attr;
963 bool oplock_request;
964 #if 0
965 bool return_additional_info;
966 int16 open_sattr;
967 time_t open_time;
968 #endif
969 int open_ofun;
970 uint32 open_size;
971 char *pname;
972 char *fname = NULL;
973 SMB_OFF_T size=0;
974 int fattr=0,mtime=0;
975 SMB_INO_T inode = 0;
976 int smb_action = 0;
977 files_struct *fsp;
978 struct ea_list *ea_list = NULL;
979 uint16 flags = 0;
980 NTSTATUS status;
981 uint32 access_mask;
982 uint32 share_mode;
983 uint32 create_disposition;
984 uint32 create_options = 0;
985 TALLOC_CTX *ctx = talloc_tos();
988 * Ensure we have enough parameters to perform the operation.
991 if (total_params < 29) {
992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
993 goto out;
996 flags = SVAL(params, 0);
997 deny_mode = SVAL(params, 2);
998 open_attr = SVAL(params,6);
999 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1000 if (oplock_request) {
1001 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1004 #if 0
1005 return_additional_info = BITSETW(params,0);
1006 open_sattr = SVAL(params, 4);
1007 open_time = make_unix_date3(params+8);
1008 #endif
1009 open_ofun = SVAL(params,12);
1010 open_size = IVAL(params,14);
1011 pname = &params[28];
1013 if (IS_IPC(conn)) {
1014 reply_doserror(req, ERRSRV, ERRaccess);
1015 goto out;
1018 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1019 total_params - 28, STR_TERMINATE,
1020 &status);
1021 if (!NT_STATUS_IS_OK(status)) {
1022 reply_nterror(req, status);
1023 goto out;
1026 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1027 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1028 (unsigned int)open_ofun, open_size));
1030 status = filename_convert(ctx,
1031 conn,
1032 req->flags2 & FLAGS2_DFS_PATHNAMES,
1033 fname,
1035 NULL,
1036 &smb_fname);
1037 if (!NT_STATUS_IS_OK(status)) {
1038 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1039 reply_botherror(req,
1040 NT_STATUS_PATH_NOT_COVERED,
1041 ERRSRV, ERRbadpath);
1042 goto out;
1044 reply_nterror(req, status);
1045 goto out;
1048 if (open_ofun == 0) {
1049 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1050 goto out;
1053 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1054 &access_mask, &share_mode,
1055 &create_disposition,
1056 &create_options)) {
1057 reply_doserror(req, ERRDOS, ERRbadaccess);
1058 goto out;
1061 /* Any data in this call is an EA list. */
1062 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1063 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1064 goto out;
1067 if (total_data != 4) {
1068 if (total_data < 10) {
1069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1070 goto out;
1073 if (IVAL(pdata,0) > total_data) {
1074 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1075 IVAL(pdata,0), (unsigned int)total_data));
1076 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1077 goto out;
1080 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1081 total_data - 4);
1082 if (!ea_list) {
1083 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1084 goto out;
1086 } else if (IVAL(pdata,0) != 4) {
1087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1088 goto out;
1091 status = SMB_VFS_CREATE_FILE(
1092 conn, /* conn */
1093 req, /* req */
1094 0, /* root_dir_fid */
1095 smb_fname, /* fname */
1096 access_mask, /* access_mask */
1097 share_mode, /* share_access */
1098 create_disposition, /* create_disposition*/
1099 create_options, /* create_options */
1100 open_attr, /* file_attributes */
1101 oplock_request, /* oplock_request */
1102 open_size, /* allocation_size */
1103 NULL, /* sd */
1104 ea_list, /* ea_list */
1105 &fsp, /* result */
1106 &smb_action); /* psbuf */
1108 if (!NT_STATUS_IS_OK(status)) {
1109 if (open_was_deferred(req->mid)) {
1110 /* We have re-scheduled this call. */
1111 goto out;
1113 reply_openerror(req, status);
1114 goto out;
1117 size = get_file_size_stat(&smb_fname->st);
1118 fattr = dos_mode(conn, smb_fname);
1119 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1120 inode = smb_fname->st.st_ex_ino;
1121 if (fattr & aDIR) {
1122 close_file(req, fsp, ERROR_CLOSE);
1123 reply_doserror(req, ERRDOS,ERRnoaccess);
1124 goto out;
1127 /* Realloc the size of parameters and data we will return */
1128 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1129 if(*pparams == NULL ) {
1130 reply_nterror(req, NT_STATUS_NO_MEMORY);
1131 goto out;
1133 params = *pparams;
1135 SSVAL(params,0,fsp->fnum);
1136 SSVAL(params,2,fattr);
1137 srv_put_dos_date2(params,4, mtime);
1138 SIVAL(params,8, (uint32)size);
1139 SSVAL(params,12,deny_mode);
1140 SSVAL(params,14,0); /* open_type - file or directory. */
1141 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1143 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1144 smb_action |= EXTENDED_OPLOCK_GRANTED;
1147 SSVAL(params,18,smb_action);
1150 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1152 SIVAL(params,20,inode);
1153 SSVAL(params,24,0); /* Padding. */
1154 if (flags & 8) {
1155 uint32 ea_size = estimate_ea_size(conn, fsp,
1156 fsp->fsp_name->base_name);
1157 SIVAL(params, 26, ea_size);
1158 } else {
1159 SIVAL(params, 26, 0);
1162 /* Send the required number of replies */
1163 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1164 out:
1165 TALLOC_FREE(smb_fname);
1168 /*********************************************************
1169 Routine to check if a given string matches exactly.
1170 as a special case a mask of "." does NOT match. That
1171 is required for correct wildcard semantics
1172 Case can be significant or not.
1173 **********************************************************/
1175 static bool exact_match(bool has_wild,
1176 bool case_sensitive,
1177 const char *str,
1178 const char *mask)
1180 if (mask[0] == '.' && mask[1] == 0) {
1181 return false;
1184 if (has_wild) {
1185 return false;
1188 if (case_sensitive) {
1189 return strcmp(str,mask)==0;
1190 } else {
1191 return StrCaseCmp(str,mask) == 0;
1195 /****************************************************************************
1196 Return the filetype for UNIX extensions.
1197 ****************************************************************************/
1199 static uint32 unix_filetype(mode_t mode)
1201 if(S_ISREG(mode))
1202 return UNIX_TYPE_FILE;
1203 else if(S_ISDIR(mode))
1204 return UNIX_TYPE_DIR;
1205 #ifdef S_ISLNK
1206 else if(S_ISLNK(mode))
1207 return UNIX_TYPE_SYMLINK;
1208 #endif
1209 #ifdef S_ISCHR
1210 else if(S_ISCHR(mode))
1211 return UNIX_TYPE_CHARDEV;
1212 #endif
1213 #ifdef S_ISBLK
1214 else if(S_ISBLK(mode))
1215 return UNIX_TYPE_BLKDEV;
1216 #endif
1217 #ifdef S_ISFIFO
1218 else if(S_ISFIFO(mode))
1219 return UNIX_TYPE_FIFO;
1220 #endif
1221 #ifdef S_ISSOCK
1222 else if(S_ISSOCK(mode))
1223 return UNIX_TYPE_SOCKET;
1224 #endif
1226 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1227 return UNIX_TYPE_UNKNOWN;
1230 /****************************************************************************
1231 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1232 ****************************************************************************/
1234 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1236 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1237 const SMB_STRUCT_STAT *psbuf,
1238 uint32 perms,
1239 enum perm_type ptype,
1240 mode_t *ret_perms)
1242 mode_t ret = 0;
1244 if (perms == SMB_MODE_NO_CHANGE) {
1245 if (!VALID_STAT(*psbuf)) {
1246 return NT_STATUS_INVALID_PARAMETER;
1247 } else {
1248 *ret_perms = psbuf->st_ex_mode;
1249 return NT_STATUS_OK;
1253 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1254 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1255 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1256 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1257 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1258 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1259 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1260 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1261 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1262 #ifdef S_ISVTX
1263 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1264 #endif
1265 #ifdef S_ISGID
1266 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1267 #endif
1268 #ifdef S_ISUID
1269 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1270 #endif
1272 switch (ptype) {
1273 case PERM_NEW_FILE:
1274 /* Apply mode mask */
1275 ret &= lp_create_mask(SNUM(conn));
1276 /* Add in force bits */
1277 ret |= lp_force_create_mode(SNUM(conn));
1278 break;
1279 case PERM_NEW_DIR:
1280 ret &= lp_dir_mask(SNUM(conn));
1281 /* Add in force bits */
1282 ret |= lp_force_dir_mode(SNUM(conn));
1283 break;
1284 case PERM_EXISTING_FILE:
1285 /* Apply mode mask */
1286 ret &= lp_security_mask(SNUM(conn));
1287 /* Add in force bits */
1288 ret |= lp_force_security_mode(SNUM(conn));
1289 break;
1290 case PERM_EXISTING_DIR:
1291 /* Apply mode mask */
1292 ret &= lp_dir_security_mask(SNUM(conn));
1293 /* Add in force bits */
1294 ret |= lp_force_dir_security_mode(SNUM(conn));
1295 break;
1298 *ret_perms = ret;
1299 return NT_STATUS_OK;
1302 /****************************************************************************
1303 Needed to show the msdfs symlinks as directories. Modifies psbuf
1304 to be a directory if it's a msdfs link.
1305 ****************************************************************************/
1307 static bool check_msdfs_link(connection_struct *conn,
1308 const char *pathname,
1309 SMB_STRUCT_STAT *psbuf)
1311 int saved_errno = errno;
1312 if(lp_host_msdfs() &&
1313 lp_msdfs_root(SNUM(conn)) &&
1314 is_msdfs_link(conn, pathname, psbuf)) {
1316 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1317 "as a directory\n",
1318 pathname));
1319 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1320 errno = saved_errno;
1321 return true;
1323 errno = saved_errno;
1324 return false;
1328 /****************************************************************************
1329 Get a level dependent lanman2 dir entry.
1330 ****************************************************************************/
1332 struct smbd_dirptr_lanman2_state {
1333 connection_struct *conn;
1334 uint32_t info_level;
1335 bool check_mangled_names;
1336 bool has_wild;
1337 bool got_exact_match;
1340 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1341 void *private_data,
1342 const char *dname,
1343 const char *mask,
1344 char **_fname)
1346 struct smbd_dirptr_lanman2_state *state =
1347 (struct smbd_dirptr_lanman2_state *)private_data;
1348 bool ok;
1349 char mangled_name[13]; /* mangled 8.3 name. */
1350 bool got_match;
1351 const char *fname;
1353 /* Mangle fname if it's an illegal name. */
1354 if (mangle_must_mangle(dname, state->conn->params)) {
1355 ok = name_to_8_3(dname, mangled_name,
1356 true, state->conn->params);
1357 if (!ok) {
1358 return false;
1360 fname = mangled_name;
1361 } else {
1362 fname = dname;
1365 got_match = exact_match(state->has_wild,
1366 state->conn->case_sensitive,
1367 fname, mask);
1368 state->got_exact_match = got_match;
1369 if (!got_match) {
1370 got_match = mask_match(fname, mask,
1371 state->conn->case_sensitive);
1374 if(!got_match && state->check_mangled_names &&
1375 !mangle_is_8_3(fname, false, state->conn->params)) {
1377 * It turns out that NT matches wildcards against
1378 * both long *and* short names. This may explain some
1379 * of the wildcard wierdness from old DOS clients
1380 * that some people have been seeing.... JRA.
1382 /* Force the mangling into 8.3. */
1383 ok = name_to_8_3(fname, mangled_name,
1384 false, state->conn->params);
1385 if (!ok) {
1386 return false;
1389 got_match = exact_match(state->has_wild,
1390 state->conn->case_sensitive,
1391 mangled_name, mask);
1392 state->got_exact_match = got_match;
1393 if (!got_match) {
1394 got_match = mask_match(mangled_name, mask,
1395 state->conn->case_sensitive);
1399 if (!got_match) {
1400 return false;
1403 *_fname = talloc_strdup(ctx, fname);
1404 if (*_fname == NULL) {
1405 return false;
1408 return true;
1411 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1412 void *private_data,
1413 struct smb_filename *smb_fname,
1414 uint32_t *_mode)
1416 struct smbd_dirptr_lanman2_state *state =
1417 (struct smbd_dirptr_lanman2_state *)private_data;
1418 bool ms_dfs_link = false;
1419 uint32_t mode = 0;
1421 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1422 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1423 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1424 "Couldn't lstat [%s] (%s)\n",
1425 smb_fname_str_dbg(smb_fname),
1426 strerror(errno)));
1427 return false;
1429 } else if (!VALID_STAT(smb_fname->st) &&
1430 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1431 /* Needed to show the msdfs symlinks as
1432 * directories */
1434 ms_dfs_link = check_msdfs_link(state->conn,
1435 smb_fname->base_name,
1436 &smb_fname->st);
1437 if (!ms_dfs_link) {
1438 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1439 "Couldn't stat [%s] (%s)\n",
1440 smb_fname_str_dbg(smb_fname),
1441 strerror(errno)));
1442 return false;
1446 if (ms_dfs_link) {
1447 mode = dos_mode_msdfs(state->conn, smb_fname);
1448 } else {
1449 mode = dos_mode(state->conn, smb_fname);
1452 *_mode = mode;
1453 return true;
1456 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1457 connection_struct *conn,
1458 uint16_t flags2,
1459 uint32_t info_level,
1460 struct ea_list *name_list,
1461 bool check_mangled_names,
1462 bool requires_resume_key,
1463 uint32_t mode,
1464 const char *fname,
1465 const struct smb_filename *smb_fname,
1466 uint64_t space_remaining,
1467 uint8_t align,
1468 bool do_pad,
1469 char *base_data,
1470 char **ppdata,
1471 char *end_data,
1472 bool *out_of_space,
1473 uint64_t *last_entry_off)
1475 char *p, *q, *pdata = *ppdata;
1476 uint32_t reskey=0;
1477 uint64_t file_size = 0;
1478 uint64_t allocation_size = 0;
1479 uint32_t len;
1480 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1481 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1482 time_t c_date = (time_t)0;
1483 char *nameptr;
1484 char *last_entry_ptr;
1485 bool was_8_3;
1486 uint32_t nt_extmode; /* Used for NT connections instead of mode */
1487 off_t off;
1488 off_t pad = 0;
1490 *out_of_space = false;
1492 ZERO_STRUCT(mdate_ts);
1493 ZERO_STRUCT(adate_ts);
1494 ZERO_STRUCT(create_date_ts);
1495 ZERO_STRUCT(cdate_ts);
1497 if (!(mode & aDIR)) {
1498 file_size = get_file_size_stat(&smb_fname->st);
1500 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1502 mdate_ts = smb_fname->st.st_ex_mtime;
1503 adate_ts = smb_fname->st.st_ex_atime;
1504 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1505 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1507 if (lp_dos_filetime_resolution(SNUM(conn))) {
1508 dos_filetime_timespec(&create_date_ts);
1509 dos_filetime_timespec(&mdate_ts);
1510 dos_filetime_timespec(&adate_ts);
1511 dos_filetime_timespec(&cdate_ts);
1514 create_date = convert_timespec_to_time_t(create_date_ts);
1515 mdate = convert_timespec_to_time_t(mdate_ts);
1516 adate = convert_timespec_to_time_t(adate_ts);
1517 c_date = convert_timespec_to_time_t(cdate_ts);
1519 /* align the record */
1520 off = PTR_DIFF(pdata, base_data);
1521 pad = (off + (align-1)) & ~(align-1);
1522 pad -= off;
1523 off += pad;
1524 /* initialize padding to 0 */
1525 memset(pdata, 0, pad);
1526 space_remaining -= pad;
1528 pdata += pad;
1529 p = pdata;
1530 last_entry_ptr = p;
1532 pad = 0;
1533 off = 0;
1535 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1537 switch (info_level) {
1538 case SMB_FIND_INFO_STANDARD:
1539 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1540 if(requires_resume_key) {
1541 SIVAL(p,0,reskey);
1542 p += 4;
1544 srv_put_dos_date2(p,0,create_date);
1545 srv_put_dos_date2(p,4,adate);
1546 srv_put_dos_date2(p,8,mdate);
1547 SIVAL(p,12,(uint32)file_size);
1548 SIVAL(p,16,(uint32)allocation_size);
1549 SSVAL(p,20,mode);
1550 p += 23;
1551 nameptr = p;
1552 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1553 p += ucs2_align(base_data, p, 0);
1555 len = srvstr_push(base_data, flags2, p,
1556 fname, PTR_DIFF(end_data, p),
1557 STR_TERMINATE);
1558 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1559 if (len > 2) {
1560 SCVAL(nameptr, -1, len - 2);
1561 } else {
1562 SCVAL(nameptr, -1, 0);
1564 } else {
1565 if (len > 1) {
1566 SCVAL(nameptr, -1, len - 1);
1567 } else {
1568 SCVAL(nameptr, -1, 0);
1571 p += len;
1572 break;
1574 case SMB_FIND_EA_SIZE:
1575 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1576 if (requires_resume_key) {
1577 SIVAL(p,0,reskey);
1578 p += 4;
1580 srv_put_dos_date2(p,0,create_date);
1581 srv_put_dos_date2(p,4,adate);
1582 srv_put_dos_date2(p,8,mdate);
1583 SIVAL(p,12,(uint32)file_size);
1584 SIVAL(p,16,(uint32)allocation_size);
1585 SSVAL(p,20,mode);
1587 unsigned int ea_size = estimate_ea_size(conn, NULL,
1588 smb_fname->base_name);
1589 SIVAL(p,22,ea_size); /* Extended attributes */
1591 p += 27;
1592 nameptr = p - 1;
1593 len = srvstr_push(base_data, flags2,
1594 p, fname, PTR_DIFF(end_data, p),
1595 STR_TERMINATE | STR_NOALIGN);
1596 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1597 if (len > 2) {
1598 len -= 2;
1599 } else {
1600 len = 0;
1602 } else {
1603 if (len > 1) {
1604 len -= 1;
1605 } else {
1606 len = 0;
1609 SCVAL(nameptr,0,len);
1610 p += len;
1611 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1612 break;
1614 case SMB_FIND_EA_LIST:
1616 struct ea_list *file_list = NULL;
1617 size_t ea_len = 0;
1619 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1620 if (!name_list) {
1621 return false;
1623 if (requires_resume_key) {
1624 SIVAL(p,0,reskey);
1625 p += 4;
1627 srv_put_dos_date2(p,0,create_date);
1628 srv_put_dos_date2(p,4,adate);
1629 srv_put_dos_date2(p,8,mdate);
1630 SIVAL(p,12,(uint32)file_size);
1631 SIVAL(p,16,(uint32)allocation_size);
1632 SSVAL(p,20,mode);
1633 p += 22; /* p now points to the EA area. */
1635 file_list = get_ea_list_from_file(ctx, conn, NULL,
1636 smb_fname->base_name,
1637 &ea_len);
1638 name_list = ea_list_union(name_list, file_list, &ea_len);
1640 /* We need to determine if this entry will fit in the space available. */
1641 /* Max string size is 255 bytes. */
1642 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1643 *out_of_space = true;
1644 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1645 return False; /* Not finished - just out of space */
1648 /* Push the ea_data followed by the name. */
1649 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1650 nameptr = p;
1651 len = srvstr_push(base_data, flags2,
1652 p + 1, fname, PTR_DIFF(end_data, p+1),
1653 STR_TERMINATE | STR_NOALIGN);
1654 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1655 if (len > 2) {
1656 len -= 2;
1657 } else {
1658 len = 0;
1660 } else {
1661 if (len > 1) {
1662 len -= 1;
1663 } else {
1664 len = 0;
1667 SCVAL(nameptr,0,len);
1668 p += len + 1;
1669 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1670 break;
1673 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1674 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1675 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1676 p += 4;
1677 SIVAL(p,0,reskey); p += 4;
1678 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1679 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1680 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1681 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1682 SOFF_T(p,0,file_size); p += 8;
1683 SOFF_T(p,0,allocation_size); p += 8;
1684 SIVAL(p,0,nt_extmode); p += 4;
1685 q = p; p += 4; /* q is placeholder for name length. */
1687 unsigned int ea_size = estimate_ea_size(conn, NULL,
1688 smb_fname->base_name);
1689 SIVAL(p,0,ea_size); /* Extended attributes */
1690 p += 4;
1692 /* Clear the short name buffer. This is
1693 * IMPORTANT as not doing so will trigger
1694 * a Win2k client bug. JRA.
1696 if (!was_8_3 && check_mangled_names) {
1697 char mangled_name[13]; /* mangled 8.3 name. */
1698 if (!name_to_8_3(fname,mangled_name,True,
1699 conn->params)) {
1700 /* Error - mangle failed ! */
1701 memset(mangled_name,'\0',12);
1703 mangled_name[12] = 0;
1704 len = srvstr_push(base_data, flags2,
1705 p+2, mangled_name, 24,
1706 STR_UPPER|STR_UNICODE);
1707 if (len < 24) {
1708 memset(p + 2 + len,'\0',24 - len);
1710 SSVAL(p, 0, len);
1711 } else {
1712 memset(p,'\0',26);
1714 p += 2 + 24;
1715 len = srvstr_push(base_data, flags2, p,
1716 fname, PTR_DIFF(end_data, p),
1717 STR_TERMINATE_ASCII);
1718 SIVAL(q,0,len);
1719 p += len;
1721 len = PTR_DIFF(p, pdata);
1722 pad = (len + (align-1)) & ~(align-1);
1724 * offset to the next entry, the caller
1725 * will overwrite it for the last entry
1726 * that's why we always include the padding
1728 SIVAL(pdata,0,pad);
1730 * set padding to zero
1732 if (do_pad) {
1733 memset(p, 0, pad - len);
1734 p = pdata + pad;
1735 } else {
1736 p = pdata + len;
1738 break;
1740 case SMB_FIND_FILE_DIRECTORY_INFO:
1741 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1742 p += 4;
1743 SIVAL(p,0,reskey); p += 4;
1744 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1745 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1746 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1747 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1748 SOFF_T(p,0,file_size); p += 8;
1749 SOFF_T(p,0,allocation_size); p += 8;
1750 SIVAL(p,0,nt_extmode); p += 4;
1751 len = srvstr_push(base_data, flags2,
1752 p + 4, fname, PTR_DIFF(end_data, p+4),
1753 STR_TERMINATE_ASCII);
1754 SIVAL(p,0,len);
1755 p += 4 + len;
1757 len = PTR_DIFF(p, pdata);
1758 pad = (len + (align-1)) & ~(align-1);
1760 * offset to the next entry, the caller
1761 * will overwrite it for the last entry
1762 * that's why we always include the padding
1764 SIVAL(pdata,0,pad);
1766 * set padding to zero
1768 if (do_pad) {
1769 memset(p, 0, pad - len);
1770 p = pdata + pad;
1771 } else {
1772 p = pdata + len;
1774 break;
1776 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1777 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1778 p += 4;
1779 SIVAL(p,0,reskey); p += 4;
1780 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1781 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1782 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1783 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1784 SOFF_T(p,0,file_size); p += 8;
1785 SOFF_T(p,0,allocation_size); p += 8;
1786 SIVAL(p,0,nt_extmode); p += 4;
1787 q = p; p += 4; /* q is placeholder for name length. */
1789 unsigned int ea_size = estimate_ea_size(conn, NULL,
1790 smb_fname->base_name);
1791 SIVAL(p,0,ea_size); /* Extended attributes */
1792 p +=4;
1794 len = srvstr_push(base_data, flags2, p,
1795 fname, PTR_DIFF(end_data, p),
1796 STR_TERMINATE_ASCII);
1797 SIVAL(q, 0, len);
1798 p += len;
1800 len = PTR_DIFF(p, pdata);
1801 pad = (len + (align-1)) & ~(align-1);
1803 * offset to the next entry, the caller
1804 * will overwrite it for the last entry
1805 * that's why we always include the padding
1807 SIVAL(pdata,0,pad);
1809 * set padding to zero
1811 if (do_pad) {
1812 memset(p, 0, pad - len);
1813 p = pdata + pad;
1814 } else {
1815 p = pdata + len;
1817 break;
1819 case SMB_FIND_FILE_NAMES_INFO:
1820 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1821 p += 4;
1822 SIVAL(p,0,reskey); p += 4;
1823 p += 4;
1824 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1825 acl on a dir (tridge) */
1826 len = srvstr_push(base_data, flags2, p,
1827 fname, PTR_DIFF(end_data, p),
1828 STR_TERMINATE_ASCII);
1829 SIVAL(p, -4, len);
1830 p += len;
1832 len = PTR_DIFF(p, pdata);
1833 pad = (len + (align-1)) & ~(align-1);
1835 * offset to the next entry, the caller
1836 * will overwrite it for the last entry
1837 * that's why we always include the padding
1839 SIVAL(pdata,0,pad);
1841 * set padding to zero
1843 if (do_pad) {
1844 memset(p, 0, pad - len);
1845 p = pdata + pad;
1846 } else {
1847 p = pdata + len;
1849 break;
1851 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1852 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1853 p += 4;
1854 SIVAL(p,0,reskey); p += 4;
1855 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1856 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1857 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1858 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1859 SOFF_T(p,0,file_size); p += 8;
1860 SOFF_T(p,0,allocation_size); p += 8;
1861 SIVAL(p,0,nt_extmode); p += 4;
1862 q = p; p += 4; /* q is placeholder for name length. */
1864 unsigned int ea_size = estimate_ea_size(conn, NULL,
1865 smb_fname->base_name);
1866 SIVAL(p,0,ea_size); /* Extended attributes */
1867 p +=4;
1869 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1870 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1871 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1872 len = srvstr_push(base_data, flags2, p,
1873 fname, PTR_DIFF(end_data, p),
1874 STR_TERMINATE_ASCII);
1875 SIVAL(q, 0, len);
1876 p += len;
1878 len = PTR_DIFF(p, pdata);
1879 pad = (len + (align-1)) & ~(align-1);
1881 * offset to the next entry, the caller
1882 * will overwrite it for the last entry
1883 * that's why we always include the padding
1885 SIVAL(pdata,0,pad);
1887 * set padding to zero
1889 if (do_pad) {
1890 memset(p, 0, pad - len);
1891 p = pdata + pad;
1892 } else {
1893 p = pdata + len;
1895 break;
1897 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1898 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1899 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1900 p += 4;
1901 SIVAL(p,0,reskey); p += 4;
1902 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1903 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1904 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1905 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1906 SOFF_T(p,0,file_size); p += 8;
1907 SOFF_T(p,0,allocation_size); p += 8;
1908 SIVAL(p,0,nt_extmode); p += 4;
1909 q = p; p += 4; /* q is placeholder for name length */
1911 unsigned int ea_size = estimate_ea_size(conn, NULL,
1912 smb_fname->base_name);
1913 SIVAL(p,0,ea_size); /* Extended attributes */
1914 p +=4;
1916 /* Clear the short name buffer. This is
1917 * IMPORTANT as not doing so will trigger
1918 * a Win2k client bug. JRA.
1920 if (!was_8_3 && check_mangled_names) {
1921 char mangled_name[13]; /* mangled 8.3 name. */
1922 if (!name_to_8_3(fname,mangled_name,True,
1923 conn->params)) {
1924 /* Error - mangle failed ! */
1925 memset(mangled_name,'\0',12);
1927 mangled_name[12] = 0;
1928 len = srvstr_push(base_data, flags2,
1929 p+2, mangled_name, 24,
1930 STR_UPPER|STR_UNICODE);
1931 SSVAL(p, 0, len);
1932 if (len < 24) {
1933 memset(p + 2 + len,'\0',24 - len);
1935 SSVAL(p, 0, len);
1936 } else {
1937 memset(p,'\0',26);
1939 p += 26;
1940 SSVAL(p,0,0); p += 2; /* Reserved ? */
1941 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1942 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1943 len = srvstr_push(base_data, flags2, p,
1944 fname, PTR_DIFF(end_data, p),
1945 STR_TERMINATE_ASCII);
1946 SIVAL(q,0,len);
1947 p += len;
1949 len = PTR_DIFF(p, pdata);
1950 pad = (len + (align-1)) & ~(align-1);
1952 * offset to the next entry, the caller
1953 * will overwrite it for the last entry
1954 * that's why we always include the padding
1956 SIVAL(pdata,0,pad);
1958 * set padding to zero
1960 if (do_pad) {
1961 memset(p, 0, pad - len);
1962 p = pdata + pad;
1963 } else {
1964 p = pdata + len;
1966 break;
1968 /* CIFS UNIX Extension. */
1970 case SMB_FIND_FILE_UNIX:
1971 case SMB_FIND_FILE_UNIX_INFO2:
1972 p+= 4;
1973 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1975 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1977 if (info_level == SMB_FIND_FILE_UNIX) {
1978 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1979 p = store_file_unix_basic(conn, p,
1980 NULL, &smb_fname->st);
1981 len = srvstr_push(base_data, flags2, p,
1982 fname, PTR_DIFF(end_data, p),
1983 STR_TERMINATE);
1984 } else {
1985 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1986 p = store_file_unix_basic_info2(conn, p,
1987 NULL, &smb_fname->st);
1988 nameptr = p;
1989 p += 4;
1990 len = srvstr_push(base_data, flags2, p, fname,
1991 PTR_DIFF(end_data, p), 0);
1992 SIVAL(nameptr, 0, len);
1995 p += len;
1997 len = PTR_DIFF(p, pdata);
1998 pad = (len + (align-1)) & ~(align-1);
2000 * offset to the next entry, the caller
2001 * will overwrite it for the last entry
2002 * that's why we always include the padding
2004 SIVAL(pdata,0,pad);
2006 * set padding to zero
2008 if (do_pad) {
2009 memset(p, 0, pad - len);
2010 p = pdata + pad;
2011 } else {
2012 p = pdata + len;
2014 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2016 break;
2018 default:
2019 return false;
2022 if (PTR_DIFF(p,pdata) > space_remaining) {
2023 *out_of_space = true;
2024 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
2025 return false; /* Not finished - just out of space */
2028 /* Setup the last entry pointer, as an offset from base_data */
2029 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2030 /* Advance the data pointer to the next slot */
2031 *ppdata = p;
2033 return true;
2036 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2037 connection_struct *conn,
2038 struct dptr_struct *dirptr,
2039 uint16 flags2,
2040 const char *path_mask,
2041 uint32 dirtype,
2042 int info_level,
2043 int requires_resume_key,
2044 bool dont_descend,
2045 bool ask_sharemode,
2046 uint8_t align,
2047 bool do_pad,
2048 char **ppdata,
2049 char *base_data,
2050 char *end_data,
2051 int space_remaining,
2052 bool *out_of_space,
2053 bool *got_exact_match,
2054 int *_last_entry_off,
2055 struct ea_list *name_list)
2057 const char *p;
2058 const char *mask = NULL;
2059 long prev_dirpos = 0;
2060 uint32_t mode = 0;
2061 char *fname = NULL;
2062 struct smb_filename *smb_fname = NULL;
2063 struct smbd_dirptr_lanman2_state state;
2064 bool ok;
2065 uint64_t last_entry_off = 0;
2067 ZERO_STRUCT(state);
2068 state.conn = conn;
2069 state.info_level = info_level;
2070 state.check_mangled_names = lp_manglednames(conn->params);
2071 state.has_wild = dptr_has_wild(dirptr);
2072 state.got_exact_match = false;
2074 *out_of_space = false;
2075 *got_exact_match = false;
2077 p = strrchr_m(path_mask,'/');
2078 if(p != NULL) {
2079 if(p[1] == '\0') {
2080 mask = "*.*";
2081 } else {
2082 mask = p+1;
2084 } else {
2085 mask = path_mask;
2088 ok = smbd_dirptr_get_entry(ctx,
2089 dirptr,
2090 mask,
2091 dirtype,
2092 dont_descend,
2093 ask_sharemode,
2094 smbd_dirptr_lanman2_match_fn,
2095 smbd_dirptr_lanman2_mode_fn,
2096 &state,
2097 &fname,
2098 &smb_fname,
2099 &mode,
2100 &prev_dirpos);
2101 if (!ok) {
2102 return false;
2105 *got_exact_match = state.got_exact_match;
2107 ok = smbd_marshall_dir_entry(ctx,
2108 conn,
2109 flags2,
2110 info_level,
2111 name_list,
2112 state.check_mangled_names,
2113 requires_resume_key,
2114 mode,
2115 fname,
2116 smb_fname,
2117 space_remaining,
2118 align,
2119 do_pad,
2120 base_data,
2121 ppdata,
2122 end_data,
2123 out_of_space,
2124 &last_entry_off);
2125 TALLOC_FREE(fname);
2126 TALLOC_FREE(smb_fname);
2127 if (*out_of_space) {
2128 dptr_SeekDir(dirptr, prev_dirpos);
2129 return false;
2131 if (!ok) {
2132 return false;
2135 *_last_entry_off = last_entry_off;
2136 return true;
2139 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2140 connection_struct *conn,
2141 struct dptr_struct *dirptr,
2142 uint16 flags2,
2143 const char *path_mask,
2144 uint32 dirtype,
2145 int info_level,
2146 int requires_resume_key,
2147 bool dont_descend,
2148 bool ask_sharemode,
2149 char **ppdata,
2150 char *base_data,
2151 char *end_data,
2152 int space_remaining,
2153 bool *out_of_space,
2154 bool *got_exact_match,
2155 int *last_entry_off,
2156 struct ea_list *name_list)
2158 bool resume_key = false;
2159 const uint8_t align = 4;
2160 const bool do_pad = true;
2162 if (requires_resume_key) {
2163 resume_key = true;
2166 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2167 path_mask, dirtype, info_level,
2168 resume_key, dont_descend, ask_sharemode,
2169 align, do_pad,
2170 ppdata, base_data, end_data,
2171 space_remaining,
2172 out_of_space, got_exact_match,
2173 last_entry_off, name_list);
2176 /****************************************************************************
2177 Reply to a TRANS2_FINDFIRST.
2178 ****************************************************************************/
2180 static void call_trans2findfirst(connection_struct *conn,
2181 struct smb_request *req,
2182 char **pparams, int total_params,
2183 char **ppdata, int total_data,
2184 unsigned int max_data_bytes)
2186 /* We must be careful here that we don't return more than the
2187 allowed number of data bytes. If this means returning fewer than
2188 maxentries then so be it. We assume that the redirector has
2189 enough room for the fixed number of parameter bytes it has
2190 requested. */
2191 struct smb_filename *smb_dname = NULL;
2192 char *params = *pparams;
2193 char *pdata = *ppdata;
2194 char *data_end;
2195 uint32 dirtype;
2196 int maxentries;
2197 uint16 findfirst_flags;
2198 bool close_after_first;
2199 bool close_if_end;
2200 bool requires_resume_key;
2201 int info_level;
2202 char *directory = NULL;
2203 char *mask = NULL;
2204 char *p;
2205 int last_entry_off=0;
2206 int dptr_num = -1;
2207 int numentries = 0;
2208 int i;
2209 bool finished = False;
2210 bool dont_descend = False;
2211 bool out_of_space = False;
2212 int space_remaining;
2213 bool mask_contains_wcard = False;
2214 struct ea_list *ea_list = NULL;
2215 NTSTATUS ntstatus = NT_STATUS_OK;
2216 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2217 TALLOC_CTX *ctx = talloc_tos();
2218 struct dptr_struct *dirptr = NULL;
2219 struct smbd_server_connection *sconn = smbd_server_conn;
2221 if (total_params < 13) {
2222 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2223 goto out;
2226 dirtype = SVAL(params,0);
2227 maxentries = SVAL(params,2);
2228 findfirst_flags = SVAL(params,4);
2229 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2230 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2231 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2232 info_level = SVAL(params,6);
2234 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2235 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2236 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2237 info_level, max_data_bytes));
2239 if (!maxentries) {
2240 /* W2K3 seems to treat zero as 1. */
2241 maxentries = 1;
2244 switch (info_level) {
2245 case SMB_FIND_INFO_STANDARD:
2246 case SMB_FIND_EA_SIZE:
2247 case SMB_FIND_EA_LIST:
2248 case SMB_FIND_FILE_DIRECTORY_INFO:
2249 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2250 case SMB_FIND_FILE_NAMES_INFO:
2251 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2252 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2253 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2254 break;
2255 case SMB_FIND_FILE_UNIX:
2256 case SMB_FIND_FILE_UNIX_INFO2:
2257 /* Always use filesystem for UNIX mtime query. */
2258 ask_sharemode = false;
2259 if (!lp_unix_extensions()) {
2260 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2261 goto out;
2263 break;
2264 default:
2265 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2266 goto out;
2269 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2270 params+12, total_params - 12,
2271 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2272 if (!NT_STATUS_IS_OK(ntstatus)) {
2273 reply_nterror(req, ntstatus);
2274 goto out;
2277 ntstatus = filename_convert(ctx, conn,
2278 req->flags2 & FLAGS2_DFS_PATHNAMES,
2279 directory,
2280 (UCF_SAVE_LCOMP |
2281 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2282 &mask_contains_wcard,
2283 &smb_dname);
2284 if (!NT_STATUS_IS_OK(ntstatus)) {
2285 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2286 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2287 ERRSRV, ERRbadpath);
2288 goto out;
2290 reply_nterror(req, ntstatus);
2291 goto out;
2294 mask = smb_dname->original_lcomp;
2296 directory = smb_dname->base_name;
2298 p = strrchr_m(directory,'/');
2299 if(p == NULL) {
2300 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2301 if((directory[0] == '.') && (directory[1] == '\0')) {
2302 mask = talloc_strdup(ctx,"*");
2303 if (!mask) {
2304 reply_nterror(req, NT_STATUS_NO_MEMORY);
2305 goto out;
2307 mask_contains_wcard = True;
2309 directory = talloc_strdup(talloc_tos(), "./");
2310 if (!directory) {
2311 reply_nterror(req, NT_STATUS_NO_MEMORY);
2312 goto out;
2314 } else {
2315 *p = 0;
2318 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2320 if (info_level == SMB_FIND_EA_LIST) {
2321 uint32 ea_size;
2323 if (total_data < 4) {
2324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2325 goto out;
2328 ea_size = IVAL(pdata,0);
2329 if (ea_size != total_data) {
2330 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2331 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2333 goto out;
2336 if (!lp_ea_support(SNUM(conn))) {
2337 reply_doserror(req, ERRDOS, ERReasnotsupported);
2338 goto out;
2341 /* Pull out the list of names. */
2342 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2343 if (!ea_list) {
2344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2345 goto out;
2349 *ppdata = (char *)SMB_REALLOC(
2350 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2351 if(*ppdata == NULL ) {
2352 reply_nterror(req, NT_STATUS_NO_MEMORY);
2353 goto out;
2355 pdata = *ppdata;
2356 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2358 /* Realloc the params space */
2359 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2360 if (*pparams == NULL) {
2361 reply_nterror(req, NT_STATUS_NO_MEMORY);
2362 goto out;
2364 params = *pparams;
2366 /* Save the wildcard match and attribs we are using on this directory -
2367 needed as lanman2 assumes these are being saved between calls */
2369 ntstatus = dptr_create(conn,
2370 directory,
2371 False,
2372 True,
2373 req->smbpid,
2374 mask,
2375 mask_contains_wcard,
2376 dirtype,
2377 &dirptr);
2379 if (!NT_STATUS_IS_OK(ntstatus)) {
2380 reply_nterror(req, ntstatus);
2381 goto out;
2384 dptr_num = dptr_dnum(dirptr);
2385 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2387 /* Initialize per TRANS2_FIND_FIRST operation data */
2388 dptr_init_search_op(dirptr);
2390 /* We don't need to check for VOL here as this is returned by
2391 a different TRANS2 call. */
2393 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2394 directory,lp_dontdescend(SNUM(conn))));
2395 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2396 dont_descend = True;
2398 p = pdata;
2399 space_remaining = max_data_bytes;
2400 out_of_space = False;
2402 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2403 bool got_exact_match = False;
2405 /* this is a heuristic to avoid seeking the dirptr except when
2406 absolutely necessary. It allows for a filename of about 40 chars */
2407 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2408 out_of_space = True;
2409 finished = False;
2410 } else {
2411 finished = !get_lanman2_dir_entry(ctx,
2412 conn,
2413 dirptr,
2414 req->flags2,
2415 mask,dirtype,info_level,
2416 requires_resume_key,dont_descend,
2417 ask_sharemode,
2418 &p,pdata,data_end,
2419 space_remaining, &out_of_space,
2420 &got_exact_match,
2421 &last_entry_off, ea_list);
2424 if (finished && out_of_space)
2425 finished = False;
2427 if (!finished && !out_of_space)
2428 numentries++;
2431 * As an optimisation if we know we aren't looking
2432 * for a wildcard name (ie. the name matches the wildcard exactly)
2433 * then we can finish on any (first) match.
2434 * This speeds up large directory searches. JRA.
2437 if(got_exact_match)
2438 finished = True;
2440 /* Ensure space_remaining never goes -ve. */
2441 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2442 space_remaining = 0;
2443 out_of_space = true;
2444 } else {
2445 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2449 /* Check if we can close the dirptr */
2450 if(close_after_first || (finished && close_if_end)) {
2451 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2452 dptr_close(sconn, &dptr_num);
2456 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2457 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2458 * the protocol level is less than NT1. Tested with smbclient. JRA.
2459 * This should fix the OS/2 client bug #2335.
2462 if(numentries == 0) {
2463 dptr_close(sconn, &dptr_num);
2464 if (Protocol < PROTOCOL_NT1) {
2465 reply_doserror(req, ERRDOS, ERRnofiles);
2466 goto out;
2467 } else {
2468 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2469 ERRDOS, ERRbadfile);
2470 goto out;
2474 /* At this point pdata points to numentries directory entries. */
2476 /* Set up the return parameter block */
2477 SSVAL(params,0,dptr_num);
2478 SSVAL(params,2,numentries);
2479 SSVAL(params,4,finished);
2480 SSVAL(params,6,0); /* Never an EA error */
2481 SSVAL(params,8,last_entry_off);
2483 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2484 max_data_bytes);
2486 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2487 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2488 if (!directory) {
2489 reply_nterror(req, NT_STATUS_NO_MEMORY);
2493 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2494 smb_fn_name(req->cmd),
2495 mask, directory, dirtype, numentries ) );
2498 * Force a name mangle here to ensure that the
2499 * mask as an 8.3 name is top of the mangled cache.
2500 * The reasons for this are subtle. Don't remove
2501 * this code unless you know what you are doing
2502 * (see PR#13758). JRA.
2505 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2506 char mangled_name[13];
2507 name_to_8_3(mask, mangled_name, True, conn->params);
2509 out:
2510 TALLOC_FREE(smb_dname);
2511 return;
2514 /****************************************************************************
2515 Reply to a TRANS2_FINDNEXT.
2516 ****************************************************************************/
2518 static void call_trans2findnext(connection_struct *conn,
2519 struct smb_request *req,
2520 char **pparams, int total_params,
2521 char **ppdata, int total_data,
2522 unsigned int max_data_bytes)
2524 /* We must be careful here that we don't return more than the
2525 allowed number of data bytes. If this means returning fewer than
2526 maxentries then so be it. We assume that the redirector has
2527 enough room for the fixed number of parameter bytes it has
2528 requested. */
2529 char *params = *pparams;
2530 char *pdata = *ppdata;
2531 char *data_end;
2532 int dptr_num;
2533 int maxentries;
2534 uint16 info_level;
2535 uint32 resume_key;
2536 uint16 findnext_flags;
2537 bool close_after_request;
2538 bool close_if_end;
2539 bool requires_resume_key;
2540 bool continue_bit;
2541 bool mask_contains_wcard = False;
2542 char *resume_name = NULL;
2543 const char *mask = NULL;
2544 const char *directory = NULL;
2545 char *p = NULL;
2546 uint16 dirtype;
2547 int numentries = 0;
2548 int i, last_entry_off=0;
2549 bool finished = False;
2550 bool dont_descend = False;
2551 bool out_of_space = False;
2552 int space_remaining;
2553 struct ea_list *ea_list = NULL;
2554 NTSTATUS ntstatus = NT_STATUS_OK;
2555 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2556 TALLOC_CTX *ctx = talloc_tos();
2557 struct dptr_struct *dirptr;
2558 struct smbd_server_connection *sconn = smbd_server_conn;
2560 if (total_params < 13) {
2561 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2562 return;
2565 dptr_num = SVAL(params,0);
2566 maxentries = SVAL(params,2);
2567 info_level = SVAL(params,4);
2568 resume_key = IVAL(params,6);
2569 findnext_flags = SVAL(params,10);
2570 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2571 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2572 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2573 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2575 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2576 params+12,
2577 total_params - 12, STR_TERMINATE, &ntstatus,
2578 &mask_contains_wcard);
2579 if (!NT_STATUS_IS_OK(ntstatus)) {
2580 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2581 complain (it thinks we're asking for the directory above the shared
2582 path or an invalid name). Catch this as the resume name is only compared, never used in
2583 a file access. JRA. */
2584 srvstr_pull_talloc(ctx, params, req->flags2,
2585 &resume_name, params+12,
2586 total_params - 12,
2587 STR_TERMINATE);
2589 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2590 reply_nterror(req, ntstatus);
2591 return;
2595 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2596 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2597 resume_key = %d resume name = %s continue=%d level = %d\n",
2598 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2599 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2601 if (!maxentries) {
2602 /* W2K3 seems to treat zero as 1. */
2603 maxentries = 1;
2606 switch (info_level) {
2607 case SMB_FIND_INFO_STANDARD:
2608 case SMB_FIND_EA_SIZE:
2609 case SMB_FIND_EA_LIST:
2610 case SMB_FIND_FILE_DIRECTORY_INFO:
2611 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2612 case SMB_FIND_FILE_NAMES_INFO:
2613 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2614 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2615 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2616 break;
2617 case SMB_FIND_FILE_UNIX:
2618 case SMB_FIND_FILE_UNIX_INFO2:
2619 /* Always use filesystem for UNIX mtime query. */
2620 ask_sharemode = false;
2621 if (!lp_unix_extensions()) {
2622 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2623 return;
2625 break;
2626 default:
2627 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2628 return;
2631 if (info_level == SMB_FIND_EA_LIST) {
2632 uint32 ea_size;
2634 if (total_data < 4) {
2635 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2636 return;
2639 ea_size = IVAL(pdata,0);
2640 if (ea_size != total_data) {
2641 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2642 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2643 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2644 return;
2647 if (!lp_ea_support(SNUM(conn))) {
2648 reply_doserror(req, ERRDOS, ERReasnotsupported);
2649 return;
2652 /* Pull out the list of names. */
2653 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2654 if (!ea_list) {
2655 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2656 return;
2660 *ppdata = (char *)SMB_REALLOC(
2661 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2662 if(*ppdata == NULL) {
2663 reply_nterror(req, NT_STATUS_NO_MEMORY);
2664 return;
2667 pdata = *ppdata;
2668 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2670 /* Realloc the params space */
2671 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2672 if(*pparams == NULL ) {
2673 reply_nterror(req, NT_STATUS_NO_MEMORY);
2674 return;
2677 params = *pparams;
2679 /* Check that the dptr is valid */
2680 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2681 reply_doserror(req, ERRDOS, ERRnofiles);
2682 return;
2685 directory = dptr_path(sconn, dptr_num);
2687 /* Get the wildcard mask from the dptr */
2688 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2689 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2690 reply_doserror(req, ERRDOS, ERRnofiles);
2691 return;
2694 mask = p;
2696 /* Get the attr mask from the dptr */
2697 dirtype = dptr_attr(sconn, dptr_num);
2699 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2700 dptr_num, mask, dirtype,
2701 (long)dirptr,
2702 dptr_TellDir(dirptr)));
2704 /* Initialize per TRANS2_FIND_NEXT operation data */
2705 dptr_init_search_op(dirptr);
2707 /* We don't need to check for VOL here as this is returned by
2708 a different TRANS2 call. */
2710 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2711 directory,lp_dontdescend(SNUM(conn))));
2712 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2713 dont_descend = True;
2715 p = pdata;
2716 space_remaining = max_data_bytes;
2717 out_of_space = False;
2720 * Seek to the correct position. We no longer use the resume key but
2721 * depend on the last file name instead.
2724 if(*resume_name && !continue_bit) {
2725 SMB_STRUCT_STAT st;
2727 long current_pos = 0;
2729 * Remember, name_to_8_3 is called by
2730 * get_lanman2_dir_entry(), so the resume name
2731 * could be mangled. Ensure we check the unmangled name.
2734 if (mangle_is_mangled(resume_name, conn->params)) {
2735 char *new_resume_name = NULL;
2736 mangle_lookup_name_from_8_3(ctx,
2737 resume_name,
2738 &new_resume_name,
2739 conn->params);
2740 if (new_resume_name) {
2741 resume_name = new_resume_name;
2746 * Fix for NT redirector problem triggered by resume key indexes
2747 * changing between directory scans. We now return a resume key of 0
2748 * and instead look for the filename to continue from (also given
2749 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2750 * findfirst/findnext (as is usual) then the directory pointer
2751 * should already be at the correct place.
2754 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2755 } /* end if resume_name && !continue_bit */
2757 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2758 bool got_exact_match = False;
2760 /* this is a heuristic to avoid seeking the dirptr except when
2761 absolutely necessary. It allows for a filename of about 40 chars */
2762 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2763 out_of_space = True;
2764 finished = False;
2765 } else {
2766 finished = !get_lanman2_dir_entry(ctx,
2767 conn,
2768 dirptr,
2769 req->flags2,
2770 mask,dirtype,info_level,
2771 requires_resume_key,dont_descend,
2772 ask_sharemode,
2773 &p,pdata,data_end,
2774 space_remaining, &out_of_space,
2775 &got_exact_match,
2776 &last_entry_off, ea_list);
2779 if (finished && out_of_space)
2780 finished = False;
2782 if (!finished && !out_of_space)
2783 numentries++;
2786 * As an optimisation if we know we aren't looking
2787 * for a wildcard name (ie. the name matches the wildcard exactly)
2788 * then we can finish on any (first) match.
2789 * This speeds up large directory searches. JRA.
2792 if(got_exact_match)
2793 finished = True;
2795 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2798 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2799 smb_fn_name(req->cmd),
2800 mask, directory, dirtype, numentries ) );
2802 /* Check if we can close the dirptr */
2803 if(close_after_request || (finished && close_if_end)) {
2804 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2805 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2808 /* Set up the return parameter block */
2809 SSVAL(params,0,numentries);
2810 SSVAL(params,2,finished);
2811 SSVAL(params,4,0); /* Never an EA error */
2812 SSVAL(params,6,last_entry_off);
2814 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2815 max_data_bytes);
2817 return;
2820 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2822 E_md4hash(lp_servicename(SNUM(conn)),objid);
2823 return objid;
2826 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2828 SMB_ASSERT(extended_info != NULL);
2830 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2831 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2832 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2833 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2834 #ifdef SAMBA_VERSION_REVISION
2835 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2836 #endif
2837 extended_info->samba_subversion = 0;
2838 #ifdef SAMBA_VERSION_RC_RELEASE
2839 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2840 #else
2841 #ifdef SAMBA_VERSION_PRE_RELEASE
2842 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2843 #endif
2844 #endif
2845 #ifdef SAMBA_VERSION_VENDOR_PATCH
2846 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2847 #endif
2848 extended_info->samba_gitcommitdate = 0;
2849 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2850 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2851 #endif
2853 memset(extended_info->samba_version_string, 0,
2854 sizeof(extended_info->samba_version_string));
2856 snprintf (extended_info->samba_version_string,
2857 sizeof(extended_info->samba_version_string),
2858 "%s", samba_version_string());
2861 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2862 TALLOC_CTX *mem_ctx,
2863 uint16_t info_level,
2864 uint16_t flags2,
2865 unsigned int max_data_bytes,
2866 char **ppdata,
2867 int *ret_data_len)
2869 char *pdata, *end_data;
2870 int data_len = 0, len;
2871 const char *vname = volume_label(SNUM(conn));
2872 int snum = SNUM(conn);
2873 char *fstype = lp_fstype(SNUM(conn));
2874 uint32 additional_flags = 0;
2875 struct smb_filename *smb_fname_dot = NULL;
2876 SMB_STRUCT_STAT st;
2877 NTSTATUS status;
2879 if (IS_IPC(conn)) {
2880 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2881 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2882 "info level (0x%x) on IPC$.\n",
2883 (unsigned int)info_level));
2884 return NT_STATUS_ACCESS_DENIED;
2888 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2890 status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL,
2891 &smb_fname_dot);
2892 if (!NT_STATUS_IS_OK(status)) {
2893 return status;
2896 if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) {
2897 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2898 TALLOC_FREE(smb_fname_dot);
2899 return map_nt_error_from_unix(errno);
2902 st = smb_fname_dot->st;
2903 TALLOC_FREE(smb_fname_dot);
2905 *ppdata = (char *)SMB_REALLOC(
2906 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2907 if (*ppdata == NULL) {
2908 return NT_STATUS_NO_MEMORY;
2911 pdata = *ppdata;
2912 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2913 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2915 switch (info_level) {
2916 case SMB_INFO_ALLOCATION:
2918 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2919 data_len = 18;
2920 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2921 return map_nt_error_from_unix(errno);
2924 block_size = lp_block_size(snum);
2925 if (bsize < block_size) {
2926 uint64_t factor = block_size/bsize;
2927 bsize = block_size;
2928 dsize /= factor;
2929 dfree /= factor;
2931 if (bsize > block_size) {
2932 uint64_t factor = bsize/block_size;
2933 bsize = block_size;
2934 dsize *= factor;
2935 dfree *= factor;
2937 bytes_per_sector = 512;
2938 sectors_per_unit = bsize/bytes_per_sector;
2940 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2941 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2942 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2944 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2945 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2946 SIVAL(pdata,l1_cUnit,dsize);
2947 SIVAL(pdata,l1_cUnitAvail,dfree);
2948 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2949 break;
2952 case SMB_INFO_VOLUME:
2953 /* Return volume name */
2955 * Add volume serial number - hash of a combination of
2956 * the called hostname and the service name.
2958 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2960 * Win2k3 and previous mess this up by sending a name length
2961 * one byte short. I believe only older clients (OS/2 Win9x) use
2962 * this call so try fixing this by adding a terminating null to
2963 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2965 len = srvstr_push(
2966 pdata, flags2,
2967 pdata+l2_vol_szVolLabel, vname,
2968 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2969 STR_NOALIGN|STR_TERMINATE);
2970 SCVAL(pdata,l2_vol_cch,len);
2971 data_len = l2_vol_szVolLabel + len;
2972 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2973 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2974 len, vname));
2975 break;
2977 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2978 case SMB_FS_ATTRIBUTE_INFORMATION:
2980 additional_flags = 0;
2981 #if defined(HAVE_SYS_QUOTAS)
2982 additional_flags |= FILE_VOLUME_QUOTAS;
2983 #endif
2985 if(lp_nt_acl_support(SNUM(conn))) {
2986 additional_flags |= FILE_PERSISTENT_ACLS;
2989 /* Capabilities are filled in at connection time through STATVFS call */
2990 additional_flags |= conn->fs_capabilities;
2991 additional_flags |= lp_parm_int(conn->params->service,
2992 "share", "fake_fscaps",
2995 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2996 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2997 additional_flags); /* FS ATTRIBUTES */
2999 SIVAL(pdata,4,255); /* Max filename component length */
3000 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3001 and will think we can't do long filenames */
3002 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3003 PTR_DIFF(end_data, pdata+12),
3004 STR_UNICODE);
3005 SIVAL(pdata,8,len);
3006 data_len = 12 + len;
3007 break;
3009 case SMB_QUERY_FS_LABEL_INFO:
3010 case SMB_FS_LABEL_INFORMATION:
3011 len = srvstr_push(pdata, flags2, pdata+4, vname,
3012 PTR_DIFF(end_data, pdata+4), 0);
3013 data_len = 4 + len;
3014 SIVAL(pdata,0,len);
3015 break;
3017 case SMB_QUERY_FS_VOLUME_INFO:
3018 case SMB_FS_VOLUME_INFORMATION:
3021 * Add volume serial number - hash of a combination of
3022 * the called hostname and the service name.
3024 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3025 (str_checksum(get_local_machine_name())<<16));
3027 /* Max label len is 32 characters. */
3028 len = srvstr_push(pdata, flags2, pdata+18, vname,
3029 PTR_DIFF(end_data, pdata+18),
3030 STR_UNICODE);
3031 SIVAL(pdata,12,len);
3032 data_len = 18+len;
3034 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3035 (int)strlen(vname),vname, lp_servicename(snum)));
3036 break;
3038 case SMB_QUERY_FS_SIZE_INFO:
3039 case SMB_FS_SIZE_INFORMATION:
3041 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3042 data_len = 24;
3043 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3044 return map_nt_error_from_unix(errno);
3046 block_size = lp_block_size(snum);
3047 if (bsize < block_size) {
3048 uint64_t factor = block_size/bsize;
3049 bsize = block_size;
3050 dsize /= factor;
3051 dfree /= factor;
3053 if (bsize > block_size) {
3054 uint64_t factor = bsize/block_size;
3055 bsize = block_size;
3056 dsize *= factor;
3057 dfree *= factor;
3059 bytes_per_sector = 512;
3060 sectors_per_unit = bsize/bytes_per_sector;
3061 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3062 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3063 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3064 SBIG_UINT(pdata,0,dsize);
3065 SBIG_UINT(pdata,8,dfree);
3066 SIVAL(pdata,16,sectors_per_unit);
3067 SIVAL(pdata,20,bytes_per_sector);
3068 break;
3071 case SMB_FS_FULL_SIZE_INFORMATION:
3073 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3074 data_len = 32;
3075 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3076 return map_nt_error_from_unix(errno);
3078 block_size = lp_block_size(snum);
3079 if (bsize < block_size) {
3080 uint64_t factor = block_size/bsize;
3081 bsize = block_size;
3082 dsize /= factor;
3083 dfree /= factor;
3085 if (bsize > block_size) {
3086 uint64_t factor = bsize/block_size;
3087 bsize = block_size;
3088 dsize *= factor;
3089 dfree *= factor;
3091 bytes_per_sector = 512;
3092 sectors_per_unit = bsize/bytes_per_sector;
3093 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3094 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3095 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3096 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3097 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3098 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3099 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3100 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3101 break;
3104 case SMB_QUERY_FS_DEVICE_INFO:
3105 case SMB_FS_DEVICE_INFORMATION:
3106 data_len = 8;
3107 SIVAL(pdata,0,0); /* dev type */
3108 SIVAL(pdata,4,0); /* characteristics */
3109 break;
3111 #ifdef HAVE_SYS_QUOTAS
3112 case SMB_FS_QUOTA_INFORMATION:
3114 * what we have to send --metze:
3116 * Unknown1: 24 NULL bytes
3117 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3118 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3119 * Quota Flags: 2 byte :
3120 * Unknown3: 6 NULL bytes
3122 * 48 bytes total
3124 * details for Quota Flags:
3126 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3127 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3128 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3129 * 0x0001 Enable Quotas: enable quota for this fs
3133 /* we need to fake up a fsp here,
3134 * because its not send in this call
3136 files_struct fsp;
3137 SMB_NTQUOTA_STRUCT quotas;
3139 ZERO_STRUCT(fsp);
3140 ZERO_STRUCT(quotas);
3142 fsp.conn = conn;
3143 fsp.fnum = -1;
3145 /* access check */
3146 if (conn->server_info->utok.uid != sec_initial_uid()) {
3147 DEBUG(0,("set_user_quota: access_denied "
3148 "service [%s] user [%s]\n",
3149 lp_servicename(SNUM(conn)),
3150 conn->server_info->unix_name));
3151 return NT_STATUS_ACCESS_DENIED;
3154 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3155 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3156 return map_nt_error_from_unix(errno);
3159 data_len = 48;
3161 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3162 lp_servicename(SNUM(conn))));
3164 /* Unknown1 24 NULL bytes*/
3165 SBIG_UINT(pdata,0,(uint64_t)0);
3166 SBIG_UINT(pdata,8,(uint64_t)0);
3167 SBIG_UINT(pdata,16,(uint64_t)0);
3169 /* Default Soft Quota 8 bytes */
3170 SBIG_UINT(pdata,24,quotas.softlim);
3172 /* Default Hard Quota 8 bytes */
3173 SBIG_UINT(pdata,32,quotas.hardlim);
3175 /* Quota flag 2 bytes */
3176 SSVAL(pdata,40,quotas.qflags);
3178 /* Unknown3 6 NULL bytes */
3179 SSVAL(pdata,42,0);
3180 SIVAL(pdata,44,0);
3182 break;
3184 #endif /* HAVE_SYS_QUOTAS */
3185 case SMB_FS_OBJECTID_INFORMATION:
3187 unsigned char objid[16];
3188 struct smb_extended_info extended_info;
3189 memcpy(pdata,create_volume_objectid(conn, objid),16);
3190 samba_extended_info_version (&extended_info);
3191 SIVAL(pdata,16,extended_info.samba_magic);
3192 SIVAL(pdata,20,extended_info.samba_version);
3193 SIVAL(pdata,24,extended_info.samba_subversion);
3194 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3195 memcpy(pdata+36,extended_info.samba_version_string,28);
3196 data_len = 64;
3197 break;
3201 * Query the version and capabilities of the CIFS UNIX extensions
3202 * in use.
3205 case SMB_QUERY_CIFS_UNIX_INFO:
3207 bool large_write = lp_min_receive_file_size() &&
3208 !srv_is_signing_active(smbd_server_conn);
3209 bool large_read = !srv_is_signing_active(smbd_server_conn);
3210 int encrypt_caps = 0;
3212 if (!lp_unix_extensions()) {
3213 return NT_STATUS_INVALID_LEVEL;
3216 switch (conn->encrypt_level) {
3217 case 0:
3218 encrypt_caps = 0;
3219 break;
3220 case 1:
3221 case Auto:
3222 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3223 break;
3224 case Required:
3225 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3226 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3227 large_write = false;
3228 large_read = false;
3229 break;
3232 data_len = 12;
3233 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3234 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3236 /* We have POSIX ACLs, pathname, encryption,
3237 * large read/write, and locking capability. */
3239 SBIG_UINT(pdata,4,((uint64_t)(
3240 CIFS_UNIX_POSIX_ACLS_CAP|
3241 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3242 CIFS_UNIX_FCNTL_LOCKS_CAP|
3243 CIFS_UNIX_EXTATTR_CAP|
3244 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3245 encrypt_caps|
3246 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3247 (large_write ?
3248 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3249 break;
3252 case SMB_QUERY_POSIX_FS_INFO:
3254 int rc;
3255 vfs_statvfs_struct svfs;
3257 if (!lp_unix_extensions()) {
3258 return NT_STATUS_INVALID_LEVEL;
3261 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3263 if (!rc) {
3264 data_len = 56;
3265 SIVAL(pdata,0,svfs.OptimalTransferSize);
3266 SIVAL(pdata,4,svfs.BlockSize);
3267 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3268 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3269 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3270 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3271 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3272 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3273 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3274 #ifdef EOPNOTSUPP
3275 } else if (rc == EOPNOTSUPP) {
3276 return NT_STATUS_INVALID_LEVEL;
3277 #endif /* EOPNOTSUPP */
3278 } else {
3279 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3280 return NT_STATUS_DOS(ERRSRV, ERRerror);
3282 break;
3285 case SMB_QUERY_POSIX_WHOAMI:
3287 uint32_t flags = 0;
3288 uint32_t sid_bytes;
3289 int i;
3291 if (!lp_unix_extensions()) {
3292 return NT_STATUS_INVALID_LEVEL;
3295 if (max_data_bytes < 40) {
3296 return NT_STATUS_BUFFER_TOO_SMALL;
3299 /* We ARE guest if global_sid_Builtin_Guests is
3300 * in our list of SIDs.
3302 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3303 conn->server_info->ptok)) {
3304 flags |= SMB_WHOAMI_GUEST;
3307 /* We are NOT guest if global_sid_Authenticated_Users
3308 * is in our list of SIDs.
3310 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3311 conn->server_info->ptok)) {
3312 flags &= ~SMB_WHOAMI_GUEST;
3315 /* NOTE: 8 bytes for UID/GID, irrespective of native
3316 * platform size. This matches
3317 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3319 data_len = 4 /* flags */
3320 + 4 /* flag mask */
3321 + 8 /* uid */
3322 + 8 /* gid */
3323 + 4 /* ngroups */
3324 + 4 /* num_sids */
3325 + 4 /* SID bytes */
3326 + 4 /* pad/reserved */
3327 + (conn->server_info->utok.ngroups * 8)
3328 /* groups list */
3329 + (conn->server_info->ptok->num_sids *
3330 SID_MAX_SIZE)
3331 /* SID list */;
3333 SIVAL(pdata, 0, flags);
3334 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3335 SBIG_UINT(pdata, 8,
3336 (uint64_t)conn->server_info->utok.uid);
3337 SBIG_UINT(pdata, 16,
3338 (uint64_t)conn->server_info->utok.gid);
3341 if (data_len >= max_data_bytes) {
3342 /* Potential overflow, skip the GIDs and SIDs. */
3344 SIVAL(pdata, 24, 0); /* num_groups */
3345 SIVAL(pdata, 28, 0); /* num_sids */
3346 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3347 SIVAL(pdata, 36, 0); /* reserved */
3349 data_len = 40;
3350 break;
3353 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3354 SIVAL(pdata, 28, conn->server_info->num_sids);
3356 /* We walk the SID list twice, but this call is fairly
3357 * infrequent, and I don't expect that it's performance
3358 * sensitive -- jpeach
3360 for (i = 0, sid_bytes = 0;
3361 i < conn->server_info->ptok->num_sids; ++i) {
3362 sid_bytes += ndr_size_dom_sid(
3363 &conn->server_info->ptok->user_sids[i],
3364 NULL,
3368 /* SID list byte count */
3369 SIVAL(pdata, 32, sid_bytes);
3371 /* 4 bytes pad/reserved - must be zero */
3372 SIVAL(pdata, 36, 0);
3373 data_len = 40;
3375 /* GID list */
3376 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3377 SBIG_UINT(pdata, data_len,
3378 (uint64_t)conn->server_info->utok.groups[i]);
3379 data_len += 8;
3382 /* SID list */
3383 for (i = 0;
3384 i < conn->server_info->ptok->num_sids; ++i) {
3385 int sid_len = ndr_size_dom_sid(
3386 &conn->server_info->ptok->user_sids[i],
3387 NULL,
3390 sid_linearize(pdata + data_len, sid_len,
3391 &conn->server_info->ptok->user_sids[i]);
3392 data_len += sid_len;
3395 break;
3398 case SMB_MAC_QUERY_FS_INFO:
3400 * Thursby MAC extension... ONLY on NTFS filesystems
3401 * once we do streams then we don't need this
3403 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3404 data_len = 88;
3405 SIVAL(pdata,84,0x100); /* Don't support mac... */
3406 break;
3408 /* drop through */
3409 default:
3410 return NT_STATUS_INVALID_LEVEL;
3413 *ret_data_len = data_len;
3414 return NT_STATUS_OK;
3417 /****************************************************************************
3418 Reply to a TRANS2_QFSINFO (query filesystem info).
3419 ****************************************************************************/
3421 static void call_trans2qfsinfo(connection_struct *conn,
3422 struct smb_request *req,
3423 char **pparams, int total_params,
3424 char **ppdata, int total_data,
3425 unsigned int max_data_bytes)
3427 char *params = *pparams;
3428 uint16_t info_level;
3429 int data_len = 0;
3430 NTSTATUS status;
3432 if (total_params < 2) {
3433 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3434 return;
3437 info_level = SVAL(params,0);
3439 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3440 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3441 DEBUG(0,("call_trans2qfsinfo: encryption required "
3442 "and info level 0x%x sent.\n",
3443 (unsigned int)info_level));
3444 exit_server_cleanly("encryption required "
3445 "on connection");
3446 return;
3450 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3452 status = smbd_do_qfsinfo(conn, req,
3453 info_level,
3454 req->flags2,
3455 max_data_bytes,
3456 ppdata, &data_len);
3457 if (!NT_STATUS_IS_OK(status)) {
3458 reply_nterror(req, status);
3459 return;
3462 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3463 max_data_bytes);
3465 DEBUG( 4, ( "%s info_level = %d\n",
3466 smb_fn_name(req->cmd), info_level) );
3468 return;
3471 /****************************************************************************
3472 Reply to a TRANS2_SETFSINFO (set filesystem info).
3473 ****************************************************************************/
3475 static void call_trans2setfsinfo(connection_struct *conn,
3476 struct smb_request *req,
3477 char **pparams, int total_params,
3478 char **ppdata, int total_data,
3479 unsigned int max_data_bytes)
3481 char *pdata = *ppdata;
3482 char *params = *pparams;
3483 uint16 info_level;
3485 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3487 /* */
3488 if (total_params < 4) {
3489 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3490 total_params));
3491 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3492 return;
3495 info_level = SVAL(params,2);
3497 if (IS_IPC(conn)) {
3498 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3499 info_level != SMB_SET_CIFS_UNIX_INFO) {
3500 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3501 "info level (0x%x) on IPC$.\n",
3502 (unsigned int)info_level));
3503 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3504 return;
3508 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3509 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3510 DEBUG(0,("call_trans2setfsinfo: encryption required "
3511 "and info level 0x%x sent.\n",
3512 (unsigned int)info_level));
3513 exit_server_cleanly("encryption required "
3514 "on connection");
3515 return;
3519 switch(info_level) {
3520 case SMB_SET_CIFS_UNIX_INFO:
3522 uint16 client_unix_major;
3523 uint16 client_unix_minor;
3524 uint32 client_unix_cap_low;
3525 uint32 client_unix_cap_high;
3527 if (!lp_unix_extensions()) {
3528 reply_nterror(req,
3529 NT_STATUS_INVALID_LEVEL);
3530 return;
3533 /* There should be 12 bytes of capabilities set. */
3534 if (total_data < 8) {
3535 reply_nterror(
3536 req,
3537 NT_STATUS_INVALID_PARAMETER);
3538 return;
3540 client_unix_major = SVAL(pdata,0);
3541 client_unix_minor = SVAL(pdata,2);
3542 client_unix_cap_low = IVAL(pdata,4);
3543 client_unix_cap_high = IVAL(pdata,8);
3544 /* Just print these values for now. */
3545 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3546 cap_low = 0x%x, cap_high = 0x%x\n",
3547 (unsigned int)client_unix_major,
3548 (unsigned int)client_unix_minor,
3549 (unsigned int)client_unix_cap_low,
3550 (unsigned int)client_unix_cap_high ));
3552 /* Here is where we must switch to posix pathname processing... */
3553 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3554 lp_set_posix_pathnames();
3555 mangle_change_to_posix();
3558 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3559 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3560 /* Client that knows how to do posix locks,
3561 * but not posix open/mkdir operations. Set a
3562 * default type for read/write checks. */
3564 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3567 break;
3570 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3572 NTSTATUS status;
3573 size_t param_len = 0;
3574 size_t data_len = total_data;
3576 if (!lp_unix_extensions()) {
3577 reply_nterror(
3578 req,
3579 NT_STATUS_INVALID_LEVEL);
3580 return;
3583 if (lp_smb_encrypt(SNUM(conn)) == false) {
3584 reply_nterror(
3585 req,
3586 NT_STATUS_NOT_SUPPORTED);
3587 return;
3590 DEBUG( 4,("call_trans2setfsinfo: "
3591 "request transport encryption.\n"));
3593 status = srv_request_encryption_setup(conn,
3594 (unsigned char **)ppdata,
3595 &data_len,
3596 (unsigned char **)pparams,
3597 &param_len);
3599 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3600 !NT_STATUS_IS_OK(status)) {
3601 reply_nterror(req, status);
3602 return;
3605 send_trans2_replies(conn, req,
3606 *pparams,
3607 param_len,
3608 *ppdata,
3609 data_len,
3610 max_data_bytes);
3612 if (NT_STATUS_IS_OK(status)) {
3613 /* Server-side transport
3614 * encryption is now *on*. */
3615 status = srv_encryption_start(conn);
3616 if (!NT_STATUS_IS_OK(status)) {
3617 exit_server_cleanly(
3618 "Failure in setting "
3619 "up encrypted transport");
3622 return;
3625 case SMB_FS_QUOTA_INFORMATION:
3627 files_struct *fsp = NULL;
3628 SMB_NTQUOTA_STRUCT quotas;
3630 ZERO_STRUCT(quotas);
3632 /* access check */
3633 if ((conn->server_info->utok.uid != sec_initial_uid())
3634 ||!CAN_WRITE(conn)) {
3635 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3636 lp_servicename(SNUM(conn)),
3637 conn->server_info->unix_name));
3638 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3639 return;
3642 /* note: normaly there're 48 bytes,
3643 * but we didn't use the last 6 bytes for now
3644 * --metze
3646 fsp = file_fsp(req, SVAL(params,0));
3648 if (!check_fsp_ntquota_handle(conn, req,
3649 fsp)) {
3650 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3651 reply_nterror(
3652 req, NT_STATUS_INVALID_HANDLE);
3653 return;
3656 if (total_data < 42) {
3657 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3658 total_data));
3659 reply_nterror(
3660 req,
3661 NT_STATUS_INVALID_PARAMETER);
3662 return;
3665 /* unknown_1 24 NULL bytes in pdata*/
3667 /* the soft quotas 8 bytes (uint64_t)*/
3668 quotas.softlim = (uint64_t)IVAL(pdata,24);
3669 #ifdef LARGE_SMB_OFF_T
3670 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3671 #else /* LARGE_SMB_OFF_T */
3672 if ((IVAL(pdata,28) != 0)&&
3673 ((quotas.softlim != 0xFFFFFFFF)||
3674 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3675 /* more than 32 bits? */
3676 reply_nterror(
3677 req,
3678 NT_STATUS_INVALID_PARAMETER);
3679 return;
3681 #endif /* LARGE_SMB_OFF_T */
3683 /* the hard quotas 8 bytes (uint64_t)*/
3684 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3685 #ifdef LARGE_SMB_OFF_T
3686 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3687 #else /* LARGE_SMB_OFF_T */
3688 if ((IVAL(pdata,36) != 0)&&
3689 ((quotas.hardlim != 0xFFFFFFFF)||
3690 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3691 /* more than 32 bits? */
3692 reply_nterror(
3693 req,
3694 NT_STATUS_INVALID_PARAMETER);
3695 return;
3697 #endif /* LARGE_SMB_OFF_T */
3699 /* quota_flags 2 bytes **/
3700 quotas.qflags = SVAL(pdata,40);
3702 /* unknown_2 6 NULL bytes follow*/
3704 /* now set the quotas */
3705 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3706 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3707 reply_nterror(req, map_nt_error_from_unix(errno));
3708 return;
3711 break;
3713 default:
3714 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3715 info_level));
3716 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3717 return;
3718 break;
3722 * sending this reply works fine,
3723 * but I'm not sure it's the same
3724 * like windows do...
3725 * --metze
3727 reply_outbuf(req, 10, 0);
3730 #if defined(HAVE_POSIX_ACLS)
3731 /****************************************************************************
3732 Utility function to count the number of entries in a POSIX acl.
3733 ****************************************************************************/
3735 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3737 unsigned int ace_count = 0;
3738 int entry_id = SMB_ACL_FIRST_ENTRY;
3739 SMB_ACL_ENTRY_T entry;
3741 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3742 /* get_next... */
3743 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3744 entry_id = SMB_ACL_NEXT_ENTRY;
3746 ace_count++;
3748 return ace_count;
3751 /****************************************************************************
3752 Utility function to marshall a POSIX acl into wire format.
3753 ****************************************************************************/
3755 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3757 int entry_id = SMB_ACL_FIRST_ENTRY;
3758 SMB_ACL_ENTRY_T entry;
3760 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3761 SMB_ACL_TAG_T tagtype;
3762 SMB_ACL_PERMSET_T permset;
3763 unsigned char perms = 0;
3764 unsigned int own_grp;
3766 /* get_next... */
3767 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3768 entry_id = SMB_ACL_NEXT_ENTRY;
3771 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3772 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3773 return False;
3776 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3777 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3778 return False;
3781 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3782 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3783 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3785 SCVAL(pdata,1,perms);
3787 switch (tagtype) {
3788 case SMB_ACL_USER_OBJ:
3789 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3790 own_grp = (unsigned int)pst->st_ex_uid;
3791 SIVAL(pdata,2,own_grp);
3792 SIVAL(pdata,6,0);
3793 break;
3794 case SMB_ACL_USER:
3796 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3797 if (!puid) {
3798 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3799 return False;
3801 own_grp = (unsigned int)*puid;
3802 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3803 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3804 SIVAL(pdata,2,own_grp);
3805 SIVAL(pdata,6,0);
3806 break;
3808 case SMB_ACL_GROUP_OBJ:
3809 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3810 own_grp = (unsigned int)pst->st_ex_gid;
3811 SIVAL(pdata,2,own_grp);
3812 SIVAL(pdata,6,0);
3813 break;
3814 case SMB_ACL_GROUP:
3816 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3817 if (!pgid) {
3818 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3819 return False;
3821 own_grp = (unsigned int)*pgid;
3822 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3823 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3824 SIVAL(pdata,2,own_grp);
3825 SIVAL(pdata,6,0);
3826 break;
3828 case SMB_ACL_MASK:
3829 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3830 SIVAL(pdata,2,0xFFFFFFFF);
3831 SIVAL(pdata,6,0xFFFFFFFF);
3832 break;
3833 case SMB_ACL_OTHER:
3834 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3835 SIVAL(pdata,2,0xFFFFFFFF);
3836 SIVAL(pdata,6,0xFFFFFFFF);
3837 break;
3838 default:
3839 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3840 return False;
3842 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3845 return True;
3847 #endif
3849 /****************************************************************************
3850 Store the FILE_UNIX_BASIC info.
3851 ****************************************************************************/
3853 static char *store_file_unix_basic(connection_struct *conn,
3854 char *pdata,
3855 files_struct *fsp,
3856 const SMB_STRUCT_STAT *psbuf)
3858 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3859 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3861 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3862 pdata += 8;
3864 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3865 pdata += 8;
3867 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3868 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3869 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3870 pdata += 24;
3872 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3873 SIVAL(pdata,4,0);
3874 pdata += 8;
3876 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3877 SIVAL(pdata,4,0);
3878 pdata += 8;
3880 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3881 pdata += 4;
3883 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3884 SIVAL(pdata,4,0);
3885 pdata += 8;
3887 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3888 SIVAL(pdata,4,0);
3889 pdata += 8;
3891 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3892 pdata += 8;
3894 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3895 SIVAL(pdata,4,0);
3896 pdata += 8;
3898 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3899 SIVAL(pdata,4,0);
3900 pdata += 8;
3902 return pdata;
3905 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3906 * the chflags(2) (or equivalent) flags.
3908 * XXX: this really should be behind the VFS interface. To do this, we would
3909 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3910 * Each VFS module could then implement its own mapping as appropriate for the
3911 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3913 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3914 info2_flags_map[] =
3916 #ifdef UF_NODUMP
3917 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3918 #endif
3920 #ifdef UF_IMMUTABLE
3921 { UF_IMMUTABLE, EXT_IMMUTABLE },
3922 #endif
3924 #ifdef UF_APPEND
3925 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3926 #endif
3928 #ifdef UF_HIDDEN
3929 { UF_HIDDEN, EXT_HIDDEN },
3930 #endif
3932 /* Do not remove. We need to guarantee that this array has at least one
3933 * entry to build on HP-UX.
3935 { 0, 0 }
3939 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3940 uint32 *smb_fflags, uint32 *smb_fmask)
3942 int i;
3944 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3945 *smb_fmask |= info2_flags_map[i].smb_fflag;
3946 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3947 *smb_fflags |= info2_flags_map[i].smb_fflag;
3952 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3953 const uint32 smb_fflags,
3954 const uint32 smb_fmask,
3955 int *stat_fflags)
3957 uint32 max_fmask = 0;
3958 int i;
3960 *stat_fflags = psbuf->st_ex_flags;
3962 /* For each flags requested in smb_fmask, check the state of the
3963 * corresponding flag in smb_fflags and set or clear the matching
3964 * stat flag.
3967 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3968 max_fmask |= info2_flags_map[i].smb_fflag;
3969 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3970 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3971 *stat_fflags |= info2_flags_map[i].stat_fflag;
3972 } else {
3973 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3978 /* If smb_fmask is asking to set any bits that are not supported by
3979 * our flag mappings, we should fail.
3981 if ((smb_fmask & max_fmask) != smb_fmask) {
3982 return False;
3985 return True;
3989 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3990 * of file flags and birth (create) time.
3992 static char *store_file_unix_basic_info2(connection_struct *conn,
3993 char *pdata,
3994 files_struct *fsp,
3995 const SMB_STRUCT_STAT *psbuf)
3997 uint32 file_flags = 0;
3998 uint32 flags_mask = 0;
4000 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4002 /* Create (birth) time 64 bit */
4003 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4004 pdata += 8;
4006 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4007 SIVAL(pdata, 0, file_flags); /* flags */
4008 SIVAL(pdata, 4, flags_mask); /* mask */
4009 pdata += 8;
4011 return pdata;
4014 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4015 const struct stream_struct *streams,
4016 char *data,
4017 unsigned int max_data_bytes,
4018 unsigned int *data_size)
4020 unsigned int i;
4021 unsigned int ofs = 0;
4023 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4024 unsigned int next_offset;
4025 size_t namelen;
4026 smb_ucs2_t *namebuf;
4028 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4029 streams[i].name, &namelen) ||
4030 namelen <= 2)
4032 return NT_STATUS_INVALID_PARAMETER;
4036 * name_buf is now null-terminated, we need to marshall as not
4037 * terminated
4040 namelen -= 2;
4042 SIVAL(data, ofs+4, namelen);
4043 SOFF_T(data, ofs+8, streams[i].size);
4044 SOFF_T(data, ofs+16, streams[i].alloc_size);
4045 memcpy(data+ofs+24, namebuf, namelen);
4046 TALLOC_FREE(namebuf);
4048 next_offset = ofs + 24 + namelen;
4050 if (i == num_streams-1) {
4051 SIVAL(data, ofs, 0);
4053 else {
4054 unsigned int align = ndr_align_size(next_offset, 8);
4056 memset(data+next_offset, 0, align);
4057 next_offset += align;
4059 SIVAL(data, ofs, next_offset - ofs);
4060 ofs = next_offset;
4063 ofs = next_offset;
4066 *data_size = ofs;
4068 return NT_STATUS_OK;
4071 /****************************************************************************
4072 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4073 ****************************************************************************/
4075 static void call_trans2qpipeinfo(connection_struct *conn,
4076 struct smb_request *req,
4077 unsigned int tran_call,
4078 char **pparams, int total_params,
4079 char **ppdata, int total_data,
4080 unsigned int max_data_bytes)
4082 char *params = *pparams;
4083 char *pdata = *ppdata;
4084 unsigned int data_size = 0;
4085 unsigned int param_size = 2;
4086 uint16 info_level;
4087 files_struct *fsp;
4089 if (!params) {
4090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4091 return;
4094 if (total_params < 4) {
4095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4096 return;
4099 fsp = file_fsp(req, SVAL(params,0));
4100 if (!fsp_is_np(fsp)) {
4101 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4102 return;
4105 info_level = SVAL(params,2);
4107 *pparams = (char *)SMB_REALLOC(*pparams,2);
4108 if (*pparams == NULL) {
4109 reply_nterror(req, NT_STATUS_NO_MEMORY);
4110 return;
4112 params = *pparams;
4113 SSVAL(params,0,0);
4114 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4115 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4116 if (*ppdata == NULL ) {
4117 reply_nterror(req, NT_STATUS_NO_MEMORY);
4118 return;
4120 pdata = *ppdata;
4122 switch (info_level) {
4123 case SMB_FILE_STANDARD_INFORMATION:
4124 memset(pdata,0,24);
4125 SOFF_T(pdata,0,4096LL);
4126 SIVAL(pdata,16,1);
4127 SIVAL(pdata,20,1);
4128 data_size = 24;
4129 break;
4131 default:
4132 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4133 return;
4136 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4137 max_data_bytes);
4139 return;
4142 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4143 TALLOC_CTX *mem_ctx,
4144 uint16_t info_level,
4145 files_struct *fsp,
4146 struct smb_filename *smb_fname,
4147 bool delete_pending,
4148 struct timespec write_time_ts,
4149 bool ms_dfs_link,
4150 struct ea_list *ea_list,
4151 int lock_data_count,
4152 char *lock_data,
4153 uint16_t flags2,
4154 unsigned int max_data_bytes,
4155 char **ppdata,
4156 unsigned int *pdata_size)
4158 char *pdata = *ppdata;
4159 char *dstart, *dend;
4160 unsigned int data_size;
4161 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4162 time_t create_time, mtime, atime, c_time;
4163 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4164 char *p;
4165 char *base_name;
4166 char *dos_fname;
4167 int mode;
4168 int nlink;
4169 NTSTATUS status;
4170 uint64_t file_size = 0;
4171 uint64_t pos = 0;
4172 uint64_t allocation_size = 0;
4173 uint64_t file_index = 0;
4174 uint32_t access_mask = 0;
4176 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4177 return NT_STATUS_INVALID_LEVEL;
4180 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4181 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4182 info_level, max_data_bytes));
4184 if (ms_dfs_link) {
4185 mode = dos_mode_msdfs(conn, smb_fname);
4186 } else {
4187 mode = dos_mode(conn, smb_fname);
4189 if (!mode)
4190 mode = FILE_ATTRIBUTE_NORMAL;
4192 nlink = psbuf->st_ex_nlink;
4194 if (nlink && (mode&aDIR)) {
4195 nlink = 1;
4198 if ((nlink > 0) && delete_pending) {
4199 nlink -= 1;
4202 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4203 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4204 if (*ppdata == NULL) {
4205 return NT_STATUS_NO_MEMORY;
4207 pdata = *ppdata;
4208 dstart = pdata;
4209 dend = dstart + data_size - 1;
4211 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4212 update_stat_ex_mtime(psbuf, write_time_ts);
4215 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4216 mtime_ts = psbuf->st_ex_mtime;
4217 atime_ts = psbuf->st_ex_atime;
4218 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4220 if (lp_dos_filetime_resolution(SNUM(conn))) {
4221 dos_filetime_timespec(&create_time_ts);
4222 dos_filetime_timespec(&mtime_ts);
4223 dos_filetime_timespec(&atime_ts);
4224 dos_filetime_timespec(&ctime_ts);
4227 create_time = convert_timespec_to_time_t(create_time_ts);
4228 mtime = convert_timespec_to_time_t(mtime_ts);
4229 atime = convert_timespec_to_time_t(atime_ts);
4230 c_time = convert_timespec_to_time_t(ctime_ts);
4232 p = strrchr_m(smb_fname->base_name,'/');
4233 if (!p)
4234 base_name = smb_fname->base_name;
4235 else
4236 base_name = p+1;
4238 /* NT expects the name to be in an exact form of the *full*
4239 filename. See the trans2 torture test */
4240 if (ISDOT(base_name)) {
4241 dos_fname = talloc_strdup(mem_ctx, "\\");
4242 if (!dos_fname) {
4243 return NT_STATUS_NO_MEMORY;
4245 } else {
4246 dos_fname = talloc_asprintf(mem_ctx,
4247 "\\%s",
4248 smb_fname->base_name);
4249 if (!dos_fname) {
4250 return NT_STATUS_NO_MEMORY;
4252 if (is_ntfs_stream_smb_fname(smb_fname)) {
4253 dos_fname = talloc_asprintf(dos_fname, "%s",
4254 smb_fname->stream_name);
4255 if (!dos_fname) {
4256 return NT_STATUS_NO_MEMORY;
4260 string_replace(dos_fname, '/', '\\');
4263 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4265 if (!fsp) {
4266 /* Do we have this path open ? */
4267 files_struct *fsp1;
4268 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4269 fsp1 = file_find_di_first(fileid);
4270 if (fsp1 && fsp1->initial_allocation_size) {
4271 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4275 if (!(mode & aDIR)) {
4276 file_size = get_file_size_stat(psbuf);
4279 if (fsp) {
4280 pos = fsp->fh->position_information;
4283 if (fsp) {
4284 access_mask = fsp->access_mask;
4285 } else {
4286 /* GENERIC_EXECUTE mapping from Windows */
4287 access_mask = 0x12019F;
4290 /* This should be an index number - looks like
4291 dev/ino to me :-)
4293 I think this causes us to fail the IFSKIT
4294 BasicFileInformationTest. -tpot */
4295 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4296 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4298 switch (info_level) {
4299 case SMB_INFO_STANDARD:
4300 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4301 data_size = 22;
4302 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4303 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4304 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4305 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4306 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4307 SSVAL(pdata,l1_attrFile,mode);
4308 break;
4310 case SMB_INFO_QUERY_EA_SIZE:
4312 unsigned int ea_size =
4313 estimate_ea_size(conn, fsp,
4314 smb_fname->base_name);
4315 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4316 data_size = 26;
4317 srv_put_dos_date2(pdata,0,create_time);
4318 srv_put_dos_date2(pdata,4,atime);
4319 srv_put_dos_date2(pdata,8,mtime); /* write time */
4320 SIVAL(pdata,12,(uint32)file_size);
4321 SIVAL(pdata,16,(uint32)allocation_size);
4322 SSVAL(pdata,20,mode);
4323 SIVAL(pdata,22,ea_size);
4324 break;
4327 case SMB_INFO_IS_NAME_VALID:
4328 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4329 if (fsp) {
4330 /* os/2 needs this ? really ?*/
4331 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4333 /* This is only reached for qpathinfo */
4334 data_size = 0;
4335 break;
4337 case SMB_INFO_QUERY_EAS_FROM_LIST:
4339 size_t total_ea_len = 0;
4340 struct ea_list *ea_file_list = NULL;
4342 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4344 ea_file_list =
4345 get_ea_list_from_file(mem_ctx, conn, fsp,
4346 smb_fname->base_name,
4347 &total_ea_len);
4348 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4350 if (!ea_list || (total_ea_len > data_size)) {
4351 data_size = 4;
4352 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4353 break;
4356 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4357 break;
4360 case SMB_INFO_QUERY_ALL_EAS:
4362 /* We have data_size bytes to put EA's into. */
4363 size_t total_ea_len = 0;
4365 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4367 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4368 smb_fname->base_name,
4369 &total_ea_len);
4370 if (!ea_list || (total_ea_len > data_size)) {
4371 data_size = 4;
4372 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4373 break;
4376 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4377 break;
4380 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4382 /* We have data_size bytes to put EA's into. */
4383 size_t total_ea_len = 0;
4384 struct ea_list *ea_file_list = NULL;
4386 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4388 /*TODO: add filtering and index handling */
4390 ea_file_list =
4391 get_ea_list_from_file(mem_ctx, conn, fsp,
4392 smb_fname->base_name,
4393 &total_ea_len);
4394 if (!ea_file_list) {
4395 return NT_STATUS_NO_EAS_ON_FILE;
4398 status = fill_ea_chained_buffer(mem_ctx,
4399 pdata,
4400 data_size,
4401 &data_size,
4402 conn, ea_file_list);
4403 if (!NT_STATUS_IS_OK(status)) {
4404 return status;
4406 break;
4409 case SMB_FILE_BASIC_INFORMATION:
4410 case SMB_QUERY_FILE_BASIC_INFO:
4412 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4413 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4414 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4415 } else {
4416 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4417 data_size = 40;
4418 SIVAL(pdata,36,0);
4420 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4421 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4422 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4423 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4424 SIVAL(pdata,32,mode);
4426 DEBUG(5,("SMB_QFBI - "));
4427 DEBUG(5,("create: %s ", ctime(&create_time)));
4428 DEBUG(5,("access: %s ", ctime(&atime)));
4429 DEBUG(5,("write: %s ", ctime(&mtime)));
4430 DEBUG(5,("change: %s ", ctime(&c_time)));
4431 DEBUG(5,("mode: %x\n", mode));
4432 break;
4434 case SMB_FILE_STANDARD_INFORMATION:
4435 case SMB_QUERY_FILE_STANDARD_INFO:
4437 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4438 data_size = 24;
4439 SOFF_T(pdata,0,allocation_size);
4440 SOFF_T(pdata,8,file_size);
4441 SIVAL(pdata,16,nlink);
4442 SCVAL(pdata,20,delete_pending?1:0);
4443 SCVAL(pdata,21,(mode&aDIR)?1:0);
4444 SSVAL(pdata,22,0); /* Padding. */
4445 break;
4447 case SMB_FILE_EA_INFORMATION:
4448 case SMB_QUERY_FILE_EA_INFO:
4450 unsigned int ea_size =
4451 estimate_ea_size(conn, fsp, smb_fname->base_name);
4452 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4453 data_size = 4;
4454 SIVAL(pdata,0,ea_size);
4455 break;
4458 /* Get the 8.3 name - used if NT SMB was negotiated. */
4459 case SMB_QUERY_FILE_ALT_NAME_INFO:
4460 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4462 int len;
4463 char mangled_name[13];
4464 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4465 if (!name_to_8_3(base_name,mangled_name,
4466 True,conn->params)) {
4467 return NT_STATUS_NO_MEMORY;
4469 len = srvstr_push(dstart, flags2,
4470 pdata+4, mangled_name,
4471 PTR_DIFF(dend, pdata+4),
4472 STR_UNICODE);
4473 data_size = 4 + len;
4474 SIVAL(pdata,0,len);
4475 break;
4478 case SMB_QUERY_FILE_NAME_INFO:
4480 int len;
4482 this must be *exactly* right for ACLs on mapped drives to work
4484 len = srvstr_push(dstart, flags2,
4485 pdata+4, dos_fname,
4486 PTR_DIFF(dend, pdata+4),
4487 STR_UNICODE);
4488 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4489 data_size = 4 + len;
4490 SIVAL(pdata,0,len);
4491 break;
4494 case SMB_FILE_ALLOCATION_INFORMATION:
4495 case SMB_QUERY_FILE_ALLOCATION_INFO:
4496 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4497 data_size = 8;
4498 SOFF_T(pdata,0,allocation_size);
4499 break;
4501 case SMB_FILE_END_OF_FILE_INFORMATION:
4502 case SMB_QUERY_FILE_END_OF_FILEINFO:
4503 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4504 data_size = 8;
4505 SOFF_T(pdata,0,file_size);
4506 break;
4508 case SMB_QUERY_FILE_ALL_INFO:
4509 case SMB_FILE_ALL_INFORMATION:
4511 int len;
4512 unsigned int ea_size =
4513 estimate_ea_size(conn, fsp, smb_fname->base_name);
4514 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4515 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4516 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4517 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4518 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4519 SIVAL(pdata,32,mode);
4520 SIVAL(pdata,36,0); /* padding. */
4521 pdata += 40;
4522 SOFF_T(pdata,0,allocation_size);
4523 SOFF_T(pdata,8,file_size);
4524 SIVAL(pdata,16,nlink);
4525 SCVAL(pdata,20,delete_pending);
4526 SCVAL(pdata,21,(mode&aDIR)?1:0);
4527 SSVAL(pdata,22,0);
4528 pdata += 24;
4529 SIVAL(pdata,0,ea_size);
4530 pdata += 4; /* EA info */
4531 len = srvstr_push(dstart, flags2,
4532 pdata+4, dos_fname,
4533 PTR_DIFF(dend, pdata+4),
4534 STR_UNICODE);
4535 SIVAL(pdata,0,len);
4536 pdata += 4 + len;
4537 data_size = PTR_DIFF(pdata,(*ppdata));
4538 break;
4541 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4543 int len;
4544 unsigned int ea_size =
4545 estimate_ea_size(conn, fsp, smb_fname->base_name);
4546 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4547 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4548 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4549 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4550 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4551 SIVAL(pdata, 0x20, mode);
4552 SIVAL(pdata, 0x24, 0); /* padding. */
4553 SBVAL(pdata, 0x28, allocation_size);
4554 SBVAL(pdata, 0x30, file_size);
4555 SIVAL(pdata, 0x38, nlink);
4556 SCVAL(pdata, 0x3C, delete_pending);
4557 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4558 SSVAL(pdata, 0x3E, 0); /* padding */
4559 SBVAL(pdata, 0x40, file_index);
4560 SIVAL(pdata, 0x48, ea_size);
4561 SIVAL(pdata, 0x4C, access_mask);
4562 SBVAL(pdata, 0x50, pos);
4563 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4564 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4566 pdata += 0x60;
4568 len = srvstr_push(dstart, flags2,
4569 pdata+4, dos_fname,
4570 PTR_DIFF(dend, pdata+4),
4571 STR_UNICODE);
4572 SIVAL(pdata,0,len);
4573 pdata += 4 + len;
4574 data_size = PTR_DIFF(pdata,(*ppdata));
4575 break;
4577 case SMB_FILE_INTERNAL_INFORMATION:
4579 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4580 SBVAL(pdata, 0, file_index);
4581 data_size = 8;
4582 break;
4584 case SMB_FILE_ACCESS_INFORMATION:
4585 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4586 SIVAL(pdata, 0, access_mask);
4587 data_size = 4;
4588 break;
4590 case SMB_FILE_NAME_INFORMATION:
4591 /* Pathname with leading '\'. */
4593 size_t byte_len;
4594 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4595 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4596 SIVAL(pdata,0,byte_len);
4597 data_size = 4 + byte_len;
4598 break;
4601 case SMB_FILE_DISPOSITION_INFORMATION:
4602 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4603 data_size = 1;
4604 SCVAL(pdata,0,delete_pending);
4605 break;
4607 case SMB_FILE_POSITION_INFORMATION:
4608 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4609 data_size = 8;
4610 SOFF_T(pdata,0,pos);
4611 break;
4613 case SMB_FILE_MODE_INFORMATION:
4614 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4615 SIVAL(pdata,0,mode);
4616 data_size = 4;
4617 break;
4619 case SMB_FILE_ALIGNMENT_INFORMATION:
4620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4621 SIVAL(pdata,0,0); /* No alignment needed. */
4622 data_size = 4;
4623 break;
4626 * NT4 server just returns "invalid query" to this - if we try
4627 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4628 * want this. JRA.
4630 /* The first statement above is false - verified using Thursby
4631 * client against NT4 -- gcolley.
4633 case SMB_QUERY_FILE_STREAM_INFO:
4634 case SMB_FILE_STREAM_INFORMATION: {
4635 unsigned int num_streams;
4636 struct stream_struct *streams;
4638 DEBUG(10,("smbd_do_qfilepathinfo: "
4639 "SMB_FILE_STREAM_INFORMATION\n"));
4641 if (is_ntfs_stream_smb_fname(smb_fname)) {
4642 return NT_STATUS_INVALID_PARAMETER;
4645 status = SMB_VFS_STREAMINFO(
4646 conn, fsp, smb_fname->base_name, talloc_tos(),
4647 &num_streams, &streams);
4649 if (!NT_STATUS_IS_OK(status)) {
4650 DEBUG(10, ("could not get stream info: %s\n",
4651 nt_errstr(status)));
4652 return status;
4655 status = marshall_stream_info(num_streams, streams,
4656 pdata, max_data_bytes,
4657 &data_size);
4659 if (!NT_STATUS_IS_OK(status)) {
4660 DEBUG(10, ("marshall_stream_info failed: %s\n",
4661 nt_errstr(status)));
4662 return status;
4665 TALLOC_FREE(streams);
4667 break;
4669 case SMB_QUERY_COMPRESSION_INFO:
4670 case SMB_FILE_COMPRESSION_INFORMATION:
4671 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4672 SOFF_T(pdata,0,file_size);
4673 SIVAL(pdata,8,0); /* ??? */
4674 SIVAL(pdata,12,0); /* ??? */
4675 data_size = 16;
4676 break;
4678 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4679 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4680 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4681 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4682 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4683 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4684 SOFF_T(pdata,32,allocation_size);
4685 SOFF_T(pdata,40,file_size);
4686 SIVAL(pdata,48,mode);
4687 SIVAL(pdata,52,0); /* ??? */
4688 data_size = 56;
4689 break;
4691 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4692 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4693 SIVAL(pdata,0,mode);
4694 SIVAL(pdata,4,0);
4695 data_size = 8;
4696 break;
4699 * CIFS UNIX Extensions.
4702 case SMB_QUERY_FILE_UNIX_BASIC:
4704 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4705 data_size = PTR_DIFF(pdata,(*ppdata));
4708 int i;
4709 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4711 for (i=0; i<100; i++)
4712 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4713 DEBUG(4,("\n"));
4716 break;
4718 case SMB_QUERY_FILE_UNIX_INFO2:
4720 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4721 data_size = PTR_DIFF(pdata,(*ppdata));
4724 int i;
4725 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4727 for (i=0; i<100; i++)
4728 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4729 DEBUG(4,("\n"));
4732 break;
4734 case SMB_QUERY_FILE_UNIX_LINK:
4736 int len;
4737 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4739 if (!buffer) {
4740 return NT_STATUS_NO_MEMORY;
4743 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4744 #ifdef S_ISLNK
4745 if(!S_ISLNK(psbuf->st_ex_mode)) {
4746 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4748 #else
4749 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4750 #endif
4751 len = SMB_VFS_READLINK(conn,
4752 smb_fname->base_name,
4753 buffer, PATH_MAX);
4754 if (len == -1) {
4755 return map_nt_error_from_unix(errno);
4757 buffer[len] = 0;
4758 len = srvstr_push(dstart, flags2,
4759 pdata, buffer,
4760 PTR_DIFF(dend, pdata),
4761 STR_TERMINATE);
4762 pdata += len;
4763 data_size = PTR_DIFF(pdata,(*ppdata));
4765 break;
4768 #if defined(HAVE_POSIX_ACLS)
4769 case SMB_QUERY_POSIX_ACL:
4771 SMB_ACL_T file_acl = NULL;
4772 SMB_ACL_T def_acl = NULL;
4773 uint16 num_file_acls = 0;
4774 uint16 num_def_acls = 0;
4776 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4777 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4778 } else {
4779 file_acl =
4780 SMB_VFS_SYS_ACL_GET_FILE(conn,
4781 smb_fname->base_name,
4782 SMB_ACL_TYPE_ACCESS);
4785 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4786 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4787 "not implemented on "
4788 "filesystem containing %s\n",
4789 smb_fname->base_name));
4790 return NT_STATUS_NOT_IMPLEMENTED;
4793 if (S_ISDIR(psbuf->st_ex_mode)) {
4794 if (fsp && fsp->is_directory) {
4795 def_acl =
4796 SMB_VFS_SYS_ACL_GET_FILE(
4797 conn,
4798 fsp->fsp_name->base_name,
4799 SMB_ACL_TYPE_DEFAULT);
4800 } else {
4801 def_acl =
4802 SMB_VFS_SYS_ACL_GET_FILE(
4803 conn,
4804 smb_fname->base_name,
4805 SMB_ACL_TYPE_DEFAULT);
4807 def_acl = free_empty_sys_acl(conn, def_acl);
4810 num_file_acls = count_acl_entries(conn, file_acl);
4811 num_def_acls = count_acl_entries(conn, def_acl);
4813 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4814 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4815 data_size,
4816 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4817 SMB_POSIX_ACL_HEADER_SIZE) ));
4818 if (file_acl) {
4819 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4821 if (def_acl) {
4822 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4824 return NT_STATUS_BUFFER_TOO_SMALL;
4827 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4828 SSVAL(pdata,2,num_file_acls);
4829 SSVAL(pdata,4,num_def_acls);
4830 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4831 if (file_acl) {
4832 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4834 if (def_acl) {
4835 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4837 return NT_STATUS_INTERNAL_ERROR;
4839 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4840 if (file_acl) {
4841 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4843 if (def_acl) {
4844 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4846 return NT_STATUS_INTERNAL_ERROR;
4849 if (file_acl) {
4850 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4852 if (def_acl) {
4853 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4855 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4856 break;
4858 #endif
4861 case SMB_QUERY_POSIX_LOCK:
4863 uint64_t count;
4864 uint64_t offset;
4865 uint32 lock_pid;
4866 enum brl_type lock_type;
4868 /* We need an open file with a real fd for this. */
4869 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4870 return NT_STATUS_INVALID_LEVEL;
4873 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4874 return NT_STATUS_INVALID_PARAMETER;
4877 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4878 case POSIX_LOCK_TYPE_READ:
4879 lock_type = READ_LOCK;
4880 break;
4881 case POSIX_LOCK_TYPE_WRITE:
4882 lock_type = WRITE_LOCK;
4883 break;
4884 case POSIX_LOCK_TYPE_UNLOCK:
4885 default:
4886 /* There's no point in asking for an unlock... */
4887 return NT_STATUS_INVALID_PARAMETER;
4890 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4891 #if defined(HAVE_LONGLONG)
4892 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4893 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4894 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4895 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4896 #else /* HAVE_LONGLONG */
4897 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4898 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4899 #endif /* HAVE_LONGLONG */
4901 status = query_lock(fsp,
4902 &lock_pid,
4903 &count,
4904 &offset,
4905 &lock_type,
4906 POSIX_LOCK);
4908 if (ERROR_WAS_LOCK_DENIED(status)) {
4909 /* Here we need to report who has it locked... */
4910 data_size = POSIX_LOCK_DATA_SIZE;
4912 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4913 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4914 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4915 #if defined(HAVE_LONGLONG)
4916 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4917 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4918 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4919 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4920 #else /* HAVE_LONGLONG */
4921 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4922 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4923 #endif /* HAVE_LONGLONG */
4925 } else if (NT_STATUS_IS_OK(status)) {
4926 /* For success we just return a copy of what we sent
4927 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4928 data_size = POSIX_LOCK_DATA_SIZE;
4929 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4930 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4931 } else {
4932 return status;
4934 break;
4937 default:
4938 return NT_STATUS_INVALID_LEVEL;
4941 *pdata_size = data_size;
4942 return NT_STATUS_OK;
4945 /****************************************************************************
4946 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4947 file name or file id).
4948 ****************************************************************************/
4950 static void call_trans2qfilepathinfo(connection_struct *conn,
4951 struct smb_request *req,
4952 unsigned int tran_call,
4953 char **pparams, int total_params,
4954 char **ppdata, int total_data,
4955 unsigned int max_data_bytes)
4957 char *params = *pparams;
4958 char *pdata = *ppdata;
4959 uint16 info_level;
4960 unsigned int data_size = 0;
4961 unsigned int param_size = 2;
4962 struct smb_filename *smb_fname = NULL;
4963 bool delete_pending = False;
4964 struct timespec write_time_ts;
4965 files_struct *fsp = NULL;
4966 struct file_id fileid;
4967 struct ea_list *ea_list = NULL;
4968 int lock_data_count = 0;
4969 char *lock_data = NULL;
4970 bool ms_dfs_link = false;
4971 NTSTATUS status = NT_STATUS_OK;
4973 if (!params) {
4974 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4975 return;
4978 ZERO_STRUCT(write_time_ts);
4980 if (tran_call == TRANSACT2_QFILEINFO) {
4981 if (total_params < 4) {
4982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4983 return;
4986 if (IS_IPC(conn)) {
4987 call_trans2qpipeinfo(conn, req, tran_call,
4988 pparams, total_params,
4989 ppdata, total_data,
4990 max_data_bytes);
4991 return;
4994 fsp = file_fsp(req, SVAL(params,0));
4995 info_level = SVAL(params,2);
4997 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4999 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5000 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5001 return;
5004 /* Initial check for valid fsp ptr. */
5005 if (!check_fsp_open(conn, req, fsp)) {
5006 return;
5009 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5010 &smb_fname);
5011 if (!NT_STATUS_IS_OK(status)) {
5012 reply_nterror(req, status);
5013 return;
5016 if(fsp->fake_file_handle) {
5018 * This is actually for the QUOTA_FAKE_FILE --metze
5021 /* We know this name is ok, it's already passed the checks. */
5023 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5025 * This is actually a QFILEINFO on a directory
5026 * handle (returned from an NT SMB). NT5.0 seems
5027 * to do this call. JRA.
5030 if (INFO_LEVEL_IS_UNIX(info_level)) {
5031 /* Always do lstat for UNIX calls. */
5032 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5033 DEBUG(3,("call_trans2qfilepathinfo: "
5034 "SMB_VFS_LSTAT of %s failed "
5035 "(%s)\n",
5036 smb_fname_str_dbg(smb_fname),
5037 strerror(errno)));
5038 reply_nterror(req,
5039 map_nt_error_from_unix(errno));
5040 return;
5042 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5043 DEBUG(3,("call_trans2qfilepathinfo: "
5044 "SMB_VFS_STAT of %s failed (%s)\n",
5045 smb_fname_str_dbg(smb_fname),
5046 strerror(errno)));
5047 reply_nterror(req,
5048 map_nt_error_from_unix(errno));
5049 return;
5052 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5053 get_file_infos(fileid, &delete_pending, &write_time_ts);
5054 } else {
5056 * Original code - this is an open file.
5058 if (!check_fsp(conn, req, fsp)) {
5059 return;
5062 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5063 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5064 fsp->fnum, strerror(errno)));
5065 reply_nterror(req,
5066 map_nt_error_from_unix(errno));
5067 return;
5069 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5070 get_file_infos(fileid, &delete_pending, &write_time_ts);
5073 } else {
5074 char *fname = NULL;
5076 /* qpathinfo */
5077 if (total_params < 7) {
5078 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5079 return;
5082 info_level = SVAL(params,0);
5084 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5086 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5087 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5088 return;
5091 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
5092 total_params - 6,
5093 STR_TERMINATE, &status);
5094 if (!NT_STATUS_IS_OK(status)) {
5095 reply_nterror(req, status);
5096 return;
5099 status = filename_convert(req,
5100 conn,
5101 req->flags2 & FLAGS2_DFS_PATHNAMES,
5102 fname,
5104 NULL,
5105 &smb_fname);
5106 if (!NT_STATUS_IS_OK(status)) {
5107 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5108 reply_botherror(req,
5109 NT_STATUS_PATH_NOT_COVERED,
5110 ERRSRV, ERRbadpath);
5111 return;
5113 reply_nterror(req, status);
5114 return;
5117 /* If this is a stream, check if there is a delete_pending. */
5118 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5119 && is_ntfs_stream_smb_fname(smb_fname)) {
5120 struct smb_filename *smb_fname_base = NULL;
5122 /* Create an smb_filename with stream_name == NULL. */
5123 status =
5124 create_synthetic_smb_fname(talloc_tos(),
5125 smb_fname->base_name,
5126 NULL, NULL,
5127 &smb_fname_base);
5128 if (!NT_STATUS_IS_OK(status)) {
5129 reply_nterror(req, status);
5130 return;
5133 if (INFO_LEVEL_IS_UNIX(info_level)) {
5134 /* Always do lstat for UNIX calls. */
5135 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5136 DEBUG(3,("call_trans2qfilepathinfo: "
5137 "SMB_VFS_LSTAT of %s failed "
5138 "(%s)\n",
5139 smb_fname_str_dbg(smb_fname_base),
5140 strerror(errno)));
5141 TALLOC_FREE(smb_fname_base);
5142 reply_nterror(req,
5143 map_nt_error_from_unix(errno));
5144 return;
5146 } else {
5147 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5148 DEBUG(3,("call_trans2qfilepathinfo: "
5149 "fileinfo 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;
5160 fileid = vfs_file_id_from_sbuf(conn,
5161 &smb_fname_base->st);
5162 TALLOC_FREE(smb_fname_base);
5163 get_file_infos(fileid, &delete_pending, NULL);
5164 if (delete_pending) {
5165 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5166 return;
5170 if (INFO_LEVEL_IS_UNIX(info_level)) {
5171 /* Always do lstat for UNIX calls. */
5172 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5173 DEBUG(3,("call_trans2qfilepathinfo: "
5174 "SMB_VFS_LSTAT of %s failed (%s)\n",
5175 smb_fname_str_dbg(smb_fname),
5176 strerror(errno)));
5177 reply_nterror(req,
5178 map_nt_error_from_unix(errno));
5179 return;
5182 } else if (!VALID_STAT(smb_fname->st) &&
5183 SMB_VFS_STAT(conn, smb_fname) &&
5184 (info_level != SMB_INFO_IS_NAME_VALID)) {
5185 ms_dfs_link = check_msdfs_link(conn,
5186 smb_fname->base_name,
5187 &smb_fname->st);
5189 if (!ms_dfs_link) {
5190 DEBUG(3,("call_trans2qfilepathinfo: "
5191 "SMB_VFS_STAT of %s failed (%s)\n",
5192 smb_fname_str_dbg(smb_fname),
5193 strerror(errno)));
5194 reply_nterror(req,
5195 map_nt_error_from_unix(errno));
5196 return;
5200 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5201 get_file_infos(fileid, &delete_pending, &write_time_ts);
5202 if (delete_pending) {
5203 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5204 return;
5208 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5209 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5210 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5212 /* Pull out any data sent here before we realloc. */
5213 switch (info_level) {
5214 case SMB_INFO_QUERY_EAS_FROM_LIST:
5216 /* Pull any EA list from the data portion. */
5217 uint32 ea_size;
5219 if (total_data < 4) {
5220 reply_nterror(
5221 req, NT_STATUS_INVALID_PARAMETER);
5222 return;
5224 ea_size = IVAL(pdata,0);
5226 if (total_data > 0 && ea_size != total_data) {
5227 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5228 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5229 reply_nterror(
5230 req, NT_STATUS_INVALID_PARAMETER);
5231 return;
5234 if (!lp_ea_support(SNUM(conn))) {
5235 reply_doserror(req, ERRDOS,
5236 ERReasnotsupported);
5237 return;
5240 /* Pull out the list of names. */
5241 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5242 if (!ea_list) {
5243 reply_nterror(
5244 req, NT_STATUS_INVALID_PARAMETER);
5245 return;
5247 break;
5250 case SMB_QUERY_POSIX_LOCK:
5252 if (fsp == NULL || fsp->fh->fd == -1) {
5253 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5254 return;
5257 if (total_data != POSIX_LOCK_DATA_SIZE) {
5258 reply_nterror(
5259 req, NT_STATUS_INVALID_PARAMETER);
5260 return;
5263 /* Copy the lock range data. */
5264 lock_data = (char *)TALLOC_MEMDUP(
5265 req, pdata, total_data);
5266 if (!lock_data) {
5267 reply_nterror(req, NT_STATUS_NO_MEMORY);
5268 return;
5270 lock_data_count = total_data;
5272 default:
5273 break;
5276 *pparams = (char *)SMB_REALLOC(*pparams,2);
5277 if (*pparams == NULL) {
5278 reply_nterror(req, NT_STATUS_NO_MEMORY);
5279 return;
5281 params = *pparams;
5282 SSVAL(params,0,0);
5285 * draft-leach-cifs-v1-spec-02.txt
5286 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5287 * says:
5289 * The requested information is placed in the Data portion of the
5290 * transaction response. For the information levels greater than 0x100,
5291 * the transaction response has 1 parameter word which should be
5292 * ignored by the client.
5294 * However Windows only follows this rule for the IS_NAME_VALID call.
5296 switch (info_level) {
5297 case SMB_INFO_IS_NAME_VALID:
5298 param_size = 0;
5299 break;
5302 if ((info_level & 0xFF00) == 0xFF00) {
5304 * We use levels that start with 0xFF00
5305 * internally to represent SMB2 specific levels
5307 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5308 return;
5311 status = smbd_do_qfilepathinfo(conn, req, info_level,
5312 fsp, smb_fname,
5313 delete_pending, write_time_ts,
5314 ms_dfs_link, ea_list,
5315 lock_data_count, lock_data,
5316 req->flags2, max_data_bytes,
5317 ppdata, &data_size);
5318 if (!NT_STATUS_IS_OK(status)) {
5319 reply_nterror(req, status);
5320 return;
5323 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5324 max_data_bytes);
5326 return;
5329 /****************************************************************************
5330 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5331 code.
5332 ****************************************************************************/
5334 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5335 connection_struct *conn,
5336 const struct smb_filename *smb_fname_old,
5337 const struct smb_filename *smb_fname_new)
5339 NTSTATUS status = NT_STATUS_OK;
5341 /* source must already exist. */
5342 if (!VALID_STAT(smb_fname_old->st)) {
5343 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5346 /* Disallow if newname already exists. */
5347 if (VALID_STAT(smb_fname_new->st)) {
5348 return NT_STATUS_OBJECT_NAME_COLLISION;
5351 /* No links from a directory. */
5352 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5353 return NT_STATUS_FILE_IS_A_DIRECTORY;
5356 /* Setting a hardlink to/from a stream isn't currently supported. */
5357 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5358 is_ntfs_stream_smb_fname(smb_fname_new)) {
5359 return NT_STATUS_INVALID_PARAMETER;
5362 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5363 smb_fname_old->base_name, smb_fname_new->base_name));
5365 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5366 smb_fname_new->base_name) != 0) {
5367 status = map_nt_error_from_unix(errno);
5368 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5369 nt_errstr(status), smb_fname_old->base_name,
5370 smb_fname_new->base_name));
5372 return status;
5375 /****************************************************************************
5376 Deal with setting the time from any of the setfilepathinfo functions.
5377 ****************************************************************************/
5379 NTSTATUS smb_set_file_time(connection_struct *conn,
5380 files_struct *fsp,
5381 const struct smb_filename *smb_fname,
5382 struct smb_file_time *ft,
5383 bool setting_write_time)
5385 struct smb_filename *smb_fname_base = NULL;
5386 uint32 action =
5387 FILE_NOTIFY_CHANGE_LAST_ACCESS
5388 |FILE_NOTIFY_CHANGE_LAST_WRITE
5389 |FILE_NOTIFY_CHANGE_CREATION;
5390 NTSTATUS status;
5392 if (!VALID_STAT(smb_fname->st)) {
5393 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5396 /* get some defaults (no modifications) if any info is zero or -1. */
5397 if (null_timespec(ft->create_time)) {
5398 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5401 if (null_timespec(ft->atime)) {
5402 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5405 if (null_timespec(ft->mtime)) {
5406 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5409 if (!setting_write_time) {
5410 /* ft->mtime comes from change time, not write time. */
5411 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5414 /* Ensure the resolution is the correct for
5415 * what we can store on this filesystem. */
5417 round_timespec(conn->ts_res, &ft->create_time);
5418 round_timespec(conn->ts_res, &ft->ctime);
5419 round_timespec(conn->ts_res, &ft->atime);
5420 round_timespec(conn->ts_res, &ft->mtime);
5422 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5423 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5424 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5425 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5426 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5427 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5428 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5429 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5431 if (setting_write_time) {
5433 * This was a Windows setfileinfo on an open file.
5434 * NT does this a lot. We also need to
5435 * set the time here, as it can be read by
5436 * FindFirst/FindNext and with the patch for bug #2045
5437 * in smbd/fileio.c it ensures that this timestamp is
5438 * kept sticky even after a write. We save the request
5439 * away and will set it on file close and after a write. JRA.
5442 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5443 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5445 if (fsp != NULL) {
5446 if (fsp->base_fsp) {
5447 set_sticky_write_time_fsp(fsp->base_fsp,
5448 ft->mtime);
5449 } else {
5450 set_sticky_write_time_fsp(fsp, ft->mtime);
5452 } else {
5453 set_sticky_write_time_path(
5454 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5455 ft->mtime);
5459 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5461 /* Always call ntimes on the base, even if a stream was passed in. */
5462 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5463 NULL, &smb_fname->st,
5464 &smb_fname_base);
5465 if (!NT_STATUS_IS_OK(status)) {
5466 return status;
5469 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5470 TALLOC_FREE(smb_fname_base);
5471 return map_nt_error_from_unix(errno);
5473 TALLOC_FREE(smb_fname_base);
5475 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5476 smb_fname->base_name);
5477 return NT_STATUS_OK;
5480 /****************************************************************************
5481 Deal with setting the dosmode from any of the setfilepathinfo functions.
5482 ****************************************************************************/
5484 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5485 const struct smb_filename *smb_fname,
5486 uint32 dosmode)
5488 struct smb_filename *smb_fname_base = NULL;
5489 NTSTATUS status;
5491 if (!VALID_STAT(smb_fname->st)) {
5492 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5495 /* Always operate on the base_name, even if a stream was passed in. */
5496 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5497 NULL, &smb_fname->st,
5498 &smb_fname_base);
5499 if (!NT_STATUS_IS_OK(status)) {
5500 return status;
5503 if (dosmode) {
5504 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5505 dosmode |= aDIR;
5506 } else {
5507 dosmode &= ~aDIR;
5511 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5513 /* check the mode isn't different, before changing it */
5514 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5515 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5516 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5517 (unsigned int)dosmode));
5519 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5520 false)) {
5521 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5522 "%s failed (%s)\n",
5523 smb_fname_str_dbg(smb_fname_base),
5524 strerror(errno)));
5525 status = map_nt_error_from_unix(errno);
5526 goto out;
5529 status = NT_STATUS_OK;
5530 out:
5531 TALLOC_FREE(smb_fname_base);
5532 return status;
5535 /****************************************************************************
5536 Deal with setting the size from any of the setfilepathinfo functions.
5537 ****************************************************************************/
5539 static NTSTATUS smb_set_file_size(connection_struct *conn,
5540 struct smb_request *req,
5541 files_struct *fsp,
5542 const struct smb_filename *smb_fname,
5543 const SMB_STRUCT_STAT *psbuf,
5544 SMB_OFF_T size)
5546 NTSTATUS status = NT_STATUS_OK;
5547 struct smb_filename *smb_fname_tmp = NULL;
5548 files_struct *new_fsp = NULL;
5550 if (!VALID_STAT(*psbuf)) {
5551 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5554 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5556 if (size == get_file_size_stat(psbuf)) {
5557 return NT_STATUS_OK;
5560 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5561 smb_fname_str_dbg(smb_fname), (double)size));
5563 if (fsp && fsp->fh->fd != -1) {
5564 /* Handle based call. */
5565 if (vfs_set_filelen(fsp, size) == -1) {
5566 return map_nt_error_from_unix(errno);
5568 trigger_write_time_update_immediate(fsp);
5569 return NT_STATUS_OK;
5572 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5573 if (!NT_STATUS_IS_OK(status)) {
5574 return status;
5577 smb_fname_tmp->st = *psbuf;
5579 status = SMB_VFS_CREATE_FILE(
5580 conn, /* conn */
5581 req, /* req */
5582 0, /* root_dir_fid */
5583 smb_fname_tmp, /* fname */
5584 FILE_WRITE_ATTRIBUTES, /* access_mask */
5585 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5586 FILE_SHARE_DELETE),
5587 FILE_OPEN, /* create_disposition*/
5588 0, /* create_options */
5589 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5590 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5591 0, /* allocation_size */
5592 NULL, /* sd */
5593 NULL, /* ea_list */
5594 &new_fsp, /* result */
5595 NULL); /* pinfo */
5597 TALLOC_FREE(smb_fname_tmp);
5599 if (!NT_STATUS_IS_OK(status)) {
5600 /* NB. We check for open_was_deferred in the caller. */
5601 return status;
5604 if (vfs_set_filelen(new_fsp, size) == -1) {
5605 status = map_nt_error_from_unix(errno);
5606 close_file(req, new_fsp,NORMAL_CLOSE);
5607 return status;
5610 trigger_write_time_update_immediate(new_fsp);
5611 close_file(req, new_fsp,NORMAL_CLOSE);
5612 return NT_STATUS_OK;
5615 /****************************************************************************
5616 Deal with SMB_INFO_SET_EA.
5617 ****************************************************************************/
5619 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5620 const char *pdata,
5621 int total_data,
5622 files_struct *fsp,
5623 const struct smb_filename *smb_fname)
5625 struct ea_list *ea_list = NULL;
5626 TALLOC_CTX *ctx = NULL;
5627 NTSTATUS status = NT_STATUS_OK;
5629 if (total_data < 10) {
5631 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5632 length. They seem to have no effect. Bug #3212. JRA */
5634 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5635 /* We're done. We only get EA info in this call. */
5636 return NT_STATUS_OK;
5639 return NT_STATUS_INVALID_PARAMETER;
5642 if (IVAL(pdata,0) > total_data) {
5643 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5644 IVAL(pdata,0), (unsigned int)total_data));
5645 return NT_STATUS_INVALID_PARAMETER;
5648 ctx = talloc_tos();
5649 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5650 if (!ea_list) {
5651 return NT_STATUS_INVALID_PARAMETER;
5653 status = set_ea(conn, fsp, smb_fname, ea_list);
5655 return status;
5658 /****************************************************************************
5659 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5660 ****************************************************************************/
5662 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5663 const char *pdata,
5664 int total_data,
5665 files_struct *fsp,
5666 const struct smb_filename *smb_fname)
5668 NTSTATUS status = NT_STATUS_OK;
5669 bool delete_on_close;
5670 uint32 dosmode = 0;
5672 if (total_data < 1) {
5673 return NT_STATUS_INVALID_PARAMETER;
5676 if (fsp == NULL) {
5677 return NT_STATUS_INVALID_HANDLE;
5680 delete_on_close = (CVAL(pdata,0) ? True : False);
5681 dosmode = dos_mode(conn, smb_fname);
5683 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5684 "delete_on_close = %u\n",
5685 smb_fname_str_dbg(smb_fname),
5686 (unsigned int)dosmode,
5687 (unsigned int)delete_on_close ));
5689 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5691 if (!NT_STATUS_IS_OK(status)) {
5692 return status;
5695 /* The set is across all open files on this dev/inode pair. */
5696 if (!set_delete_on_close(fsp, delete_on_close,
5697 &conn->server_info->utok)) {
5698 return NT_STATUS_ACCESS_DENIED;
5700 return NT_STATUS_OK;
5703 /****************************************************************************
5704 Deal with SMB_FILE_POSITION_INFORMATION.
5705 ****************************************************************************/
5707 static NTSTATUS smb_file_position_information(connection_struct *conn,
5708 const char *pdata,
5709 int total_data,
5710 files_struct *fsp)
5712 uint64_t position_information;
5714 if (total_data < 8) {
5715 return NT_STATUS_INVALID_PARAMETER;
5718 if (fsp == NULL) {
5719 /* Ignore on pathname based set. */
5720 return NT_STATUS_OK;
5723 position_information = (uint64_t)IVAL(pdata,0);
5724 #ifdef LARGE_SMB_OFF_T
5725 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5726 #else /* LARGE_SMB_OFF_T */
5727 if (IVAL(pdata,4) != 0) {
5728 /* more than 32 bits? */
5729 return NT_STATUS_INVALID_PARAMETER;
5731 #endif /* LARGE_SMB_OFF_T */
5733 DEBUG(10,("smb_file_position_information: Set file position "
5734 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5735 (double)position_information));
5736 fsp->fh->position_information = position_information;
5737 return NT_STATUS_OK;
5740 /****************************************************************************
5741 Deal with SMB_FILE_MODE_INFORMATION.
5742 ****************************************************************************/
5744 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5745 const char *pdata,
5746 int total_data)
5748 uint32 mode;
5750 if (total_data < 4) {
5751 return NT_STATUS_INVALID_PARAMETER;
5753 mode = IVAL(pdata,0);
5754 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5755 return NT_STATUS_INVALID_PARAMETER;
5757 return NT_STATUS_OK;
5760 /****************************************************************************
5761 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5762 ****************************************************************************/
5764 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5765 struct smb_request *req,
5766 const char *pdata,
5767 int total_data,
5768 const struct smb_filename *smb_fname)
5770 char *link_target = NULL;
5771 const char *newname = smb_fname->base_name;
5772 NTSTATUS status = NT_STATUS_OK;
5773 TALLOC_CTX *ctx = talloc_tos();
5775 /* Set a symbolic link. */
5776 /* Don't allow this if follow links is false. */
5778 if (total_data == 0) {
5779 return NT_STATUS_INVALID_PARAMETER;
5782 if (!lp_symlinks(SNUM(conn))) {
5783 return NT_STATUS_ACCESS_DENIED;
5786 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5787 total_data, STR_TERMINATE);
5789 if (!link_target) {
5790 return NT_STATUS_INVALID_PARAMETER;
5793 /* !widelinks forces the target path to be within the share. */
5794 /* This means we can interpret the target as a pathname. */
5795 if (!lp_widelinks(SNUM(conn))) {
5796 char *rel_name = NULL;
5797 char *last_dirp = NULL;
5799 if (*link_target == '/') {
5800 /* No absolute paths allowed. */
5801 return NT_STATUS_ACCESS_DENIED;
5803 rel_name = talloc_strdup(ctx,newname);
5804 if (!rel_name) {
5805 return NT_STATUS_NO_MEMORY;
5807 last_dirp = strrchr_m(rel_name, '/');
5808 if (last_dirp) {
5809 last_dirp[1] = '\0';
5810 } else {
5811 rel_name = talloc_strdup(ctx,"./");
5812 if (!rel_name) {
5813 return NT_STATUS_NO_MEMORY;
5816 rel_name = talloc_asprintf_append(rel_name,
5817 "%s",
5818 link_target);
5819 if (!rel_name) {
5820 return NT_STATUS_NO_MEMORY;
5823 status = check_name(conn, rel_name);
5824 if (!NT_STATUS_IS_OK(status)) {
5825 return status;
5829 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5830 newname, link_target ));
5832 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5833 return map_nt_error_from_unix(errno);
5836 return NT_STATUS_OK;
5839 /****************************************************************************
5840 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5841 ****************************************************************************/
5843 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5844 struct smb_request *req,
5845 const char *pdata, int total_data,
5846 const struct smb_filename *smb_fname_new)
5848 char *oldname = NULL;
5849 struct smb_filename *smb_fname_old = NULL;
5850 TALLOC_CTX *ctx = talloc_tos();
5851 NTSTATUS status = NT_STATUS_OK;
5853 /* Set a hard link. */
5854 if (total_data == 0) {
5855 return NT_STATUS_INVALID_PARAMETER;
5858 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5859 total_data, STR_TERMINATE, &status);
5860 if (!NT_STATUS_IS_OK(status)) {
5861 return status;
5864 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5865 smb_fname_str_dbg(smb_fname_new), oldname));
5867 status = filename_convert(ctx,
5868 conn,
5869 req->flags2 & FLAGS2_DFS_PATHNAMES,
5870 oldname,
5872 NULL,
5873 &smb_fname_old);
5874 if (!NT_STATUS_IS_OK(status)) {
5875 return status;
5878 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5881 /****************************************************************************
5882 Deal with SMB_FILE_RENAME_INFORMATION.
5883 ****************************************************************************/
5885 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5886 struct smb_request *req,
5887 const char *pdata,
5888 int total_data,
5889 files_struct *fsp,
5890 struct smb_filename *smb_fname_src)
5892 bool overwrite;
5893 uint32 root_fid;
5894 uint32 len;
5895 char *newname = NULL;
5896 struct smb_filename *smb_fname_dst = NULL;
5897 bool dest_has_wcard = False;
5898 NTSTATUS status = NT_STATUS_OK;
5899 char *p;
5900 TALLOC_CTX *ctx = talloc_tos();
5902 if (total_data < 13) {
5903 return NT_STATUS_INVALID_PARAMETER;
5906 overwrite = (CVAL(pdata,0) ? True : False);
5907 root_fid = IVAL(pdata,4);
5908 len = IVAL(pdata,8);
5910 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5911 return NT_STATUS_INVALID_PARAMETER;
5914 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5915 len, 0, &status,
5916 &dest_has_wcard);
5917 if (!NT_STATUS_IS_OK(status)) {
5918 return status;
5921 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5922 newname));
5924 status = resolve_dfspath_wcard(ctx, conn,
5925 req->flags2 & FLAGS2_DFS_PATHNAMES,
5926 newname,
5927 &newname,
5928 &dest_has_wcard);
5929 if (!NT_STATUS_IS_OK(status)) {
5930 return status;
5933 /* Check the new name has no '/' characters. */
5934 if (strchr_m(newname, '/')) {
5935 return NT_STATUS_NOT_SUPPORTED;
5938 if (fsp && fsp->base_fsp) {
5939 /* newname must be a stream name. */
5940 if (newname[0] != ':') {
5941 return NT_STATUS_NOT_SUPPORTED;
5944 /* Create an smb_fname to call rename_internals_fsp() with. */
5945 status = create_synthetic_smb_fname(talloc_tos(),
5946 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5947 &smb_fname_dst);
5948 if (!NT_STATUS_IS_OK(status)) {
5949 goto out;
5953 * Set the original last component, since
5954 * rename_internals_fsp() requires it.
5956 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5957 newname);
5958 if (smb_fname_dst->original_lcomp == NULL) {
5959 status = NT_STATUS_NO_MEMORY;
5960 goto out;
5963 } else {
5965 * Build up an smb_fname_dst based on the filename passed in.
5966 * We basically just strip off the last component, and put on
5967 * the newname instead.
5969 char *base_name = NULL;
5971 /* newname must *not* be a stream name. */
5972 if (newname[0] == ':') {
5973 return NT_STATUS_NOT_SUPPORTED;
5977 * Strip off the last component (filename) of the path passed
5978 * in.
5980 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5981 if (!base_name) {
5982 return NT_STATUS_NO_MEMORY;
5984 p = strrchr_m(base_name, '/');
5985 if (p) {
5986 p[1] = '\0';
5987 } else {
5988 base_name = talloc_strdup(ctx, "./");
5989 if (!base_name) {
5990 return NT_STATUS_NO_MEMORY;
5993 /* Append the new name. */
5994 base_name = talloc_asprintf_append(base_name,
5995 "%s",
5996 newname);
5997 if (!base_name) {
5998 return NT_STATUS_NO_MEMORY;
6001 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6002 (UCF_SAVE_LCOMP |
6003 (dest_has_wcard ?
6004 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6005 0)));
6007 /* If an error we expect this to be
6008 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6010 if (!NT_STATUS_IS_OK(status)) {
6011 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6012 status)) {
6013 goto out;
6015 /* Create an smb_fname to call rename_internals_fsp() */
6016 status = create_synthetic_smb_fname(ctx,
6017 base_name, NULL,
6018 NULL,
6019 &smb_fname_dst);
6020 if (!NT_STATUS_IS_OK(status)) {
6021 goto out;
6026 if (fsp) {
6027 DEBUG(10,("smb_file_rename_information: "
6028 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6029 fsp->fnum, fsp_str_dbg(fsp),
6030 smb_fname_str_dbg(smb_fname_dst)));
6031 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6032 overwrite);
6033 } else {
6034 DEBUG(10,("smb_file_rename_information: "
6035 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6036 smb_fname_str_dbg(smb_fname_src),
6037 smb_fname_str_dbg(smb_fname_dst)));
6038 status = rename_internals(ctx, conn, req, smb_fname_src,
6039 smb_fname_dst, 0, overwrite, false,
6040 dest_has_wcard,
6041 FILE_WRITE_ATTRIBUTES);
6043 out:
6044 TALLOC_FREE(smb_fname_dst);
6045 return status;
6048 /****************************************************************************
6049 Deal with SMB_SET_POSIX_ACL.
6050 ****************************************************************************/
6052 #if defined(HAVE_POSIX_ACLS)
6053 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6054 const char *pdata,
6055 int total_data,
6056 files_struct *fsp,
6057 const struct smb_filename *smb_fname)
6059 uint16 posix_acl_version;
6060 uint16 num_file_acls;
6061 uint16 num_def_acls;
6062 bool valid_file_acls = True;
6063 bool valid_def_acls = True;
6065 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6066 return NT_STATUS_INVALID_PARAMETER;
6068 posix_acl_version = SVAL(pdata,0);
6069 num_file_acls = SVAL(pdata,2);
6070 num_def_acls = SVAL(pdata,4);
6072 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6073 valid_file_acls = False;
6074 num_file_acls = 0;
6077 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6078 valid_def_acls = False;
6079 num_def_acls = 0;
6082 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6083 return NT_STATUS_INVALID_PARAMETER;
6086 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6087 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6088 return NT_STATUS_INVALID_PARAMETER;
6091 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6092 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6093 (unsigned int)num_file_acls,
6094 (unsigned int)num_def_acls));
6096 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6097 smb_fname->base_name, num_file_acls,
6098 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6099 return map_nt_error_from_unix(errno);
6102 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6103 smb_fname->base_name, &smb_fname->st, num_def_acls,
6104 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6105 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6106 return map_nt_error_from_unix(errno);
6108 return NT_STATUS_OK;
6110 #endif
6112 /****************************************************************************
6113 Deal with SMB_SET_POSIX_LOCK.
6114 ****************************************************************************/
6116 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6117 struct smb_request *req,
6118 const char *pdata,
6119 int total_data,
6120 files_struct *fsp)
6122 uint64_t count;
6123 uint64_t offset;
6124 uint32 lock_pid;
6125 bool blocking_lock = False;
6126 enum brl_type lock_type;
6128 NTSTATUS status = NT_STATUS_OK;
6130 if (fsp == NULL || fsp->fh->fd == -1) {
6131 return NT_STATUS_INVALID_HANDLE;
6134 if (total_data != POSIX_LOCK_DATA_SIZE) {
6135 return NT_STATUS_INVALID_PARAMETER;
6138 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6139 case POSIX_LOCK_TYPE_READ:
6140 lock_type = READ_LOCK;
6141 break;
6142 case POSIX_LOCK_TYPE_WRITE:
6143 /* Return the right POSIX-mappable error code for files opened read-only. */
6144 if (!fsp->can_write) {
6145 return NT_STATUS_INVALID_HANDLE;
6147 lock_type = WRITE_LOCK;
6148 break;
6149 case POSIX_LOCK_TYPE_UNLOCK:
6150 lock_type = UNLOCK_LOCK;
6151 break;
6152 default:
6153 return NT_STATUS_INVALID_PARAMETER;
6156 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6157 blocking_lock = False;
6158 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6159 blocking_lock = True;
6160 } else {
6161 return NT_STATUS_INVALID_PARAMETER;
6164 if (!lp_blocking_locks(SNUM(conn))) {
6165 blocking_lock = False;
6168 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6169 #if defined(HAVE_LONGLONG)
6170 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6171 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6172 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6173 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6174 #else /* HAVE_LONGLONG */
6175 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6176 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6177 #endif /* HAVE_LONGLONG */
6179 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6180 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6181 fsp_str_dbg(fsp),
6182 (unsigned int)lock_type,
6183 (unsigned int)lock_pid,
6184 (double)count,
6185 (double)offset ));
6187 if (lock_type == UNLOCK_LOCK) {
6188 status = do_unlock(smbd_messaging_context(),
6189 fsp,
6190 lock_pid,
6191 count,
6192 offset,
6193 POSIX_LOCK);
6194 } else {
6195 uint32 block_smbpid;
6197 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6198 fsp,
6199 lock_pid,
6200 count,
6201 offset,
6202 lock_type,
6203 POSIX_LOCK,
6204 blocking_lock,
6205 &status,
6206 &block_smbpid,
6207 NULL);
6209 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6211 * A blocking lock was requested. Package up
6212 * this smb into a queued request and push it
6213 * onto the blocking lock queue.
6215 if(push_blocking_lock_request(br_lck,
6216 req,
6217 fsp,
6218 -1, /* infinite timeout. */
6220 lock_pid,
6221 lock_type,
6222 POSIX_LOCK,
6223 offset,
6224 count,
6225 block_smbpid)) {
6226 TALLOC_FREE(br_lck);
6227 return status;
6230 TALLOC_FREE(br_lck);
6233 return status;
6236 /****************************************************************************
6237 Deal with SMB_SET_FILE_BASIC_INFO.
6238 ****************************************************************************/
6240 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6241 const char *pdata,
6242 int total_data,
6243 files_struct *fsp,
6244 const struct smb_filename *smb_fname)
6246 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6247 struct smb_file_time ft;
6248 uint32 dosmode = 0;
6249 NTSTATUS status = NT_STATUS_OK;
6251 ZERO_STRUCT(ft);
6253 if (total_data < 36) {
6254 return NT_STATUS_INVALID_PARAMETER;
6257 /* Set the attributes */
6258 dosmode = IVAL(pdata,32);
6259 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6260 if (!NT_STATUS_IS_OK(status)) {
6261 return status;
6264 /* create time */
6265 ft.create_time = interpret_long_date(pdata);
6267 /* access time */
6268 ft.atime = interpret_long_date(pdata+8);
6270 /* write time. */
6271 ft.mtime = interpret_long_date(pdata+16);
6273 /* change time. */
6274 ft.ctime = interpret_long_date(pdata+24);
6276 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6277 smb_fname_str_dbg(smb_fname)));
6279 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6280 true);
6283 /****************************************************************************
6284 Deal with SMB_INFO_STANDARD.
6285 ****************************************************************************/
6287 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6288 const char *pdata,
6289 int total_data,
6290 files_struct *fsp,
6291 const struct smb_filename *smb_fname)
6293 struct smb_file_time ft;
6295 ZERO_STRUCT(ft);
6297 if (total_data < 12) {
6298 return NT_STATUS_INVALID_PARAMETER;
6301 /* create time */
6302 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6303 /* access time */
6304 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6305 /* write time */
6306 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6308 DEBUG(10,("smb_set_info_standard: file %s\n",
6309 smb_fname_str_dbg(smb_fname)));
6311 return smb_set_file_time(conn,
6312 fsp,
6313 smb_fname,
6314 &ft,
6315 true);
6318 /****************************************************************************
6319 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6320 ****************************************************************************/
6322 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6323 struct smb_request *req,
6324 const char *pdata,
6325 int total_data,
6326 files_struct *fsp,
6327 struct smb_filename *smb_fname)
6329 uint64_t allocation_size = 0;
6330 NTSTATUS status = NT_STATUS_OK;
6331 files_struct *new_fsp = NULL;
6333 if (!VALID_STAT(smb_fname->st)) {
6334 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6337 if (total_data < 8) {
6338 return NT_STATUS_INVALID_PARAMETER;
6341 allocation_size = (uint64_t)IVAL(pdata,0);
6342 #ifdef LARGE_SMB_OFF_T
6343 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6344 #else /* LARGE_SMB_OFF_T */
6345 if (IVAL(pdata,4) != 0) {
6346 /* more than 32 bits? */
6347 return NT_STATUS_INVALID_PARAMETER;
6349 #endif /* LARGE_SMB_OFF_T */
6351 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6352 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6353 (double)allocation_size));
6355 if (allocation_size) {
6356 allocation_size = smb_roundup(conn, allocation_size);
6359 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6360 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6361 (double)allocation_size));
6363 if (fsp && fsp->fh->fd != -1) {
6364 /* Open file handle. */
6365 /* Only change if needed. */
6366 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6367 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6368 return map_nt_error_from_unix(errno);
6371 /* But always update the time. */
6373 * This is equivalent to a write. Ensure it's seen immediately
6374 * if there are no pending writes.
6376 trigger_write_time_update_immediate(fsp);
6377 return NT_STATUS_OK;
6380 /* Pathname or stat or directory file. */
6381 status = SMB_VFS_CREATE_FILE(
6382 conn, /* conn */
6383 req, /* req */
6384 0, /* root_dir_fid */
6385 smb_fname, /* fname */
6386 FILE_WRITE_DATA, /* access_mask */
6387 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6388 FILE_SHARE_DELETE),
6389 FILE_OPEN, /* create_disposition*/
6390 0, /* create_options */
6391 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6392 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6393 0, /* allocation_size */
6394 NULL, /* sd */
6395 NULL, /* ea_list */
6396 &new_fsp, /* result */
6397 NULL); /* pinfo */
6399 if (!NT_STATUS_IS_OK(status)) {
6400 /* NB. We check for open_was_deferred in the caller. */
6401 return status;
6404 /* Only change if needed. */
6405 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6406 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6407 status = map_nt_error_from_unix(errno);
6408 close_file(req, new_fsp, NORMAL_CLOSE);
6409 return status;
6413 /* Changing the allocation size should set the last mod time. */
6415 * This is equivalent to a write. Ensure it's seen immediately
6416 * if there are no pending writes.
6418 trigger_write_time_update_immediate(new_fsp);
6420 close_file(req, new_fsp, NORMAL_CLOSE);
6421 return NT_STATUS_OK;
6424 /****************************************************************************
6425 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6426 ****************************************************************************/
6428 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6429 struct smb_request *req,
6430 const char *pdata,
6431 int total_data,
6432 files_struct *fsp,
6433 const struct smb_filename *smb_fname)
6435 SMB_OFF_T size;
6437 if (total_data < 8) {
6438 return NT_STATUS_INVALID_PARAMETER;
6441 size = IVAL(pdata,0);
6442 #ifdef LARGE_SMB_OFF_T
6443 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6444 #else /* LARGE_SMB_OFF_T */
6445 if (IVAL(pdata,4) != 0) {
6446 /* more than 32 bits? */
6447 return NT_STATUS_INVALID_PARAMETER;
6449 #endif /* LARGE_SMB_OFF_T */
6450 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6451 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6452 (double)size));
6454 return smb_set_file_size(conn, req,
6455 fsp,
6456 smb_fname,
6457 &smb_fname->st,
6458 size);
6461 /****************************************************************************
6462 Allow a UNIX info mknod.
6463 ****************************************************************************/
6465 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6466 const char *pdata,
6467 int total_data,
6468 const struct smb_filename *smb_fname)
6470 uint32 file_type = IVAL(pdata,56);
6471 #if defined(HAVE_MAKEDEV)
6472 uint32 dev_major = IVAL(pdata,60);
6473 uint32 dev_minor = IVAL(pdata,68);
6474 #endif
6475 SMB_DEV_T dev = (SMB_DEV_T)0;
6476 uint32 raw_unixmode = IVAL(pdata,84);
6477 NTSTATUS status;
6478 mode_t unixmode;
6480 if (total_data < 100) {
6481 return NT_STATUS_INVALID_PARAMETER;
6484 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6485 PERM_NEW_FILE, &unixmode);
6486 if (!NT_STATUS_IS_OK(status)) {
6487 return status;
6490 #if defined(HAVE_MAKEDEV)
6491 dev = makedev(dev_major, dev_minor);
6492 #endif
6494 switch (file_type) {
6495 #if defined(S_IFIFO)
6496 case UNIX_TYPE_FIFO:
6497 unixmode |= S_IFIFO;
6498 break;
6499 #endif
6500 #if defined(S_IFSOCK)
6501 case UNIX_TYPE_SOCKET:
6502 unixmode |= S_IFSOCK;
6503 break;
6504 #endif
6505 #if defined(S_IFCHR)
6506 case UNIX_TYPE_CHARDEV:
6507 unixmode |= S_IFCHR;
6508 break;
6509 #endif
6510 #if defined(S_IFBLK)
6511 case UNIX_TYPE_BLKDEV:
6512 unixmode |= S_IFBLK;
6513 break;
6514 #endif
6515 default:
6516 return NT_STATUS_INVALID_PARAMETER;
6519 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6520 "%.0f mode 0%o for file %s\n", (double)dev,
6521 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6523 /* Ok - do the mknod. */
6524 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6525 return map_nt_error_from_unix(errno);
6528 /* If any of the other "set" calls fail we
6529 * don't want to end up with a half-constructed mknod.
6532 if (lp_inherit_perms(SNUM(conn))) {
6533 char *parent;
6534 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6535 &parent, NULL)) {
6536 return NT_STATUS_NO_MEMORY;
6538 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6539 unixmode);
6540 TALLOC_FREE(parent);
6543 return NT_STATUS_OK;
6546 /****************************************************************************
6547 Deal with SMB_SET_FILE_UNIX_BASIC.
6548 ****************************************************************************/
6550 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6551 struct smb_request *req,
6552 const char *pdata,
6553 int total_data,
6554 files_struct *fsp,
6555 const struct smb_filename *smb_fname)
6557 struct smb_file_time ft;
6558 uint32 raw_unixmode;
6559 mode_t unixmode;
6560 SMB_OFF_T size = 0;
6561 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6562 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6563 NTSTATUS status = NT_STATUS_OK;
6564 bool delete_on_fail = False;
6565 enum perm_type ptype;
6566 files_struct *all_fsps = NULL;
6567 bool modify_mtime = true;
6568 struct file_id id;
6569 SMB_STRUCT_STAT sbuf;
6571 ZERO_STRUCT(ft);
6573 if (total_data < 100) {
6574 return NT_STATUS_INVALID_PARAMETER;
6577 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6578 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6579 size=IVAL(pdata,0); /* first 8 Bytes are size */
6580 #ifdef LARGE_SMB_OFF_T
6581 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6582 #else /* LARGE_SMB_OFF_T */
6583 if (IVAL(pdata,4) != 0) {
6584 /* more than 32 bits? */
6585 return NT_STATUS_INVALID_PARAMETER;
6587 #endif /* LARGE_SMB_OFF_T */
6590 ft.atime = interpret_long_date(pdata+24); /* access_time */
6591 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6592 set_owner = (uid_t)IVAL(pdata,40);
6593 set_grp = (gid_t)IVAL(pdata,48);
6594 raw_unixmode = IVAL(pdata,84);
6596 if (VALID_STAT(smb_fname->st)) {
6597 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6598 ptype = PERM_EXISTING_DIR;
6599 } else {
6600 ptype = PERM_EXISTING_FILE;
6602 } else {
6603 ptype = PERM_NEW_FILE;
6606 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6607 ptype, &unixmode);
6608 if (!NT_STATUS_IS_OK(status)) {
6609 return status;
6612 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6613 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6614 smb_fname_str_dbg(smb_fname), (double)size,
6615 (unsigned int)set_owner, (unsigned int)set_grp,
6616 (int)raw_unixmode));
6618 sbuf = smb_fname->st;
6620 if (!VALID_STAT(sbuf)) {
6621 struct smb_filename *smb_fname_tmp = NULL;
6623 * The only valid use of this is to create character and block
6624 * devices, and named pipes. This is deprecated (IMHO) and
6625 * a new info level should be used for mknod. JRA.
6628 status = smb_unix_mknod(conn,
6629 pdata,
6630 total_data,
6631 smb_fname);
6632 if (!NT_STATUS_IS_OK(status)) {
6633 return status;
6636 status = copy_smb_filename(talloc_tos(), smb_fname,
6637 &smb_fname_tmp);
6638 if (!NT_STATUS_IS_OK(status)) {
6639 return status;
6642 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6643 status = map_nt_error_from_unix(errno);
6644 TALLOC_FREE(smb_fname_tmp);
6645 SMB_VFS_UNLINK(conn, smb_fname);
6646 return status;
6649 sbuf = smb_fname_tmp->st;
6650 TALLOC_FREE(smb_fname_tmp);
6652 /* Ensure we don't try and change anything else. */
6653 raw_unixmode = SMB_MODE_NO_CHANGE;
6654 size = get_file_size_stat(&sbuf);
6655 ft.atime = sbuf.st_ex_atime;
6656 ft.mtime = sbuf.st_ex_mtime;
6658 * We continue here as we might want to change the
6659 * owner uid/gid.
6661 delete_on_fail = True;
6664 #if 1
6665 /* Horrible backwards compatibility hack as an old server bug
6666 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6667 * */
6669 if (!size) {
6670 size = get_file_size_stat(&sbuf);
6672 #endif
6675 * Deal with the UNIX specific mode set.
6678 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6679 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6680 "setting mode 0%o for file %s\n",
6681 (unsigned int)unixmode,
6682 smb_fname_str_dbg(smb_fname)));
6683 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6684 return map_nt_error_from_unix(errno);
6689 * Deal with the UNIX specific uid set.
6692 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6693 (sbuf.st_ex_uid != set_owner)) {
6694 int ret;
6696 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6697 "changing owner %u for path %s\n",
6698 (unsigned int)set_owner,
6699 smb_fname_str_dbg(smb_fname)));
6701 if (S_ISLNK(sbuf.st_ex_mode)) {
6702 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6703 set_owner, (gid_t)-1);
6704 } else {
6705 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6706 set_owner, (gid_t)-1);
6709 if (ret != 0) {
6710 status = map_nt_error_from_unix(errno);
6711 if (delete_on_fail) {
6712 SMB_VFS_UNLINK(conn, smb_fname);
6714 return status;
6719 * Deal with the UNIX specific gid set.
6722 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6723 (sbuf.st_ex_gid != set_grp)) {
6724 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6725 "changing group %u for file %s\n",
6726 (unsigned int)set_owner,
6727 smb_fname_str_dbg(smb_fname)));
6728 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6729 set_grp) != 0) {
6730 status = map_nt_error_from_unix(errno);
6731 if (delete_on_fail) {
6732 SMB_VFS_UNLINK(conn, smb_fname);
6734 return status;
6738 /* Deal with any size changes. */
6740 status = smb_set_file_size(conn, req,
6741 fsp,
6742 smb_fname,
6743 &sbuf,
6744 size);
6745 if (!NT_STATUS_IS_OK(status)) {
6746 return status;
6749 /* Deal with any time changes. */
6750 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6751 /* No change, don't cancel anything. */
6752 return status;
6755 id = vfs_file_id_from_sbuf(conn, &sbuf);
6756 for(all_fsps = file_find_di_first(id); all_fsps;
6757 all_fsps = file_find_di_next(all_fsps)) {
6759 * We're setting the time explicitly for UNIX.
6760 * Cancel any pending changes over all handles.
6762 all_fsps->update_write_time_on_close = false;
6763 TALLOC_FREE(all_fsps->update_write_time_event);
6767 * Override the "setting_write_time"
6768 * parameter here as it almost does what
6769 * we need. Just remember if we modified
6770 * mtime and send the notify ourselves.
6772 if (null_timespec(ft.mtime)) {
6773 modify_mtime = false;
6776 status = smb_set_file_time(conn,
6777 fsp,
6778 smb_fname,
6779 &ft,
6780 false);
6781 if (modify_mtime) {
6782 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6783 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6785 return status;
6788 /****************************************************************************
6789 Deal with SMB_SET_FILE_UNIX_INFO2.
6790 ****************************************************************************/
6792 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6793 struct smb_request *req,
6794 const char *pdata,
6795 int total_data,
6796 files_struct *fsp,
6797 const struct smb_filename *smb_fname)
6799 NTSTATUS status;
6800 uint32 smb_fflags;
6801 uint32 smb_fmask;
6803 if (total_data < 116) {
6804 return NT_STATUS_INVALID_PARAMETER;
6807 /* Start by setting all the fields that are common between UNIX_BASIC
6808 * and UNIX_INFO2.
6810 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6811 fsp, smb_fname);
6812 if (!NT_STATUS_IS_OK(status)) {
6813 return status;
6816 smb_fflags = IVAL(pdata, 108);
6817 smb_fmask = IVAL(pdata, 112);
6819 /* NB: We should only attempt to alter the file flags if the client
6820 * sends a non-zero mask.
6822 if (smb_fmask != 0) {
6823 int stat_fflags = 0;
6825 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6826 smb_fmask, &stat_fflags)) {
6827 /* Client asked to alter a flag we don't understand. */
6828 return NT_STATUS_INVALID_PARAMETER;
6831 if (fsp && fsp->fh->fd != -1) {
6832 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6833 return NT_STATUS_NOT_SUPPORTED;
6834 } else {
6835 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6836 stat_fflags) != 0) {
6837 return map_nt_error_from_unix(errno);
6842 /* XXX: need to add support for changing the create_time here. You
6843 * can do this for paths on Darwin with setattrlist(2). The right way
6844 * to hook this up is probably by extending the VFS utimes interface.
6847 return NT_STATUS_OK;
6850 /****************************************************************************
6851 Create a directory with POSIX semantics.
6852 ****************************************************************************/
6854 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6855 struct smb_request *req,
6856 char **ppdata,
6857 int total_data,
6858 struct smb_filename *smb_fname,
6859 int *pdata_return_size)
6861 NTSTATUS status = NT_STATUS_OK;
6862 uint32 raw_unixmode = 0;
6863 uint32 mod_unixmode = 0;
6864 mode_t unixmode = (mode_t)0;
6865 files_struct *fsp = NULL;
6866 uint16 info_level_return = 0;
6867 int info;
6868 char *pdata = *ppdata;
6870 if (total_data < 18) {
6871 return NT_STATUS_INVALID_PARAMETER;
6874 raw_unixmode = IVAL(pdata,8);
6875 /* Next 4 bytes are not yet defined. */
6877 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6878 PERM_NEW_DIR, &unixmode);
6879 if (!NT_STATUS_IS_OK(status)) {
6880 return status;
6883 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6885 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6886 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6888 status = SMB_VFS_CREATE_FILE(
6889 conn, /* conn */
6890 req, /* req */
6891 0, /* root_dir_fid */
6892 smb_fname, /* fname */
6893 FILE_READ_ATTRIBUTES, /* access_mask */
6894 FILE_SHARE_NONE, /* share_access */
6895 FILE_CREATE, /* create_disposition*/
6896 FILE_DIRECTORY_FILE, /* create_options */
6897 mod_unixmode, /* file_attributes */
6898 0, /* oplock_request */
6899 0, /* allocation_size */
6900 NULL, /* sd */
6901 NULL, /* ea_list */
6902 &fsp, /* result */
6903 &info); /* pinfo */
6905 if (NT_STATUS_IS_OK(status)) {
6906 close_file(req, fsp, NORMAL_CLOSE);
6909 info_level_return = SVAL(pdata,16);
6911 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6912 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6913 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6914 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6915 } else {
6916 *pdata_return_size = 12;
6919 /* Realloc the data size */
6920 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6921 if (*ppdata == NULL) {
6922 *pdata_return_size = 0;
6923 return NT_STATUS_NO_MEMORY;
6925 pdata = *ppdata;
6927 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6928 SSVAL(pdata,2,0); /* No fnum. */
6929 SIVAL(pdata,4,info); /* Was directory created. */
6931 switch (info_level_return) {
6932 case SMB_QUERY_FILE_UNIX_BASIC:
6933 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6934 SSVAL(pdata,10,0); /* Padding. */
6935 store_file_unix_basic(conn, pdata + 12, fsp,
6936 &smb_fname->st);
6937 break;
6938 case SMB_QUERY_FILE_UNIX_INFO2:
6939 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6940 SSVAL(pdata,10,0); /* Padding. */
6941 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6942 &smb_fname->st);
6943 break;
6944 default:
6945 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6946 SSVAL(pdata,10,0); /* Padding. */
6947 break;
6950 return status;
6953 /****************************************************************************
6954 Open/Create a file with POSIX semantics.
6955 ****************************************************************************/
6957 static NTSTATUS smb_posix_open(connection_struct *conn,
6958 struct smb_request *req,
6959 char **ppdata,
6960 int total_data,
6961 struct smb_filename *smb_fname,
6962 int *pdata_return_size)
6964 bool extended_oplock_granted = False;
6965 char *pdata = *ppdata;
6966 uint32 flags = 0;
6967 uint32 wire_open_mode = 0;
6968 uint32 raw_unixmode = 0;
6969 uint32 mod_unixmode = 0;
6970 uint32 create_disp = 0;
6971 uint32 access_mask = 0;
6972 uint32 create_options = 0;
6973 NTSTATUS status = NT_STATUS_OK;
6974 mode_t unixmode = (mode_t)0;
6975 files_struct *fsp = NULL;
6976 int oplock_request = 0;
6977 int info = 0;
6978 uint16 info_level_return = 0;
6980 if (total_data < 18) {
6981 return NT_STATUS_INVALID_PARAMETER;
6984 flags = IVAL(pdata,0);
6985 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6986 if (oplock_request) {
6987 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6990 wire_open_mode = IVAL(pdata,4);
6992 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6993 return smb_posix_mkdir(conn, req,
6994 ppdata,
6995 total_data,
6996 smb_fname,
6997 pdata_return_size);
7000 switch (wire_open_mode & SMB_ACCMODE) {
7001 case SMB_O_RDONLY:
7002 access_mask = FILE_READ_DATA;
7003 break;
7004 case SMB_O_WRONLY:
7005 access_mask = FILE_WRITE_DATA;
7006 break;
7007 case SMB_O_RDWR:
7008 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7009 break;
7010 default:
7011 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7012 (unsigned int)wire_open_mode ));
7013 return NT_STATUS_INVALID_PARAMETER;
7016 wire_open_mode &= ~SMB_ACCMODE;
7018 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7019 create_disp = FILE_CREATE;
7020 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7021 create_disp = FILE_OVERWRITE_IF;
7022 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7023 create_disp = FILE_OPEN_IF;
7024 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7025 create_disp = FILE_OPEN;
7026 } else {
7027 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7028 (unsigned int)wire_open_mode ));
7029 return NT_STATUS_INVALID_PARAMETER;
7032 raw_unixmode = IVAL(pdata,8);
7033 /* Next 4 bytes are not yet defined. */
7035 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7036 (VALID_STAT(smb_fname->st) ?
7037 PERM_EXISTING_FILE : PERM_NEW_FILE),
7038 &unixmode);
7040 if (!NT_STATUS_IS_OK(status)) {
7041 return status;
7044 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7046 if (wire_open_mode & SMB_O_SYNC) {
7047 create_options |= FILE_WRITE_THROUGH;
7049 if (wire_open_mode & SMB_O_APPEND) {
7050 access_mask |= FILE_APPEND_DATA;
7052 if (wire_open_mode & SMB_O_DIRECT) {
7053 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7056 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7057 smb_fname_str_dbg(smb_fname),
7058 (unsigned int)wire_open_mode,
7059 (unsigned int)unixmode ));
7061 status = SMB_VFS_CREATE_FILE(
7062 conn, /* conn */
7063 req, /* req */
7064 0, /* root_dir_fid */
7065 smb_fname, /* fname */
7066 access_mask, /* access_mask */
7067 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7068 FILE_SHARE_DELETE),
7069 create_disp, /* create_disposition*/
7070 FILE_NON_DIRECTORY_FILE, /* create_options */
7071 mod_unixmode, /* file_attributes */
7072 oplock_request, /* oplock_request */
7073 0, /* allocation_size */
7074 NULL, /* sd */
7075 NULL, /* ea_list */
7076 &fsp, /* result */
7077 &info); /* pinfo */
7079 if (!NT_STATUS_IS_OK(status)) {
7080 return status;
7083 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7084 extended_oplock_granted = True;
7087 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7088 extended_oplock_granted = True;
7091 info_level_return = SVAL(pdata,16);
7093 /* Allocate the correct return size. */
7095 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7096 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7097 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7098 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7099 } else {
7100 *pdata_return_size = 12;
7103 /* Realloc the data size */
7104 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7105 if (*ppdata == NULL) {
7106 close_file(req, fsp, ERROR_CLOSE);
7107 *pdata_return_size = 0;
7108 return NT_STATUS_NO_MEMORY;
7110 pdata = *ppdata;
7112 if (extended_oplock_granted) {
7113 if (flags & REQUEST_BATCH_OPLOCK) {
7114 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7115 } else {
7116 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7118 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7119 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7120 } else {
7121 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7124 SSVAL(pdata,2,fsp->fnum);
7125 SIVAL(pdata,4,info); /* Was file created etc. */
7127 switch (info_level_return) {
7128 case SMB_QUERY_FILE_UNIX_BASIC:
7129 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7130 SSVAL(pdata,10,0); /* padding. */
7131 store_file_unix_basic(conn, pdata + 12, fsp,
7132 &smb_fname->st);
7133 break;
7134 case SMB_QUERY_FILE_UNIX_INFO2:
7135 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7136 SSVAL(pdata,10,0); /* padding. */
7137 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7138 &smb_fname->st);
7139 break;
7140 default:
7141 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7142 SSVAL(pdata,10,0); /* padding. */
7143 break;
7145 return NT_STATUS_OK;
7148 /****************************************************************************
7149 Delete a file with POSIX semantics.
7150 ****************************************************************************/
7152 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7153 struct smb_request *req,
7154 const char *pdata,
7155 int total_data,
7156 struct smb_filename *smb_fname)
7158 NTSTATUS status = NT_STATUS_OK;
7159 files_struct *fsp = NULL;
7160 uint16 flags = 0;
7161 char del = 1;
7162 int info = 0;
7163 int create_options = 0;
7164 int i;
7165 struct share_mode_lock *lck = NULL;
7167 if (total_data < 2) {
7168 return NT_STATUS_INVALID_PARAMETER;
7171 flags = SVAL(pdata,0);
7173 if (!VALID_STAT(smb_fname->st)) {
7174 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7177 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7178 !VALID_STAT_OF_DIR(smb_fname->st)) {
7179 return NT_STATUS_NOT_A_DIRECTORY;
7182 DEBUG(10,("smb_posix_unlink: %s %s\n",
7183 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7184 smb_fname_str_dbg(smb_fname)));
7186 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7187 create_options |= FILE_DIRECTORY_FILE;
7190 status = SMB_VFS_CREATE_FILE(
7191 conn, /* conn */
7192 req, /* req */
7193 0, /* root_dir_fid */
7194 smb_fname, /* fname */
7195 DELETE_ACCESS, /* access_mask */
7196 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7197 FILE_SHARE_DELETE),
7198 FILE_OPEN, /* create_disposition*/
7199 create_options, /* create_options */
7200 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7201 0, /* oplock_request */
7202 0, /* allocation_size */
7203 NULL, /* sd */
7204 NULL, /* ea_list */
7205 &fsp, /* result */
7206 &info); /* pinfo */
7208 if (!NT_STATUS_IS_OK(status)) {
7209 return status;
7213 * Don't lie to client. If we can't really delete due to
7214 * non-POSIX opens return SHARING_VIOLATION.
7217 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7218 NULL);
7219 if (lck == NULL) {
7220 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7221 "lock for file %s\n", fsp_str_dbg(fsp)));
7222 close_file(req, fsp, NORMAL_CLOSE);
7223 return NT_STATUS_INVALID_PARAMETER;
7227 * See if others still have the file open. If this is the case, then
7228 * don't delete. If all opens are POSIX delete we can set the delete
7229 * on close disposition.
7231 for (i=0; i<lck->num_share_modes; i++) {
7232 struct share_mode_entry *e = &lck->share_modes[i];
7233 if (is_valid_share_mode_entry(e)) {
7234 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7235 continue;
7237 /* Fail with sharing violation. */
7238 close_file(req, fsp, NORMAL_CLOSE);
7239 TALLOC_FREE(lck);
7240 return NT_STATUS_SHARING_VIOLATION;
7245 * Set the delete on close.
7247 status = smb_set_file_disposition_info(conn,
7248 &del,
7250 fsp,
7251 smb_fname);
7253 if (!NT_STATUS_IS_OK(status)) {
7254 close_file(req, fsp, NORMAL_CLOSE);
7255 TALLOC_FREE(lck);
7256 return status;
7258 TALLOC_FREE(lck);
7259 return close_file(req, fsp, NORMAL_CLOSE);
7262 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7263 struct smb_request *req,
7264 TALLOC_CTX *mem_ctx,
7265 uint16_t info_level,
7266 files_struct *fsp,
7267 struct smb_filename *smb_fname,
7268 char **ppdata, int total_data,
7269 int *ret_data_size)
7271 char *pdata = *ppdata;
7272 NTSTATUS status = NT_STATUS_OK;
7273 int data_return_size = 0;
7275 *ret_data_size = 0;
7277 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7278 return NT_STATUS_INVALID_LEVEL;
7281 if (!CAN_WRITE(conn)) {
7282 /* Allow POSIX opens. The open path will deny
7283 * any non-readonly opens. */
7284 if (info_level != SMB_POSIX_PATH_OPEN) {
7285 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7289 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7290 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7291 fsp ? fsp->fnum : -1, info_level, total_data));
7293 switch (info_level) {
7295 case SMB_INFO_STANDARD:
7297 status = smb_set_info_standard(conn,
7298 pdata,
7299 total_data,
7300 fsp,
7301 smb_fname);
7302 break;
7305 case SMB_INFO_SET_EA:
7307 status = smb_info_set_ea(conn,
7308 pdata,
7309 total_data,
7310 fsp,
7311 smb_fname);
7312 break;
7315 case SMB_SET_FILE_BASIC_INFO:
7316 case SMB_FILE_BASIC_INFORMATION:
7318 status = smb_set_file_basic_info(conn,
7319 pdata,
7320 total_data,
7321 fsp,
7322 smb_fname);
7323 break;
7326 case SMB_FILE_ALLOCATION_INFORMATION:
7327 case SMB_SET_FILE_ALLOCATION_INFO:
7329 status = smb_set_file_allocation_info(conn, req,
7330 pdata,
7331 total_data,
7332 fsp,
7333 smb_fname);
7334 break;
7337 case SMB_FILE_END_OF_FILE_INFORMATION:
7338 case SMB_SET_FILE_END_OF_FILE_INFO:
7340 status = smb_set_file_end_of_file_info(conn, req,
7341 pdata,
7342 total_data,
7343 fsp,
7344 smb_fname);
7345 break;
7348 case SMB_FILE_DISPOSITION_INFORMATION:
7349 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7351 #if 0
7352 /* JRA - We used to just ignore this on a path ?
7353 * Shouldn't this be invalid level on a pathname
7354 * based call ?
7356 if (tran_call != TRANSACT2_SETFILEINFO) {
7357 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7359 #endif
7360 status = smb_set_file_disposition_info(conn,
7361 pdata,
7362 total_data,
7363 fsp,
7364 smb_fname);
7365 break;
7368 case SMB_FILE_POSITION_INFORMATION:
7370 status = smb_file_position_information(conn,
7371 pdata,
7372 total_data,
7373 fsp);
7374 break;
7377 /* From tridge Samba4 :
7378 * MODE_INFORMATION in setfileinfo (I have no
7379 * idea what "mode information" on a file is - it takes a value of 0,
7380 * 2, 4 or 6. What could it be?).
7383 case SMB_FILE_MODE_INFORMATION:
7385 status = smb_file_mode_information(conn,
7386 pdata,
7387 total_data);
7388 break;
7392 * CIFS UNIX extensions.
7395 case SMB_SET_FILE_UNIX_BASIC:
7397 status = smb_set_file_unix_basic(conn, req,
7398 pdata,
7399 total_data,
7400 fsp,
7401 smb_fname);
7402 break;
7405 case SMB_SET_FILE_UNIX_INFO2:
7407 status = smb_set_file_unix_info2(conn, req,
7408 pdata,
7409 total_data,
7410 fsp,
7411 smb_fname);
7412 break;
7415 case SMB_SET_FILE_UNIX_LINK:
7417 if (fsp) {
7418 /* We must have a pathname for this. */
7419 return NT_STATUS_INVALID_LEVEL;
7421 status = smb_set_file_unix_link(conn, req, pdata,
7422 total_data, smb_fname);
7423 break;
7426 case SMB_SET_FILE_UNIX_HLINK:
7428 if (fsp) {
7429 /* We must have a pathname for this. */
7430 return NT_STATUS_INVALID_LEVEL;
7432 status = smb_set_file_unix_hlink(conn, req,
7433 pdata, total_data,
7434 smb_fname);
7435 break;
7438 case SMB_FILE_RENAME_INFORMATION:
7440 status = smb_file_rename_information(conn, req,
7441 pdata, total_data,
7442 fsp, smb_fname);
7443 break;
7446 #if defined(HAVE_POSIX_ACLS)
7447 case SMB_SET_POSIX_ACL:
7449 status = smb_set_posix_acl(conn,
7450 pdata,
7451 total_data,
7452 fsp,
7453 smb_fname);
7454 break;
7456 #endif
7458 case SMB_SET_POSIX_LOCK:
7460 if (!fsp) {
7461 return NT_STATUS_INVALID_LEVEL;
7463 status = smb_set_posix_lock(conn, req,
7464 pdata, total_data, fsp);
7465 break;
7468 case SMB_POSIX_PATH_OPEN:
7470 if (fsp) {
7471 /* We must have a pathname for this. */
7472 return NT_STATUS_INVALID_LEVEL;
7475 status = smb_posix_open(conn, req,
7476 ppdata,
7477 total_data,
7478 smb_fname,
7479 &data_return_size);
7480 break;
7483 case SMB_POSIX_PATH_UNLINK:
7485 if (fsp) {
7486 /* We must have a pathname for this. */
7487 return NT_STATUS_INVALID_LEVEL;
7490 status = smb_posix_unlink(conn, req,
7491 pdata,
7492 total_data,
7493 smb_fname);
7494 break;
7497 default:
7498 return NT_STATUS_INVALID_LEVEL;
7501 if (!NT_STATUS_IS_OK(status)) {
7502 return status;
7505 *ret_data_size = data_return_size;
7506 return NT_STATUS_OK;
7509 /****************************************************************************
7510 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7511 ****************************************************************************/
7513 static void call_trans2setfilepathinfo(connection_struct *conn,
7514 struct smb_request *req,
7515 unsigned int tran_call,
7516 char **pparams, int total_params,
7517 char **ppdata, int total_data,
7518 unsigned int max_data_bytes)
7520 char *params = *pparams;
7521 char *pdata = *ppdata;
7522 uint16 info_level;
7523 struct smb_filename *smb_fname = NULL;
7524 files_struct *fsp = NULL;
7525 NTSTATUS status = NT_STATUS_OK;
7526 int data_return_size = 0;
7528 if (!params) {
7529 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7530 return;
7533 if (tran_call == TRANSACT2_SETFILEINFO) {
7534 if (total_params < 4) {
7535 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7536 return;
7539 fsp = file_fsp(req, SVAL(params,0));
7540 /* Basic check for non-null fsp. */
7541 if (!check_fsp_open(conn, req, fsp)) {
7542 return;
7544 info_level = SVAL(params,2);
7546 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7547 &smb_fname);
7548 if (!NT_STATUS_IS_OK(status)) {
7549 reply_nterror(req, status);
7550 return;
7553 if(fsp->is_directory || fsp->fh->fd == -1) {
7555 * This is actually a SETFILEINFO on a directory
7556 * handle (returned from an NT SMB). NT5.0 seems
7557 * to do this call. JRA.
7559 if (INFO_LEVEL_IS_UNIX(info_level)) {
7560 /* Always do lstat for UNIX calls. */
7561 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7562 DEBUG(3,("call_trans2setfilepathinfo: "
7563 "SMB_VFS_LSTAT of %s failed "
7564 "(%s)\n",
7565 smb_fname_str_dbg(smb_fname),
7566 strerror(errno)));
7567 reply_nterror(req, map_nt_error_from_unix(errno));
7568 return;
7570 } else {
7571 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7572 DEBUG(3,("call_trans2setfilepathinfo: "
7573 "fileinfo of %s failed (%s)\n",
7574 smb_fname_str_dbg(smb_fname),
7575 strerror(errno)));
7576 reply_nterror(req, map_nt_error_from_unix(errno));
7577 return;
7580 } else if (fsp->print_file) {
7582 * Doing a DELETE_ON_CLOSE should cancel a print job.
7584 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7585 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7587 DEBUG(3,("call_trans2setfilepathinfo: "
7588 "Cancelling print job (%s)\n",
7589 fsp_str_dbg(fsp)));
7591 SSVAL(params,0,0);
7592 send_trans2_replies(conn, req, params, 2,
7593 *ppdata, 0,
7594 max_data_bytes);
7595 return;
7596 } else {
7597 reply_doserror(req, ERRDOS, ERRbadpath);
7598 return;
7600 } else {
7602 * Original code - this is an open file.
7604 if (!check_fsp(conn, req, fsp)) {
7605 return;
7608 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7609 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7610 "of fnum %d failed (%s)\n", fsp->fnum,
7611 strerror(errno)));
7612 reply_nterror(req, map_nt_error_from_unix(errno));
7613 return;
7616 } else {
7617 char *fname = NULL;
7619 /* set path info */
7620 if (total_params < 7) {
7621 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7622 return;
7625 info_level = SVAL(params,0);
7626 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7627 total_params - 6, STR_TERMINATE,
7628 &status);
7629 if (!NT_STATUS_IS_OK(status)) {
7630 reply_nterror(req, status);
7631 return;
7634 status = filename_convert(req, conn,
7635 req->flags2 & FLAGS2_DFS_PATHNAMES,
7636 fname,
7638 NULL,
7639 &smb_fname);
7640 if (!NT_STATUS_IS_OK(status)) {
7641 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7642 reply_botherror(req,
7643 NT_STATUS_PATH_NOT_COVERED,
7644 ERRSRV, ERRbadpath);
7645 return;
7647 reply_nterror(req, status);
7648 return;
7651 if (INFO_LEVEL_IS_UNIX(info_level)) {
7653 * For CIFS UNIX extensions the target name may not exist.
7656 /* Always do lstat for UNIX calls. */
7657 SMB_VFS_LSTAT(conn, smb_fname);
7659 } else if (!VALID_STAT(smb_fname->st) &&
7660 SMB_VFS_STAT(conn, smb_fname)) {
7661 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7662 "%s failed (%s)\n",
7663 smb_fname_str_dbg(smb_fname),
7664 strerror(errno)));
7665 reply_nterror(req, map_nt_error_from_unix(errno));
7666 return;
7670 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7671 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7672 fsp ? fsp->fnum : -1, info_level,total_data));
7674 /* Realloc the parameter size */
7675 *pparams = (char *)SMB_REALLOC(*pparams,2);
7676 if (*pparams == NULL) {
7677 reply_nterror(req, NT_STATUS_NO_MEMORY);
7678 return;
7680 params = *pparams;
7682 SSVAL(params,0,0);
7684 status = smbd_do_setfilepathinfo(conn, req, req,
7685 info_level,
7686 fsp,
7687 smb_fname,
7688 ppdata, total_data,
7689 &data_return_size);
7690 if (!NT_STATUS_IS_OK(status)) {
7691 if (open_was_deferred(req->mid)) {
7692 /* We have re-scheduled this call. */
7693 return;
7695 if (blocking_lock_was_deferred(req->mid)) {
7696 /* We have re-scheduled this call. */
7697 return;
7699 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7700 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7701 ERRSRV, ERRbadpath);
7702 return;
7704 if (info_level == SMB_POSIX_PATH_OPEN) {
7705 reply_openerror(req, status);
7706 return;
7709 reply_nterror(req, status);
7710 return;
7713 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7714 max_data_bytes);
7716 return;
7719 /****************************************************************************
7720 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7721 ****************************************************************************/
7723 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7724 char **pparams, int total_params,
7725 char **ppdata, int total_data,
7726 unsigned int max_data_bytes)
7728 struct smb_filename *smb_dname = NULL;
7729 char *params = *pparams;
7730 char *pdata = *ppdata;
7731 char *directory = NULL;
7732 NTSTATUS status = NT_STATUS_OK;
7733 struct ea_list *ea_list = NULL;
7734 TALLOC_CTX *ctx = talloc_tos();
7736 if (!CAN_WRITE(conn)) {
7737 reply_doserror(req, ERRSRV, ERRaccess);
7738 return;
7741 if (total_params < 5) {
7742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7743 return;
7746 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7747 total_params - 4, STR_TERMINATE,
7748 &status);
7749 if (!NT_STATUS_IS_OK(status)) {
7750 reply_nterror(req, status);
7751 return;
7754 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7756 status = filename_convert(ctx,
7757 conn,
7758 req->flags2 & FLAGS2_DFS_PATHNAMES,
7759 directory,
7761 NULL,
7762 &smb_dname);
7764 if (!NT_STATUS_IS_OK(status)) {
7765 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7766 reply_botherror(req,
7767 NT_STATUS_PATH_NOT_COVERED,
7768 ERRSRV, ERRbadpath);
7769 return;
7771 reply_nterror(req, status);
7772 return;
7775 /* Any data in this call is an EA list. */
7776 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7777 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7778 goto out;
7782 * OS/2 workplace shell seems to send SET_EA requests of "null"
7783 * length (4 bytes containing IVAL 4).
7784 * They seem to have no effect. Bug #3212. JRA.
7787 if (total_data != 4) {
7788 if (total_data < 10) {
7789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7790 goto out;
7793 if (IVAL(pdata,0) > total_data) {
7794 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7795 IVAL(pdata,0), (unsigned int)total_data));
7796 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7797 goto out;
7800 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7801 total_data - 4);
7802 if (!ea_list) {
7803 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7804 goto out;
7807 /* If total_data == 4 Windows doesn't care what values
7808 * are placed in that field, it just ignores them.
7809 * The System i QNTC IBM SMB client puts bad values here,
7810 * so ignore them. */
7812 status = create_directory(conn, req, smb_dname);
7814 if (!NT_STATUS_IS_OK(status)) {
7815 reply_nterror(req, status);
7816 goto out;
7819 /* Try and set any given EA. */
7820 if (ea_list) {
7821 status = set_ea(conn, NULL, smb_dname, ea_list);
7822 if (!NT_STATUS_IS_OK(status)) {
7823 reply_nterror(req, status);
7824 goto out;
7828 /* Realloc the parameter and data sizes */
7829 *pparams = (char *)SMB_REALLOC(*pparams,2);
7830 if(*pparams == NULL) {
7831 reply_nterror(req, NT_STATUS_NO_MEMORY);
7832 goto out;
7834 params = *pparams;
7836 SSVAL(params,0,0);
7838 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7840 out:
7841 TALLOC_FREE(smb_dname);
7842 return;
7845 /****************************************************************************
7846 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7847 We don't actually do this - we just send a null response.
7848 ****************************************************************************/
7850 static void call_trans2findnotifyfirst(connection_struct *conn,
7851 struct smb_request *req,
7852 char **pparams, int total_params,
7853 char **ppdata, int total_data,
7854 unsigned int max_data_bytes)
7856 char *params = *pparams;
7857 uint16 info_level;
7859 if (total_params < 6) {
7860 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7861 return;
7864 info_level = SVAL(params,4);
7865 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7867 switch (info_level) {
7868 case 1:
7869 case 2:
7870 break;
7871 default:
7872 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7873 return;
7876 /* Realloc the parameter and data sizes */
7877 *pparams = (char *)SMB_REALLOC(*pparams,6);
7878 if (*pparams == NULL) {
7879 reply_nterror(req, NT_STATUS_NO_MEMORY);
7880 return;
7882 params = *pparams;
7884 SSVAL(params,0,fnf_handle);
7885 SSVAL(params,2,0); /* No changes */
7886 SSVAL(params,4,0); /* No EA errors */
7888 fnf_handle++;
7890 if(fnf_handle == 0)
7891 fnf_handle = 257;
7893 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7895 return;
7898 /****************************************************************************
7899 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7900 changes). Currently this does nothing.
7901 ****************************************************************************/
7903 static void call_trans2findnotifynext(connection_struct *conn,
7904 struct smb_request *req,
7905 char **pparams, int total_params,
7906 char **ppdata, int total_data,
7907 unsigned int max_data_bytes)
7909 char *params = *pparams;
7911 DEBUG(3,("call_trans2findnotifynext\n"));
7913 /* Realloc the parameter and data sizes */
7914 *pparams = (char *)SMB_REALLOC(*pparams,4);
7915 if (*pparams == NULL) {
7916 reply_nterror(req, NT_STATUS_NO_MEMORY);
7917 return;
7919 params = *pparams;
7921 SSVAL(params,0,0); /* No changes */
7922 SSVAL(params,2,0); /* No EA errors */
7924 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7926 return;
7929 /****************************************************************************
7930 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7931 ****************************************************************************/
7933 static void call_trans2getdfsreferral(connection_struct *conn,
7934 struct smb_request *req,
7935 char **pparams, int total_params,
7936 char **ppdata, int total_data,
7937 unsigned int max_data_bytes)
7939 char *params = *pparams;
7940 char *pathname = NULL;
7941 int reply_size = 0;
7942 int max_referral_level;
7943 NTSTATUS status = NT_STATUS_OK;
7944 TALLOC_CTX *ctx = talloc_tos();
7946 DEBUG(10,("call_trans2getdfsreferral\n"));
7948 if (total_params < 3) {
7949 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7950 return;
7953 max_referral_level = SVAL(params,0);
7955 if(!lp_host_msdfs()) {
7956 reply_doserror(req, ERRDOS, ERRbadfunc);
7957 return;
7960 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7961 total_params - 2, STR_TERMINATE);
7962 if (!pathname) {
7963 reply_nterror(req, NT_STATUS_NOT_FOUND);
7964 return;
7966 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7967 ppdata,&status)) < 0) {
7968 reply_nterror(req, status);
7969 return;
7972 SSVAL(req->inbuf, smb_flg2,
7973 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7974 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7976 return;
7979 #define LMCAT_SPL 0x53
7980 #define LMFUNC_GETJOBID 0x60
7982 /****************************************************************************
7983 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7984 ****************************************************************************/
7986 static void call_trans2ioctl(connection_struct *conn,
7987 struct smb_request *req,
7988 char **pparams, int total_params,
7989 char **ppdata, int total_data,
7990 unsigned int max_data_bytes)
7992 char *pdata = *ppdata;
7993 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7995 /* check for an invalid fid before proceeding */
7997 if (!fsp) {
7998 reply_doserror(req, ERRDOS, ERRbadfid);
7999 return;
8002 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8003 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8004 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8005 if (*ppdata == NULL) {
8006 reply_nterror(req, NT_STATUS_NO_MEMORY);
8007 return;
8009 pdata = *ppdata;
8011 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8012 CAN ACCEPT THIS IN UNICODE. JRA. */
8014 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8015 srvstr_push(pdata, req->flags2, pdata + 2,
8016 global_myname(), 15,
8017 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8018 srvstr_push(pdata, req->flags2, pdata+18,
8019 lp_servicename(SNUM(conn)), 13,
8020 STR_ASCII|STR_TERMINATE); /* Service name */
8021 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8022 max_data_bytes);
8023 return;
8026 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8027 reply_doserror(req, ERRSRV, ERRerror);
8030 /****************************************************************************
8031 Reply to a SMBfindclose (stop trans2 directory search).
8032 ****************************************************************************/
8034 void reply_findclose(struct smb_request *req)
8036 int dptr_num;
8037 struct smbd_server_connection *sconn = smbd_server_conn;
8039 START_PROFILE(SMBfindclose);
8041 if (req->wct < 1) {
8042 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8043 END_PROFILE(SMBfindclose);
8044 return;
8047 dptr_num = SVALS(req->vwv+0, 0);
8049 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8051 dptr_close(sconn, &dptr_num);
8053 reply_outbuf(req, 0, 0);
8055 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8057 END_PROFILE(SMBfindclose);
8058 return;
8061 /****************************************************************************
8062 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8063 ****************************************************************************/
8065 void reply_findnclose(struct smb_request *req)
8067 int dptr_num;
8069 START_PROFILE(SMBfindnclose);
8071 if (req->wct < 1) {
8072 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8073 END_PROFILE(SMBfindnclose);
8074 return;
8077 dptr_num = SVAL(req->vwv+0, 0);
8079 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8081 /* We never give out valid handles for a
8082 findnotifyfirst - so any dptr_num is ok here.
8083 Just ignore it. */
8085 reply_outbuf(req, 0, 0);
8087 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8089 END_PROFILE(SMBfindnclose);
8090 return;
8093 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8094 struct trans_state *state)
8096 if (Protocol >= PROTOCOL_NT1) {
8097 req->flags2 |= 0x40; /* IS_LONG_NAME */
8098 SSVAL(req->inbuf,smb_flg2,req->flags2);
8101 if (conn->encrypt_level == Required && !req->encrypted) {
8102 if (state->call != TRANSACT2_QFSINFO &&
8103 state->call != TRANSACT2_SETFSINFO) {
8104 DEBUG(0,("handle_trans2: encryption required "
8105 "with call 0x%x\n",
8106 (unsigned int)state->call));
8107 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8108 return;
8112 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8114 /* Now we must call the relevant TRANS2 function */
8115 switch(state->call) {
8116 case TRANSACT2_OPEN:
8118 START_PROFILE(Trans2_open);
8119 call_trans2open(conn, req,
8120 &state->param, state->total_param,
8121 &state->data, state->total_data,
8122 state->max_data_return);
8123 END_PROFILE(Trans2_open);
8124 break;
8127 case TRANSACT2_FINDFIRST:
8129 START_PROFILE(Trans2_findfirst);
8130 call_trans2findfirst(conn, req,
8131 &state->param, state->total_param,
8132 &state->data, state->total_data,
8133 state->max_data_return);
8134 END_PROFILE(Trans2_findfirst);
8135 break;
8138 case TRANSACT2_FINDNEXT:
8140 START_PROFILE(Trans2_findnext);
8141 call_trans2findnext(conn, req,
8142 &state->param, state->total_param,
8143 &state->data, state->total_data,
8144 state->max_data_return);
8145 END_PROFILE(Trans2_findnext);
8146 break;
8149 case TRANSACT2_QFSINFO:
8151 START_PROFILE(Trans2_qfsinfo);
8152 call_trans2qfsinfo(conn, req,
8153 &state->param, state->total_param,
8154 &state->data, state->total_data,
8155 state->max_data_return);
8156 END_PROFILE(Trans2_qfsinfo);
8157 break;
8160 case TRANSACT2_SETFSINFO:
8162 START_PROFILE(Trans2_setfsinfo);
8163 call_trans2setfsinfo(conn, req,
8164 &state->param, state->total_param,
8165 &state->data, state->total_data,
8166 state->max_data_return);
8167 END_PROFILE(Trans2_setfsinfo);
8168 break;
8171 case TRANSACT2_QPATHINFO:
8172 case TRANSACT2_QFILEINFO:
8174 START_PROFILE(Trans2_qpathinfo);
8175 call_trans2qfilepathinfo(conn, req, state->call,
8176 &state->param, state->total_param,
8177 &state->data, state->total_data,
8178 state->max_data_return);
8179 END_PROFILE(Trans2_qpathinfo);
8180 break;
8183 case TRANSACT2_SETPATHINFO:
8184 case TRANSACT2_SETFILEINFO:
8186 START_PROFILE(Trans2_setpathinfo);
8187 call_trans2setfilepathinfo(conn, req, state->call,
8188 &state->param, state->total_param,
8189 &state->data, state->total_data,
8190 state->max_data_return);
8191 END_PROFILE(Trans2_setpathinfo);
8192 break;
8195 case TRANSACT2_FINDNOTIFYFIRST:
8197 START_PROFILE(Trans2_findnotifyfirst);
8198 call_trans2findnotifyfirst(conn, req,
8199 &state->param, state->total_param,
8200 &state->data, state->total_data,
8201 state->max_data_return);
8202 END_PROFILE(Trans2_findnotifyfirst);
8203 break;
8206 case TRANSACT2_FINDNOTIFYNEXT:
8208 START_PROFILE(Trans2_findnotifynext);
8209 call_trans2findnotifynext(conn, req,
8210 &state->param, state->total_param,
8211 &state->data, state->total_data,
8212 state->max_data_return);
8213 END_PROFILE(Trans2_findnotifynext);
8214 break;
8217 case TRANSACT2_MKDIR:
8219 START_PROFILE(Trans2_mkdir);
8220 call_trans2mkdir(conn, req,
8221 &state->param, state->total_param,
8222 &state->data, state->total_data,
8223 state->max_data_return);
8224 END_PROFILE(Trans2_mkdir);
8225 break;
8228 case TRANSACT2_GET_DFS_REFERRAL:
8230 START_PROFILE(Trans2_get_dfs_referral);
8231 call_trans2getdfsreferral(conn, req,
8232 &state->param, state->total_param,
8233 &state->data, state->total_data,
8234 state->max_data_return);
8235 END_PROFILE(Trans2_get_dfs_referral);
8236 break;
8239 case TRANSACT2_IOCTL:
8241 START_PROFILE(Trans2_ioctl);
8242 call_trans2ioctl(conn, req,
8243 &state->param, state->total_param,
8244 &state->data, state->total_data,
8245 state->max_data_return);
8246 END_PROFILE(Trans2_ioctl);
8247 break;
8250 default:
8251 /* Error in request */
8252 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8253 reply_doserror(req, ERRSRV,ERRerror);
8257 /****************************************************************************
8258 Reply to a SMBtrans2.
8259 ****************************************************************************/
8261 void reply_trans2(struct smb_request *req)
8263 connection_struct *conn = req->conn;
8264 unsigned int dsoff;
8265 unsigned int dscnt;
8266 unsigned int psoff;
8267 unsigned int pscnt;
8268 unsigned int tran_call;
8269 struct trans_state *state;
8270 NTSTATUS result;
8272 START_PROFILE(SMBtrans2);
8274 if (req->wct < 14) {
8275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8276 END_PROFILE(SMBtrans2);
8277 return;
8280 dsoff = SVAL(req->vwv+12, 0);
8281 dscnt = SVAL(req->vwv+11, 0);
8282 psoff = SVAL(req->vwv+10, 0);
8283 pscnt = SVAL(req->vwv+9, 0);
8284 tran_call = SVAL(req->vwv+14, 0);
8286 result = allow_new_trans(conn->pending_trans, req->mid);
8287 if (!NT_STATUS_IS_OK(result)) {
8288 DEBUG(2, ("Got invalid trans2 request: %s\n",
8289 nt_errstr(result)));
8290 reply_nterror(req, result);
8291 END_PROFILE(SMBtrans2);
8292 return;
8295 if (IS_IPC(conn)) {
8296 switch (tran_call) {
8297 /* List the allowed trans2 calls on IPC$ */
8298 case TRANSACT2_OPEN:
8299 case TRANSACT2_GET_DFS_REFERRAL:
8300 case TRANSACT2_QFILEINFO:
8301 case TRANSACT2_QFSINFO:
8302 case TRANSACT2_SETFSINFO:
8303 break;
8304 default:
8305 reply_doserror(req, ERRSRV, ERRaccess);
8306 END_PROFILE(SMBtrans2);
8307 return;
8311 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8312 DEBUG(0, ("talloc failed\n"));
8313 reply_nterror(req, NT_STATUS_NO_MEMORY);
8314 END_PROFILE(SMBtrans2);
8315 return;
8318 state->cmd = SMBtrans2;
8320 state->mid = req->mid;
8321 state->vuid = req->vuid;
8322 state->setup_count = SVAL(req->vwv+13, 0);
8323 state->setup = NULL;
8324 state->total_param = SVAL(req->vwv+0, 0);
8325 state->param = NULL;
8326 state->total_data = SVAL(req->vwv+1, 0);
8327 state->data = NULL;
8328 state->max_param_return = SVAL(req->vwv+2, 0);
8329 state->max_data_return = SVAL(req->vwv+3, 0);
8330 state->max_setup_return = SVAL(req->vwv+4, 0);
8331 state->close_on_completion = BITSETW(req->vwv+5, 0);
8332 state->one_way = BITSETW(req->vwv+5, 1);
8334 state->call = tran_call;
8336 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8337 is so as a sanity check */
8338 if (state->setup_count != 1) {
8340 * Need to have rc=0 for ioctl to get job id for OS/2.
8341 * Network printing will fail if function is not successful.
8342 * Similar function in reply.c will be used if protocol
8343 * is LANMAN1.0 instead of LM1.2X002.
8344 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8345 * outbuf doesn't have to be set(only job id is used).
8347 if ( (state->setup_count == 4)
8348 && (tran_call == TRANSACT2_IOCTL)
8349 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8350 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8351 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8352 } else {
8353 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8354 DEBUG(2,("Transaction is %d\n",tran_call));
8355 TALLOC_FREE(state);
8356 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8357 END_PROFILE(SMBtrans2);
8358 return;
8362 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8363 goto bad_param;
8365 if (state->total_data) {
8367 if (trans_oob(state->total_data, 0, dscnt)
8368 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8369 goto bad_param;
8372 /* Can't use talloc here, the core routines do realloc on the
8373 * params and data. */
8374 state->data = (char *)SMB_MALLOC(state->total_data);
8375 if (state->data == NULL) {
8376 DEBUG(0,("reply_trans2: data malloc fail for %u "
8377 "bytes !\n", (unsigned int)state->total_data));
8378 TALLOC_FREE(state);
8379 reply_nterror(req, NT_STATUS_NO_MEMORY);
8380 END_PROFILE(SMBtrans2);
8381 return;
8384 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8387 if (state->total_param) {
8389 if (trans_oob(state->total_param, 0, pscnt)
8390 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8391 goto bad_param;
8394 /* Can't use talloc here, the core routines do realloc on the
8395 * params and data. */
8396 state->param = (char *)SMB_MALLOC(state->total_param);
8397 if (state->param == NULL) {
8398 DEBUG(0,("reply_trans: param malloc fail for %u "
8399 "bytes !\n", (unsigned int)state->total_param));
8400 SAFE_FREE(state->data);
8401 TALLOC_FREE(state);
8402 reply_nterror(req, NT_STATUS_NO_MEMORY);
8403 END_PROFILE(SMBtrans2);
8404 return;
8407 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8410 state->received_data = dscnt;
8411 state->received_param = pscnt;
8413 if ((state->received_param == state->total_param) &&
8414 (state->received_data == state->total_data)) {
8416 handle_trans2(conn, req, state);
8418 SAFE_FREE(state->data);
8419 SAFE_FREE(state->param);
8420 TALLOC_FREE(state);
8421 END_PROFILE(SMBtrans2);
8422 return;
8425 DLIST_ADD(conn->pending_trans, state);
8427 /* We need to send an interim response then receive the rest
8428 of the parameter/data bytes */
8429 reply_outbuf(req, 0, 0);
8430 show_msg((char *)req->outbuf);
8431 END_PROFILE(SMBtrans2);
8432 return;
8434 bad_param:
8436 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8437 SAFE_FREE(state->data);
8438 SAFE_FREE(state->param);
8439 TALLOC_FREE(state);
8440 END_PROFILE(SMBtrans2);
8441 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8445 /****************************************************************************
8446 Reply to a SMBtranss2
8447 ****************************************************************************/
8449 void reply_transs2(struct smb_request *req)
8451 connection_struct *conn = req->conn;
8452 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8453 struct trans_state *state;
8455 START_PROFILE(SMBtranss2);
8457 show_msg((char *)req->inbuf);
8459 if (req->wct < 8) {
8460 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8461 END_PROFILE(SMBtranss2);
8462 return;
8465 for (state = conn->pending_trans; state != NULL;
8466 state = state->next) {
8467 if (state->mid == req->mid) {
8468 break;
8472 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8473 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8474 END_PROFILE(SMBtranss2);
8475 return;
8478 /* Revise state->total_param and state->total_data in case they have
8479 changed downwards */
8481 if (SVAL(req->vwv+0, 0) < state->total_param)
8482 state->total_param = SVAL(req->vwv+0, 0);
8483 if (SVAL(req->vwv+1, 0) < state->total_data)
8484 state->total_data = SVAL(req->vwv+1, 0);
8486 pcnt = SVAL(req->vwv+2, 0);
8487 poff = SVAL(req->vwv+3, 0);
8488 pdisp = SVAL(req->vwv+4, 0);
8490 dcnt = SVAL(req->vwv+5, 0);
8491 doff = SVAL(req->vwv+6, 0);
8492 ddisp = SVAL(req->vwv+7, 0);
8494 state->received_param += pcnt;
8495 state->received_data += dcnt;
8497 if ((state->received_data > state->total_data) ||
8498 (state->received_param > state->total_param))
8499 goto bad_param;
8501 if (pcnt) {
8502 if (trans_oob(state->total_param, pdisp, pcnt)
8503 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8504 goto bad_param;
8506 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8509 if (dcnt) {
8510 if (trans_oob(state->total_data, ddisp, dcnt)
8511 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8512 goto bad_param;
8514 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8517 if ((state->received_param < state->total_param) ||
8518 (state->received_data < state->total_data)) {
8519 END_PROFILE(SMBtranss2);
8520 return;
8523 handle_trans2(conn, req, state);
8525 DLIST_REMOVE(conn->pending_trans, state);
8526 SAFE_FREE(state->data);
8527 SAFE_FREE(state->param);
8528 TALLOC_FREE(state);
8530 END_PROFILE(SMBtranss2);
8531 return;
8533 bad_param:
8535 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8536 DLIST_REMOVE(conn->pending_trans, state);
8537 SAFE_FREE(state->data);
8538 SAFE_FREE(state->param);
8539 TALLOC_FREE(state);
8540 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8541 END_PROFILE(SMBtranss2);
8542 return;