s3:smbd: split out smbd_do_qfsinfo() from call_trans2qfsinfo()
[Samba/fernandojvsilva.git] / source3 / smbd / trans2.c
blob2ee3938aecfe11742da2c542121ff3ec4bf53937
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 NULL
78 int i;
80 for (i = 0; prohibited_ea_names[i]; i++) {
81 if (strequal( prohibited_ea_names[i], unix_ea_name))
82 return true;
84 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
86 return true;
88 return false;
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
96 files_struct *fsp, const char *fname,
97 const char *ea_name, struct ea_struct *pea)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size = 256;
101 char *val = NULL;
102 ssize_t sizeret;
104 again:
106 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
107 if (!val) {
108 return NT_STATUS_NO_MEMORY;
111 if (fsp && fsp->fh->fd != -1) {
112 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
113 } else {
114 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
117 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
118 attr_size = 65536;
119 goto again;
122 if (sizeret == -1) {
123 return map_nt_error_from_unix(errno);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
127 dump_data(10, (uint8 *)val, sizeret);
129 pea->flags = 0;
130 if (strnequal(ea_name, "user.", 5)) {
131 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
132 } else {
133 pea->name = talloc_strdup(mem_ctx, ea_name);
135 if (pea->name == NULL) {
136 TALLOC_FREE(val);
137 return NT_STATUS_NO_MEMORY;
139 pea->value.data = (unsigned char *)val;
140 pea->value.length = (size_t)sizeret;
141 return NT_STATUS_OK;
144 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
145 files_struct *fsp, const char *fname,
146 char ***pnames, size_t *pnum_names)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size = 1024;
150 char *ea_namelist = NULL;
152 char *p;
153 char **names, **tmp;
154 size_t num_names;
155 ssize_t sizeret = -1;
157 if (!lp_ea_support(SNUM(conn))) {
158 *pnames = NULL;
159 *pnum_names = 0;
160 return NT_STATUS_OK;
164 * TALLOC the result early to get the talloc hierarchy right.
167 names = TALLOC_ARRAY(mem_ctx, char *, 1);
168 if (names == NULL) {
169 DEBUG(0, ("talloc failed\n"));
170 return NT_STATUS_NO_MEMORY;
173 while (ea_namelist_size <= 65536) {
175 ea_namelist = TALLOC_REALLOC_ARRAY(
176 names, ea_namelist, char, ea_namelist_size);
177 if (ea_namelist == NULL) {
178 DEBUG(0, ("talloc failed\n"));
179 TALLOC_FREE(names);
180 return NT_STATUS_NO_MEMORY;
183 if (fsp && fsp->fh->fd != -1) {
184 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
185 ea_namelist_size);
186 } else {
187 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
188 ea_namelist_size);
191 if ((sizeret == -1) && (errno == ERANGE)) {
192 ea_namelist_size *= 2;
194 else {
195 break;
199 if (sizeret == -1) {
200 TALLOC_FREE(names);
201 return map_nt_error_from_unix(errno);
204 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
205 (unsigned int)sizeret));
207 if (sizeret == 0) {
208 TALLOC_FREE(names);
209 *pnames = NULL;
210 *pnum_names = 0;
211 return NT_STATUS_OK;
215 * Ensure the result is 0-terminated
218 if (ea_namelist[sizeret-1] != '\0') {
219 TALLOC_FREE(names);
220 return NT_STATUS_INTERNAL_ERROR;
224 * count the names
226 num_names = 0;
228 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
229 num_names += 1;
232 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
233 if (tmp == NULL) {
234 DEBUG(0, ("talloc failed\n"));
235 TALLOC_FREE(names);
236 return NT_STATUS_NO_MEMORY;
239 names = tmp;
240 num_names = 0;
242 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
243 names[num_names++] = p;
246 *pnames = names;
247 *pnum_names = num_names;
248 return NT_STATUS_OK;
251 /****************************************************************************
252 Return a linked list of the total EA's. Plus the total size
253 ****************************************************************************/
255 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
256 const char *fname, size_t *pea_total_len)
258 /* Get a list of all xattrs. Max namesize is 64k. */
259 size_t i, num_names;
260 char **names;
261 struct ea_list *ea_list_head = NULL;
262 NTSTATUS status;
264 *pea_total_len = 0;
266 if (!lp_ea_support(SNUM(conn))) {
267 return NULL;
270 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
271 &names, &num_names);
273 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
274 return NULL;
277 for (i=0; i<num_names; i++) {
278 struct ea_list *listp;
279 fstring dos_ea_name;
281 if (strnequal(names[i], "system.", 7)
282 || samba_private_attr_name(names[i]))
283 continue;
285 listp = TALLOC_P(mem_ctx, struct ea_list);
286 if (listp == NULL) {
287 return NULL;
290 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
291 fname, names[i],
292 &listp->ea))) {
293 return NULL;
296 push_ascii_fstring(dos_ea_name, listp->ea.name);
298 *pea_total_len +=
299 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
301 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
302 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
303 (unsigned int)listp->ea.value.length));
305 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
309 /* Add on 4 for total length. */
310 if (*pea_total_len) {
311 *pea_total_len += 4;
314 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
315 (unsigned int)*pea_total_len));
317 return ea_list_head;
320 /****************************************************************************
321 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
322 that was filled.
323 ****************************************************************************/
325 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
326 connection_struct *conn, struct ea_list *ea_list)
328 unsigned int ret_data_size = 4;
329 char *p = pdata;
331 SMB_ASSERT(total_data_size >= 4);
333 if (!lp_ea_support(SNUM(conn))) {
334 SIVAL(pdata,4,0);
335 return 4;
338 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
339 size_t dos_namelen;
340 fstring dos_ea_name;
341 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
342 dos_namelen = strlen(dos_ea_name);
343 if (dos_namelen > 255 || dos_namelen == 0) {
344 break;
346 if (ea_list->ea.value.length > 65535) {
347 break;
349 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
350 break;
353 /* We know we have room. */
354 SCVAL(p,0,ea_list->ea.flags);
355 SCVAL(p,1,dos_namelen);
356 SSVAL(p,2,ea_list->ea.value.length);
357 fstrcpy(p+4, dos_ea_name);
358 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
360 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
361 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
364 ret_data_size = PTR_DIFF(p, pdata);
365 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
366 SIVAL(pdata,0,ret_data_size);
367 return ret_data_size;
370 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
371 char *pdata,
372 unsigned int total_data_size,
373 unsigned int *ret_data_size,
374 connection_struct *conn,
375 struct ea_list *ea_list)
377 uint8_t *p = (uint8_t *)pdata;
378 uint8_t *last_start = NULL;
380 *ret_data_size = 0;
382 if (!lp_ea_support(SNUM(conn))) {
383 return NT_STATUS_NO_EAS_ON_FILE;
386 for (; ea_list; ea_list = ea_list->next) {
387 size_t dos_namelen;
388 fstring dos_ea_name;
389 size_t this_size;
391 if (last_start) {
392 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
394 last_start = p;
396 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
397 dos_namelen = strlen(dos_ea_name);
398 if (dos_namelen > 255 || dos_namelen == 0) {
399 return NT_STATUS_INTERNAL_ERROR;
401 if (ea_list->ea.value.length > 65535) {
402 return NT_STATUS_INTERNAL_ERROR;
405 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
407 if (ea_list->next) {
408 size_t pad = 4 - (this_size % 4);
409 this_size += pad;
412 if (this_size > total_data_size) {
413 return NT_STATUS_INFO_LENGTH_MISMATCH;
416 /* We know we have room. */
417 SIVAL(p, 0x00, 0); /* next offset */
418 SCVAL(p, 0x04, ea_list->ea.flags);
419 SCVAL(p, 0x05, dos_namelen);
420 SSVAL(p, 0x06, ea_list->ea.value.length);
421 fstrcpy((char *)(p+0x08), dos_ea_name);
422 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
424 total_data_size -= this_size;
425 p += this_size;
428 *ret_data_size = PTR_DIFF(p, pdata);
429 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
430 return NT_STATUS_OK;
433 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
435 size_t total_ea_len = 0;
436 TALLOC_CTX *mem_ctx = NULL;
438 if (!lp_ea_support(SNUM(conn))) {
439 return 0;
441 mem_ctx = talloc_tos();
442 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
443 return total_ea_len;
446 /****************************************************************************
447 Ensure the EA name is case insensitive by matching any existing EA name.
448 ****************************************************************************/
450 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
452 size_t total_ea_len;
453 TALLOC_CTX *mem_ctx = talloc_tos();
454 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
456 for (; ea_list; ea_list = ea_list->next) {
457 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
458 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
459 &unix_ea_name[5], ea_list->ea.name));
460 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
461 break;
466 /****************************************************************************
467 Set or delete an extended attribute.
468 ****************************************************************************/
470 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
471 const struct smb_filename *smb_fname, struct ea_list *ea_list)
473 char *fname = NULL;
474 NTSTATUS status;
476 if (!lp_ea_support(SNUM(conn))) {
477 return NT_STATUS_EAS_NOT_SUPPORTED;
480 status = get_full_smb_filename(talloc_tos(), smb_fname,
481 &fname);
482 if (!NT_STATUS_IS_OK(status)) {
483 return status;
486 for (;ea_list; ea_list = ea_list->next) {
487 int ret;
488 fstring unix_ea_name;
490 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
491 fstrcat(unix_ea_name, ea_list->ea.name);
493 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
495 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
497 if (samba_private_attr_name(unix_ea_name)) {
498 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
499 return NT_STATUS_ACCESS_DENIED;
502 if (ea_list->ea.value.length == 0) {
503 /* Remove the attribute. */
504 if (fsp && (fsp->fh->fd != -1)) {
505 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
506 unix_ea_name, fsp->fsp_name));
507 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
508 } else {
509 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
510 unix_ea_name, fname));
511 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
513 #ifdef ENOATTR
514 /* Removing a non existent attribute always succeeds. */
515 if (ret == -1 && errno == ENOATTR) {
516 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
517 unix_ea_name));
518 ret = 0;
520 #endif
521 } else {
522 if (fsp && (fsp->fh->fd != -1)) {
523 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
524 unix_ea_name, fsp->fsp_name));
525 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
526 ea_list->ea.value.data, ea_list->ea.value.length, 0);
527 } else {
528 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
529 unix_ea_name, fname));
530 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
531 ea_list->ea.value.data, ea_list->ea.value.length, 0);
535 if (ret == -1) {
536 #ifdef ENOTSUP
537 if (errno == ENOTSUP) {
538 return NT_STATUS_EAS_NOT_SUPPORTED;
540 #endif
541 return map_nt_error_from_unix(errno);
545 return NT_STATUS_OK;
547 /****************************************************************************
548 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
549 ****************************************************************************/
551 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
553 struct ea_list *ea_list_head = NULL;
554 size_t converted_size, offset = 0;
556 while (offset + 2 < data_size) {
557 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
558 unsigned int namelen = CVAL(pdata,offset);
560 offset++; /* Go past the namelen byte. */
562 /* integer wrap paranioa. */
563 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
564 (offset > data_size) || (namelen > data_size) ||
565 (offset + namelen >= data_size)) {
566 break;
568 /* Ensure the name is null terminated. */
569 if (pdata[offset + namelen] != '\0') {
570 return NULL;
572 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
573 &converted_size)) {
574 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
575 "failed: %s", strerror(errno)));
577 if (!eal->ea.name) {
578 return NULL;
581 offset += (namelen + 1); /* Go past the name + terminating zero. */
582 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
583 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
586 return ea_list_head;
589 /****************************************************************************
590 Read one EA list entry from the buffer.
591 ****************************************************************************/
593 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
595 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
596 uint16 val_len;
597 unsigned int namelen;
598 size_t converted_size;
600 if (!eal) {
601 return NULL;
604 if (data_size < 6) {
605 return NULL;
608 eal->ea.flags = CVAL(pdata,0);
609 namelen = CVAL(pdata,1);
610 val_len = SVAL(pdata,2);
612 if (4 + namelen + 1 + val_len > data_size) {
613 return NULL;
616 /* Ensure the name is null terminated. */
617 if (pdata[namelen + 4] != '\0') {
618 return NULL;
620 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
621 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
622 strerror(errno)));
624 if (!eal->ea.name) {
625 return NULL;
628 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
629 if (!eal->ea.value.data) {
630 return NULL;
633 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
635 /* Ensure we're null terminated just in case we print the value. */
636 eal->ea.value.data[val_len] = '\0';
637 /* But don't count the null. */
638 eal->ea.value.length--;
640 if (pbytes_used) {
641 *pbytes_used = 4 + namelen + 1 + val_len;
644 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
645 dump_data(10, eal->ea.value.data, eal->ea.value.length);
647 return eal;
650 /****************************************************************************
651 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
652 ****************************************************************************/
654 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
656 struct ea_list *ea_list_head = NULL;
657 size_t offset = 0;
658 size_t bytes_used = 0;
660 while (offset < data_size) {
661 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
663 if (!eal) {
664 return NULL;
667 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
668 offset += bytes_used;
671 return ea_list_head;
674 /****************************************************************************
675 Count the total EA size needed.
676 ****************************************************************************/
678 static size_t ea_list_size(struct ea_list *ealist)
680 fstring dos_ea_name;
681 struct ea_list *listp;
682 size_t ret = 0;
684 for (listp = ealist; listp; listp = listp->next) {
685 push_ascii_fstring(dos_ea_name, listp->ea.name);
686 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
688 /* Add on 4 for total length. */
689 if (ret) {
690 ret += 4;
693 return ret;
696 /****************************************************************************
697 Return a union of EA's from a file list and a list of names.
698 The TALLOC context for the two lists *MUST* be identical as we steal
699 memory from one list to add to another. JRA.
700 ****************************************************************************/
702 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
704 struct ea_list *nlistp, *flistp;
706 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
707 for (flistp = file_list; flistp; flistp = flistp->next) {
708 if (strequal(nlistp->ea.name, flistp->ea.name)) {
709 break;
713 if (flistp) {
714 /* Copy the data from this entry. */
715 nlistp->ea.flags = flistp->ea.flags;
716 nlistp->ea.value = flistp->ea.value;
717 } else {
718 /* Null entry. */
719 nlistp->ea.flags = 0;
720 ZERO_STRUCT(nlistp->ea.value);
724 *total_ea_len = ea_list_size(name_list);
725 return name_list;
728 /****************************************************************************
729 Send the required number of replies back.
730 We assume all fields other than the data fields are
731 set correctly for the type of call.
732 HACK ! Always assumes smb_setup field is zero.
733 ****************************************************************************/
735 void send_trans2_replies(connection_struct *conn,
736 struct smb_request *req,
737 const char *params,
738 int paramsize,
739 const char *pdata,
740 int datasize,
741 int max_data_bytes)
743 /* As we are using a protocol > LANMAN1 then the max_send
744 variable must have been set in the sessetupX call.
745 This takes precedence over the max_xmit field in the
746 global struct. These different max_xmit variables should
747 be merged as this is now too confusing */
749 int data_to_send = datasize;
750 int params_to_send = paramsize;
751 int useable_space;
752 const char *pp = params;
753 const char *pd = pdata;
754 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
755 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
756 int data_alignment_offset = 0;
757 bool overflow = False;
758 struct smbd_server_connection *sconn = smbd_server_conn;
759 int max_send = sconn->smb1.sessions.max_send;
761 /* Modify the data_to_send and datasize and set the error if
762 we're trying to send more than max_data_bytes. We still send
763 the part of the packet(s) that fit. Strange, but needed
764 for OS/2. */
766 if (max_data_bytes > 0 && datasize > max_data_bytes) {
767 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
768 max_data_bytes, datasize ));
769 datasize = data_to_send = max_data_bytes;
770 overflow = True;
773 /* If there genuinely are no parameters or data to send just send the empty packet */
775 if(params_to_send == 0 && data_to_send == 0) {
776 reply_outbuf(req, 10, 0);
777 show_msg((char *)req->outbuf);
778 if (!srv_send_smb(smbd_server_fd(),
779 (char *)req->outbuf,
780 true, req->seqnum+1,
781 IS_CONN_ENCRYPTED(conn),
782 &req->pcd)) {
783 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
785 TALLOC_FREE(req->outbuf);
786 return;
789 /* When sending params and data ensure that both are nicely aligned */
790 /* Only do this alignment when there is also data to send - else
791 can cause NT redirector problems. */
793 if (((params_to_send % 4) != 0) && (data_to_send != 0))
794 data_alignment_offset = 4 - (params_to_send % 4);
796 /* Space is bufsize minus Netbios over TCP header minus SMB header */
797 /* The alignment_offset is to align the param bytes on an even byte
798 boundary. NT 4.0 Beta needs this to work correctly. */
800 useable_space = max_send - (smb_size
801 + 2 * 10 /* wct */
802 + alignment_offset
803 + data_alignment_offset);
805 if (useable_space < 0) {
806 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
807 "= %d!!!", useable_space));
808 exit_server_cleanly("send_trans2_replies: Not enough space");
811 while (params_to_send || data_to_send) {
812 /* Calculate whether we will totally or partially fill this packet */
814 total_sent_thistime = params_to_send + data_to_send;
816 /* We can never send more than useable_space */
818 * Note that 'useable_space' does not include the alignment offsets,
819 * but we must include the alignment offsets in the calculation of
820 * the length of the data we send over the wire, as the alignment offsets
821 * are sent here. Fix from Marc_Jacobsen@hp.com.
824 total_sent_thistime = MIN(total_sent_thistime, useable_space);
826 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
827 + data_alignment_offset);
830 * We might have SMBtrans2s in req which was transferred to
831 * the outbuf, fix that.
833 SCVAL(req->outbuf, smb_com, SMBtrans2);
835 /* Set total params and data to be sent */
836 SSVAL(req->outbuf,smb_tprcnt,paramsize);
837 SSVAL(req->outbuf,smb_tdrcnt,datasize);
839 /* Calculate how many parameters and data we can fit into
840 * this packet. Parameters get precedence
843 params_sent_thistime = MIN(params_to_send,useable_space);
844 data_sent_thistime = useable_space - params_sent_thistime;
845 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
847 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
849 /* smb_proff is the offset from the start of the SMB header to the
850 parameter bytes, however the first 4 bytes of outbuf are
851 the Netbios over TCP header. Thus use smb_base() to subtract
852 them from the calculation */
854 SSVAL(req->outbuf,smb_proff,
855 ((smb_buf(req->outbuf)+alignment_offset)
856 - smb_base(req->outbuf)));
858 if(params_sent_thistime == 0)
859 SSVAL(req->outbuf,smb_prdisp,0);
860 else
861 /* Absolute displacement of param bytes sent in this packet */
862 SSVAL(req->outbuf,smb_prdisp,pp - params);
864 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
865 if(data_sent_thistime == 0) {
866 SSVAL(req->outbuf,smb_droff,0);
867 SSVAL(req->outbuf,smb_drdisp, 0);
868 } else {
869 /* The offset of the data bytes is the offset of the
870 parameter bytes plus the number of parameters being sent this time */
871 SSVAL(req->outbuf, smb_droff,
872 ((smb_buf(req->outbuf)+alignment_offset)
873 - smb_base(req->outbuf))
874 + params_sent_thistime + data_alignment_offset);
875 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
878 /* Initialize the padding for alignment */
880 if (alignment_offset != 0) {
881 memset(smb_buf(req->outbuf), 0, alignment_offset);
884 /* Copy the param bytes into the packet */
886 if(params_sent_thistime) {
887 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
888 params_sent_thistime);
891 /* Copy in the data bytes */
892 if(data_sent_thistime) {
893 if (data_alignment_offset != 0) {
894 memset((smb_buf(req->outbuf)+alignment_offset+
895 params_sent_thistime), 0,
896 data_alignment_offset);
898 memcpy(smb_buf(req->outbuf)+alignment_offset
899 +params_sent_thistime+data_alignment_offset,
900 pd,data_sent_thistime);
903 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
904 params_sent_thistime, data_sent_thistime, useable_space));
905 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
906 params_to_send, data_to_send, paramsize, datasize));
908 if (overflow) {
909 error_packet_set((char *)req->outbuf,
910 ERRDOS,ERRbufferoverflow,
911 STATUS_BUFFER_OVERFLOW,
912 __LINE__,__FILE__);
915 /* Send the packet */
916 show_msg((char *)req->outbuf);
917 if (!srv_send_smb(smbd_server_fd(),
918 (char *)req->outbuf,
919 true, req->seqnum+1,
920 IS_CONN_ENCRYPTED(conn),
921 &req->pcd))
922 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
924 TALLOC_FREE(req->outbuf);
926 pp += params_sent_thistime;
927 pd += data_sent_thistime;
929 params_to_send -= params_sent_thistime;
930 data_to_send -= data_sent_thistime;
932 /* Sanity check */
933 if(params_to_send < 0 || data_to_send < 0) {
934 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
935 params_to_send, data_to_send));
936 return;
940 return;
943 /****************************************************************************
944 Reply to a TRANSACT2_OPEN.
945 ****************************************************************************/
947 static void call_trans2open(connection_struct *conn,
948 struct smb_request *req,
949 char **pparams, int total_params,
950 char **ppdata, int total_data,
951 unsigned int max_data_bytes)
953 struct smb_filename *smb_fname = NULL;
954 char *params = *pparams;
955 char *pdata = *ppdata;
956 int deny_mode;
957 int32 open_attr;
958 bool oplock_request;
959 #if 0
960 bool return_additional_info;
961 int16 open_sattr;
962 time_t open_time;
963 #endif
964 int open_ofun;
965 uint32 open_size;
966 char *pname;
967 char *fname = NULL;
968 SMB_OFF_T size=0;
969 int fattr=0,mtime=0;
970 SMB_INO_T inode = 0;
971 int smb_action = 0;
972 files_struct *fsp;
973 struct ea_list *ea_list = NULL;
974 uint16 flags = 0;
975 NTSTATUS status;
976 uint32 access_mask;
977 uint32 share_mode;
978 uint32 create_disposition;
979 uint32 create_options = 0;
980 TALLOC_CTX *ctx = talloc_tos();
983 * Ensure we have enough parameters to perform the operation.
986 if (total_params < 29) {
987 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
988 goto out;
991 flags = SVAL(params, 0);
992 deny_mode = SVAL(params, 2);
993 open_attr = SVAL(params,6);
994 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
995 if (oplock_request) {
996 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
999 #if 0
1000 return_additional_info = BITSETW(params,0);
1001 open_sattr = SVAL(params, 4);
1002 open_time = make_unix_date3(params+8);
1003 #endif
1004 open_ofun = SVAL(params,12);
1005 open_size = IVAL(params,14);
1006 pname = &params[28];
1008 if (IS_IPC(conn)) {
1009 reply_doserror(req, ERRSRV, ERRaccess);
1010 goto out;
1013 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1014 total_params - 28, STR_TERMINATE,
1015 &status);
1016 if (!NT_STATUS_IS_OK(status)) {
1017 reply_nterror(req, status);
1018 goto out;
1021 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1022 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1023 (unsigned int)open_ofun, open_size));
1025 status = filename_convert(ctx,
1026 conn,
1027 req->flags2 & FLAGS2_DFS_PATHNAMES,
1028 fname,
1029 &smb_fname,
1030 NULL);
1031 if (!NT_STATUS_IS_OK(status)) {
1032 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1033 reply_botherror(req,
1034 NT_STATUS_PATH_NOT_COVERED,
1035 ERRSRV, ERRbadpath);
1036 goto out;
1038 reply_nterror(req, status);
1039 goto out;
1042 if (open_ofun == 0) {
1043 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1044 goto out;
1047 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1048 open_ofun,
1049 &access_mask,
1050 &share_mode,
1051 &create_disposition,
1052 &create_options)) {
1053 reply_doserror(req, ERRDOS, ERRbadaccess);
1054 goto out;
1057 /* Any data in this call is an EA list. */
1058 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1059 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1060 goto out;
1063 if (total_data != 4) {
1064 if (total_data < 10) {
1065 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1066 goto out;
1069 if (IVAL(pdata,0) > total_data) {
1070 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1071 IVAL(pdata,0), (unsigned int)total_data));
1072 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1073 goto out;
1076 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1077 total_data - 4);
1078 if (!ea_list) {
1079 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1080 goto out;
1082 } else if (IVAL(pdata,0) != 4) {
1083 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1084 goto out;
1087 status = SMB_VFS_CREATE_FILE(
1088 conn, /* conn */
1089 req, /* req */
1090 0, /* root_dir_fid */
1091 smb_fname, /* fname */
1092 access_mask, /* access_mask */
1093 share_mode, /* share_access */
1094 create_disposition, /* create_disposition*/
1095 create_options, /* create_options */
1096 open_attr, /* file_attributes */
1097 oplock_request, /* oplock_request */
1098 open_size, /* allocation_size */
1099 NULL, /* sd */
1100 ea_list, /* ea_list */
1101 &fsp, /* result */
1102 &smb_action); /* psbuf */
1104 if (!NT_STATUS_IS_OK(status)) {
1105 if (open_was_deferred(req->mid)) {
1106 /* We have re-scheduled this call. */
1107 goto out;
1109 reply_openerror(req, status);
1110 goto out;
1113 size = get_file_size_stat(&smb_fname->st);
1114 fattr = dos_mode(conn, smb_fname);
1115 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1116 inode = smb_fname->st.st_ex_ino;
1117 if (fattr & aDIR) {
1118 close_file(req, fsp, ERROR_CLOSE);
1119 reply_doserror(req, ERRDOS,ERRnoaccess);
1120 goto out;
1123 /* Realloc the size of parameters and data we will return */
1124 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1125 if(*pparams == NULL ) {
1126 reply_nterror(req, NT_STATUS_NO_MEMORY);
1127 goto out;
1129 params = *pparams;
1131 SSVAL(params,0,fsp->fnum);
1132 SSVAL(params,2,fattr);
1133 srv_put_dos_date2(params,4, mtime);
1134 SIVAL(params,8, (uint32)size);
1135 SSVAL(params,12,deny_mode);
1136 SSVAL(params,14,0); /* open_type - file or directory. */
1137 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1139 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1140 smb_action |= EXTENDED_OPLOCK_GRANTED;
1143 SSVAL(params,18,smb_action);
1146 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1148 SIVAL(params,20,inode);
1149 SSVAL(params,24,0); /* Padding. */
1150 if (flags & 8) {
1151 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1152 SIVAL(params, 26, ea_size);
1153 } else {
1154 SIVAL(params, 26, 0);
1157 /* Send the required number of replies */
1158 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1159 out:
1160 TALLOC_FREE(smb_fname);
1163 /*********************************************************
1164 Routine to check if a given string matches exactly.
1165 as a special case a mask of "." does NOT match. That
1166 is required for correct wildcard semantics
1167 Case can be significant or not.
1168 **********************************************************/
1170 static bool exact_match(connection_struct *conn,
1171 const char *str,
1172 const char *mask)
1174 if (mask[0] == '.' && mask[1] == 0)
1175 return False;
1176 if (dptr_has_wild(conn->dirptr)) {
1177 return False;
1179 if (conn->case_sensitive)
1180 return strcmp(str,mask)==0;
1181 else
1182 return StrCaseCmp(str,mask) == 0;
1185 /****************************************************************************
1186 Return the filetype for UNIX extensions.
1187 ****************************************************************************/
1189 static uint32 unix_filetype(mode_t mode)
1191 if(S_ISREG(mode))
1192 return UNIX_TYPE_FILE;
1193 else if(S_ISDIR(mode))
1194 return UNIX_TYPE_DIR;
1195 #ifdef S_ISLNK
1196 else if(S_ISLNK(mode))
1197 return UNIX_TYPE_SYMLINK;
1198 #endif
1199 #ifdef S_ISCHR
1200 else if(S_ISCHR(mode))
1201 return UNIX_TYPE_CHARDEV;
1202 #endif
1203 #ifdef S_ISBLK
1204 else if(S_ISBLK(mode))
1205 return UNIX_TYPE_BLKDEV;
1206 #endif
1207 #ifdef S_ISFIFO
1208 else if(S_ISFIFO(mode))
1209 return UNIX_TYPE_FIFO;
1210 #endif
1211 #ifdef S_ISSOCK
1212 else if(S_ISSOCK(mode))
1213 return UNIX_TYPE_SOCKET;
1214 #endif
1216 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1217 return UNIX_TYPE_UNKNOWN;
1220 /****************************************************************************
1221 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1222 ****************************************************************************/
1224 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1226 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1227 const SMB_STRUCT_STAT *psbuf,
1228 uint32 perms,
1229 enum perm_type ptype,
1230 mode_t *ret_perms)
1232 mode_t ret = 0;
1234 if (perms == SMB_MODE_NO_CHANGE) {
1235 if (!VALID_STAT(*psbuf)) {
1236 return NT_STATUS_INVALID_PARAMETER;
1237 } else {
1238 *ret_perms = psbuf->st_ex_mode;
1239 return NT_STATUS_OK;
1243 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1244 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1245 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1246 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1247 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1248 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1249 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1250 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1251 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1252 #ifdef S_ISVTX
1253 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1254 #endif
1255 #ifdef S_ISGID
1256 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1257 #endif
1258 #ifdef S_ISUID
1259 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1260 #endif
1262 switch (ptype) {
1263 case PERM_NEW_FILE:
1264 /* Apply mode mask */
1265 ret &= lp_create_mask(SNUM(conn));
1266 /* Add in force bits */
1267 ret |= lp_force_create_mode(SNUM(conn));
1268 break;
1269 case PERM_NEW_DIR:
1270 ret &= lp_dir_mask(SNUM(conn));
1271 /* Add in force bits */
1272 ret |= lp_force_dir_mode(SNUM(conn));
1273 break;
1274 case PERM_EXISTING_FILE:
1275 /* Apply mode mask */
1276 ret &= lp_security_mask(SNUM(conn));
1277 /* Add in force bits */
1278 ret |= lp_force_security_mode(SNUM(conn));
1279 break;
1280 case PERM_EXISTING_DIR:
1281 /* Apply mode mask */
1282 ret &= lp_dir_security_mask(SNUM(conn));
1283 /* Add in force bits */
1284 ret |= lp_force_dir_security_mode(SNUM(conn));
1285 break;
1288 *ret_perms = ret;
1289 return NT_STATUS_OK;
1292 /****************************************************************************
1293 Needed to show the msdfs symlinks as directories. Modifies psbuf
1294 to be a directory if it's a msdfs link.
1295 ****************************************************************************/
1297 static bool check_msdfs_link(connection_struct *conn,
1298 const char *pathname,
1299 SMB_STRUCT_STAT *psbuf)
1301 int saved_errno = errno;
1302 if(lp_host_msdfs() &&
1303 lp_msdfs_root(SNUM(conn)) &&
1304 is_msdfs_link(conn, pathname, psbuf)) {
1306 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1307 "as a directory\n",
1308 pathname));
1309 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1310 errno = saved_errno;
1311 return true;
1313 errno = saved_errno;
1314 return false;
1318 /****************************************************************************
1319 Get a level dependent lanman2 dir entry.
1320 ****************************************************************************/
1322 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1323 connection_struct *conn,
1324 uint16 flags2,
1325 const char *path_mask,
1326 uint32 dirtype,
1327 int info_level,
1328 int requires_resume_key,
1329 bool dont_descend,
1330 bool ask_sharemode,
1331 char **ppdata,
1332 char *base_data,
1333 char *end_data,
1334 int space_remaining,
1335 bool *out_of_space,
1336 bool *got_exact_match,
1337 int *last_entry_off,
1338 struct ea_list *name_list)
1340 char *dname;
1341 bool found = False;
1342 SMB_STRUCT_STAT sbuf;
1343 const char *mask = NULL;
1344 char *pathreal = NULL;
1345 char *fname = NULL;
1346 char *p, *q, *pdata = *ppdata;
1347 uint32 reskey=0;
1348 long prev_dirpos=0;
1349 uint32 mode=0;
1350 SMB_OFF_T file_size = 0;
1351 uint64_t allocation_size = 0;
1352 uint32 len;
1353 struct timespec mdate_ts, adate_ts, create_date_ts;
1354 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1355 char *nameptr;
1356 char *last_entry_ptr;
1357 bool was_8_3;
1358 uint32 nt_extmode; /* Used for NT connections instead of mode */
1359 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1360 bool check_mangled_names = lp_manglednames(conn->params);
1361 char mangled_name[13]; /* mangled 8.3 name. */
1363 *out_of_space = False;
1364 *got_exact_match = False;
1366 ZERO_STRUCT(mdate_ts);
1367 ZERO_STRUCT(adate_ts);
1368 ZERO_STRUCT(create_date_ts);
1370 if (!conn->dirptr) {
1371 return(False);
1374 p = strrchr_m(path_mask,'/');
1375 if(p != NULL) {
1376 if(p[1] == '\0') {
1377 mask = talloc_strdup(ctx,"*.*");
1378 } else {
1379 mask = p+1;
1381 } else {
1382 mask = path_mask;
1385 while (!found) {
1386 bool got_match;
1387 bool ms_dfs_link = False;
1389 /* Needed if we run out of space */
1390 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1391 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1394 * Due to bugs in NT client redirectors we are not using
1395 * resume keys any more - set them to zero.
1396 * Check out the related comments in findfirst/findnext.
1397 * JRA.
1400 reskey = 0;
1402 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1403 (long)conn->dirptr,curr_dirpos));
1405 if (!dname) {
1406 return(False);
1410 * fname may get mangled, dname is never mangled.
1411 * Whenever we're accessing the filesystem we use
1412 * pathreal which is composed from dname.
1415 pathreal = NULL;
1416 fname = dname;
1418 /* Mangle fname if it's an illegal name. */
1419 if (mangle_must_mangle(dname,conn->params)) {
1420 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1421 TALLOC_FREE(fname);
1422 continue; /* Error - couldn't mangle. */
1424 fname = talloc_strdup(ctx, mangled_name);
1425 if (!fname) {
1426 return False;
1430 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1431 got_match = mask_match(fname, mask, conn->case_sensitive);
1434 if(!got_match && check_mangled_names &&
1435 !mangle_is_8_3(fname, False, conn->params)) {
1437 * It turns out that NT matches wildcards against
1438 * both long *and* short names. This may explain some
1439 * of the wildcard wierdness from old DOS clients
1440 * that some people have been seeing.... JRA.
1442 /* Force the mangling into 8.3. */
1443 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1444 TALLOC_FREE(fname);
1445 continue; /* Error - couldn't mangle. */
1448 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1449 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1453 if (got_match) {
1454 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1455 struct smb_filename *smb_fname = NULL;
1456 NTSTATUS status;
1458 if (dont_descend && !isdots) {
1459 TALLOC_FREE(fname);
1460 continue;
1463 if (needslash) {
1464 pathreal = NULL;
1465 pathreal = talloc_asprintf(ctx,
1466 "%s/%s",
1467 conn->dirpath,
1468 dname);
1469 } else {
1470 pathreal = talloc_asprintf(ctx,
1471 "%s%s",
1472 conn->dirpath,
1473 dname);
1476 if (!pathreal) {
1477 TALLOC_FREE(fname);
1478 return False;
1481 /* A dirent from dptr_ReadDirName isn't a stream. */
1482 status = create_synthetic_smb_fname(ctx, pathreal,
1483 NULL, &sbuf,
1484 &smb_fname);
1485 if (!NT_STATUS_IS_OK(status)) {
1486 TALLOC_FREE(fname);
1487 return false;
1490 if (INFO_LEVEL_IS_UNIX(info_level)) {
1491 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
1492 DEBUG(5,("get_lanman2_dir_entry: "
1493 "Couldn't lstat [%s] (%s)\n",
1494 smb_fname_str_dbg(smb_fname),
1495 strerror(errno)));
1496 TALLOC_FREE(smb_fname);
1497 TALLOC_FREE(pathreal);
1498 TALLOC_FREE(fname);
1499 continue;
1501 } else if (!VALID_STAT(smb_fname->st) &&
1502 SMB_VFS_STAT(conn, smb_fname) != 0) {
1503 /* Needed to show the msdfs symlinks as
1504 * directories */
1506 ms_dfs_link =
1507 check_msdfs_link(conn,
1508 smb_fname->base_name,
1509 &smb_fname->st);
1510 if (!ms_dfs_link) {
1511 DEBUG(5,("get_lanman2_dir_entry: "
1512 "Couldn't stat [%s] (%s)\n",
1513 smb_fname_str_dbg(smb_fname),
1514 strerror(errno)));
1515 TALLOC_FREE(smb_fname);
1516 TALLOC_FREE(pathreal);
1517 TALLOC_FREE(fname);
1518 continue;
1522 if (ms_dfs_link) {
1523 mode = dos_mode_msdfs(conn, smb_fname);
1524 } else {
1525 mode = dos_mode(conn, smb_fname);
1528 if (!dir_check_ftype(conn,mode,dirtype)) {
1529 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1530 TALLOC_FREE(smb_fname);
1531 TALLOC_FREE(pathreal);
1532 TALLOC_FREE(fname);
1533 continue;
1536 if (!(mode & aDIR)) {
1537 file_size = get_file_size_stat(&smb_fname->st);
1539 allocation_size =
1540 SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1542 if (ask_sharemode) {
1543 struct timespec write_time_ts;
1544 struct file_id fileid;
1546 ZERO_STRUCT(write_time_ts);
1547 fileid = vfs_file_id_from_sbuf(conn,
1548 &smb_fname->st);
1549 get_file_infos(fileid, NULL, &write_time_ts);
1550 if (!null_timespec(write_time_ts)) {
1551 update_stat_ex_mtime(&smb_fname->st,
1552 write_time_ts);
1556 mdate_ts = smb_fname->st.st_ex_mtime;
1557 adate_ts = smb_fname->st.st_ex_atime;
1558 create_date_ts = smb_fname->st.st_ex_btime;
1560 if (lp_dos_filetime_resolution(SNUM(conn))) {
1561 dos_filetime_timespec(&create_date_ts);
1562 dos_filetime_timespec(&mdate_ts);
1563 dos_filetime_timespec(&adate_ts);
1566 create_date = convert_timespec_to_time_t(create_date_ts);
1567 mdate = convert_timespec_to_time_t(mdate_ts);
1568 adate = convert_timespec_to_time_t(adate_ts);
1570 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1571 smb_fname_str_dbg(smb_fname), fname));
1573 found = True;
1575 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1576 sbuf = smb_fname->st;
1578 TALLOC_FREE(smb_fname);
1581 if (!found)
1582 TALLOC_FREE(fname);
1585 p = pdata;
1586 last_entry_ptr = p;
1588 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1590 switch (info_level) {
1591 case SMB_FIND_INFO_STANDARD:
1592 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1593 if(requires_resume_key) {
1594 SIVAL(p,0,reskey);
1595 p += 4;
1597 srv_put_dos_date2(p,0,create_date);
1598 srv_put_dos_date2(p,4,adate);
1599 srv_put_dos_date2(p,8,mdate);
1600 SIVAL(p,12,(uint32)file_size);
1601 SIVAL(p,16,(uint32)allocation_size);
1602 SSVAL(p,20,mode);
1603 p += 23;
1604 nameptr = p;
1605 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1606 p += ucs2_align(base_data, p, 0);
1608 len = srvstr_push(base_data, flags2, p,
1609 fname, PTR_DIFF(end_data, p),
1610 STR_TERMINATE);
1611 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1612 if (len > 2) {
1613 SCVAL(nameptr, -1, len - 2);
1614 } else {
1615 SCVAL(nameptr, -1, 0);
1617 } else {
1618 if (len > 1) {
1619 SCVAL(nameptr, -1, len - 1);
1620 } else {
1621 SCVAL(nameptr, -1, 0);
1624 p += len;
1625 break;
1627 case SMB_FIND_EA_SIZE:
1628 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1629 if(requires_resume_key) {
1630 SIVAL(p,0,reskey);
1631 p += 4;
1633 srv_put_dos_date2(p,0,create_date);
1634 srv_put_dos_date2(p,4,adate);
1635 srv_put_dos_date2(p,8,mdate);
1636 SIVAL(p,12,(uint32)file_size);
1637 SIVAL(p,16,(uint32)allocation_size);
1638 SSVAL(p,20,mode);
1640 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1641 SIVAL(p,22,ea_size); /* Extended attributes */
1643 p += 27;
1644 nameptr = p - 1;
1645 len = srvstr_push(base_data, flags2,
1646 p, fname, PTR_DIFF(end_data, p),
1647 STR_TERMINATE | STR_NOALIGN);
1648 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1649 if (len > 2) {
1650 len -= 2;
1651 } else {
1652 len = 0;
1654 } else {
1655 if (len > 1) {
1656 len -= 1;
1657 } else {
1658 len = 0;
1661 SCVAL(nameptr,0,len);
1662 p += len;
1663 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1664 break;
1666 case SMB_FIND_EA_LIST:
1668 struct ea_list *file_list = NULL;
1669 size_t ea_len = 0;
1671 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1672 if (!name_list) {
1673 return False;
1675 if(requires_resume_key) {
1676 SIVAL(p,0,reskey);
1677 p += 4;
1679 srv_put_dos_date2(p,0,create_date);
1680 srv_put_dos_date2(p,4,adate);
1681 srv_put_dos_date2(p,8,mdate);
1682 SIVAL(p,12,(uint32)file_size);
1683 SIVAL(p,16,(uint32)allocation_size);
1684 SSVAL(p,20,mode);
1685 p += 22; /* p now points to the EA area. */
1687 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1688 name_list = ea_list_union(name_list, file_list, &ea_len);
1690 /* We need to determine if this entry will fit in the space available. */
1691 /* Max string size is 255 bytes. */
1692 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1693 /* Move the dirptr back to prev_dirpos */
1694 dptr_SeekDir(conn->dirptr, prev_dirpos);
1695 *out_of_space = True;
1696 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1697 return False; /* Not finished - just out of space */
1700 /* Push the ea_data followed by the name. */
1701 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1702 nameptr = p;
1703 len = srvstr_push(base_data, flags2,
1704 p + 1, fname, PTR_DIFF(end_data, p+1),
1705 STR_TERMINATE | STR_NOALIGN);
1706 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1707 if (len > 2) {
1708 len -= 2;
1709 } else {
1710 len = 0;
1712 } else {
1713 if (len > 1) {
1714 len -= 1;
1715 } else {
1716 len = 0;
1719 SCVAL(nameptr,0,len);
1720 p += len + 1;
1721 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1722 break;
1725 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1726 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1727 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1728 p += 4;
1729 SIVAL(p,0,reskey); p += 4;
1730 put_long_date_timespec(p,create_date_ts); p += 8;
1731 put_long_date_timespec(p,adate_ts); p += 8;
1732 put_long_date_timespec(p,mdate_ts); p += 8;
1733 put_long_date_timespec(p,mdate_ts); p += 8;
1734 SOFF_T(p,0,file_size); p += 8;
1735 SOFF_T(p,0,allocation_size); p += 8;
1736 SIVAL(p,0,nt_extmode); p += 4;
1737 q = p; p += 4; /* q is placeholder for name length. */
1739 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1740 SIVAL(p,0,ea_size); /* Extended attributes */
1741 p += 4;
1743 /* Clear the short name buffer. This is
1744 * IMPORTANT as not doing so will trigger
1745 * a Win2k client bug. JRA.
1747 if (!was_8_3 && check_mangled_names) {
1748 if (!name_to_8_3(fname,mangled_name,True,
1749 conn->params)) {
1750 /* Error - mangle failed ! */
1751 memset(mangled_name,'\0',12);
1753 mangled_name[12] = 0;
1754 len = srvstr_push(base_data, flags2,
1755 p+2, mangled_name, 24,
1756 STR_UPPER|STR_UNICODE);
1757 if (len < 24) {
1758 memset(p + 2 + len,'\0',24 - len);
1760 SSVAL(p, 0, len);
1761 } else {
1762 memset(p,'\0',26);
1764 p += 2 + 24;
1765 len = srvstr_push(base_data, flags2, p,
1766 fname, PTR_DIFF(end_data, p),
1767 STR_TERMINATE_ASCII);
1768 SIVAL(q,0,len);
1769 p += len;
1770 SIVAL(p,0,0); /* Ensure any padding is null. */
1771 len = PTR_DIFF(p, pdata);
1772 len = (len + 3) & ~3;
1773 SIVAL(pdata,0,len);
1774 p = pdata + len;
1775 break;
1777 case SMB_FIND_FILE_DIRECTORY_INFO:
1778 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1779 p += 4;
1780 SIVAL(p,0,reskey); p += 4;
1781 put_long_date_timespec(p,create_date_ts); p += 8;
1782 put_long_date_timespec(p,adate_ts); p += 8;
1783 put_long_date_timespec(p,mdate_ts); p += 8;
1784 put_long_date_timespec(p,mdate_ts); p += 8;
1785 SOFF_T(p,0,file_size); p += 8;
1786 SOFF_T(p,0,allocation_size); p += 8;
1787 SIVAL(p,0,nt_extmode); p += 4;
1788 len = srvstr_push(base_data, flags2,
1789 p + 4, fname, PTR_DIFF(end_data, p+4),
1790 STR_TERMINATE_ASCII);
1791 SIVAL(p,0,len);
1792 p += 4 + len;
1793 SIVAL(p,0,0); /* Ensure any padding is null. */
1794 len = PTR_DIFF(p, pdata);
1795 len = (len + 3) & ~3;
1796 SIVAL(pdata,0,len);
1797 p = pdata + len;
1798 break;
1800 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1801 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1802 p += 4;
1803 SIVAL(p,0,reskey); p += 4;
1804 put_long_date_timespec(p,create_date_ts); p += 8;
1805 put_long_date_timespec(p,adate_ts); p += 8;
1806 put_long_date_timespec(p,mdate_ts); p += 8;
1807 put_long_date_timespec(p,mdate_ts); p += 8;
1808 SOFF_T(p,0,file_size); p += 8;
1809 SOFF_T(p,0,allocation_size); p += 8;
1810 SIVAL(p,0,nt_extmode); p += 4;
1811 q = p; p += 4; /* q is placeholder for name length. */
1813 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1814 SIVAL(p,0,ea_size); /* Extended attributes */
1815 p +=4;
1817 len = srvstr_push(base_data, flags2, p,
1818 fname, PTR_DIFF(end_data, p),
1819 STR_TERMINATE_ASCII);
1820 SIVAL(q, 0, len);
1821 p += len;
1823 SIVAL(p,0,0); /* Ensure any padding is null. */
1824 len = PTR_DIFF(p, pdata);
1825 len = (len + 3) & ~3;
1826 SIVAL(pdata,0,len);
1827 p = pdata + len;
1828 break;
1830 case SMB_FIND_FILE_NAMES_INFO:
1831 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1832 p += 4;
1833 SIVAL(p,0,reskey); p += 4;
1834 p += 4;
1835 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1836 acl on a dir (tridge) */
1837 len = srvstr_push(base_data, flags2, p,
1838 fname, PTR_DIFF(end_data, p),
1839 STR_TERMINATE_ASCII);
1840 SIVAL(p, -4, len);
1841 p += len;
1842 SIVAL(p,0,0); /* Ensure any padding is null. */
1843 len = PTR_DIFF(p, pdata);
1844 len = (len + 3) & ~3;
1845 SIVAL(pdata,0,len);
1846 p = pdata + len;
1847 break;
1849 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1850 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1851 p += 4;
1852 SIVAL(p,0,reskey); p += 4;
1853 put_long_date_timespec(p,create_date_ts); p += 8;
1854 put_long_date_timespec(p,adate_ts); p += 8;
1855 put_long_date_timespec(p,mdate_ts); p += 8;
1856 put_long_date_timespec(p,mdate_ts); p += 8;
1857 SOFF_T(p,0,file_size); p += 8;
1858 SOFF_T(p,0,allocation_size); p += 8;
1859 SIVAL(p,0,nt_extmode); p += 4;
1860 q = p; p += 4; /* q is placeholder for name length. */
1862 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1863 SIVAL(p,0,ea_size); /* Extended attributes */
1864 p +=4;
1866 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1867 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1868 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1869 len = srvstr_push(base_data, flags2, p,
1870 fname, PTR_DIFF(end_data, p),
1871 STR_TERMINATE_ASCII);
1872 SIVAL(q, 0, len);
1873 p += len;
1874 SIVAL(p,0,0); /* Ensure any padding is null. */
1875 len = PTR_DIFF(p, pdata);
1876 len = (len + 3) & ~3;
1877 SIVAL(pdata,0,len);
1878 p = pdata + len;
1879 break;
1881 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1882 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1883 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1884 p += 4;
1885 SIVAL(p,0,reskey); p += 4;
1886 put_long_date_timespec(p,create_date_ts); p += 8;
1887 put_long_date_timespec(p,adate_ts); p += 8;
1888 put_long_date_timespec(p,mdate_ts); p += 8;
1889 put_long_date_timespec(p,mdate_ts); p += 8;
1890 SOFF_T(p,0,file_size); p += 8;
1891 SOFF_T(p,0,allocation_size); p += 8;
1892 SIVAL(p,0,nt_extmode); p += 4;
1893 q = p; p += 4; /* q is placeholder for name length */
1895 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1896 SIVAL(p,0,ea_size); /* Extended attributes */
1897 p +=4;
1899 /* Clear the short name buffer. This is
1900 * IMPORTANT as not doing so will trigger
1901 * a Win2k client bug. JRA.
1903 if (!was_8_3 && check_mangled_names) {
1904 if (!name_to_8_3(fname,mangled_name,True,
1905 conn->params)) {
1906 /* Error - mangle failed ! */
1907 memset(mangled_name,'\0',12);
1909 mangled_name[12] = 0;
1910 len = srvstr_push(base_data, flags2,
1911 p+2, mangled_name, 24,
1912 STR_UPPER|STR_UNICODE);
1913 SSVAL(p, 0, len);
1914 if (len < 24) {
1915 memset(p + 2 + len,'\0',24 - len);
1917 SSVAL(p, 0, len);
1918 } else {
1919 memset(p,'\0',26);
1921 p += 26;
1922 SSVAL(p,0,0); p += 2; /* Reserved ? */
1923 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1924 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1925 len = srvstr_push(base_data, flags2, p,
1926 fname, PTR_DIFF(end_data, p),
1927 STR_TERMINATE_ASCII);
1928 SIVAL(q,0,len);
1929 p += len;
1930 SIVAL(p,0,0); /* Ensure any padding is null. */
1931 len = PTR_DIFF(p, pdata);
1932 len = (len + 3) & ~3;
1933 SIVAL(pdata,0,len);
1934 p = pdata + len;
1935 break;
1937 /* CIFS UNIX Extension. */
1939 case SMB_FIND_FILE_UNIX:
1940 case SMB_FIND_FILE_UNIX_INFO2:
1941 p+= 4;
1942 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1944 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1946 if (info_level == SMB_FIND_FILE_UNIX) {
1947 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1948 p = store_file_unix_basic(conn, p,
1949 NULL, &sbuf);
1950 len = srvstr_push(base_data, flags2, p,
1951 fname, PTR_DIFF(end_data, p),
1952 STR_TERMINATE);
1953 } else {
1954 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1955 p = store_file_unix_basic_info2(conn, p,
1956 NULL, &sbuf);
1957 nameptr = p;
1958 p += 4;
1959 len = srvstr_push(base_data, flags2, p, fname,
1960 PTR_DIFF(end_data, p), 0);
1961 SIVAL(nameptr, 0, len);
1964 p += len;
1965 SIVAL(p,0,0); /* Ensure any padding is null. */
1967 len = PTR_DIFF(p, pdata);
1968 len = (len + 3) & ~3;
1969 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1970 p = pdata + len;
1971 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1973 break;
1975 default:
1976 TALLOC_FREE(fname);
1977 return(False);
1980 TALLOC_FREE(fname);
1981 if (PTR_DIFF(p,pdata) > space_remaining) {
1982 /* Move the dirptr back to prev_dirpos */
1983 dptr_SeekDir(conn->dirptr, prev_dirpos);
1984 *out_of_space = True;
1985 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1986 return False; /* Not finished - just out of space */
1989 /* Setup the last entry pointer, as an offset from base_data */
1990 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1991 /* Advance the data pointer to the next slot */
1992 *ppdata = p;
1994 return(found);
1997 /****************************************************************************
1998 Reply to a TRANS2_FINDFIRST.
1999 ****************************************************************************/
2001 static void call_trans2findfirst(connection_struct *conn,
2002 struct smb_request *req,
2003 char **pparams, int total_params,
2004 char **ppdata, int total_data,
2005 unsigned int max_data_bytes)
2007 /* We must be careful here that we don't return more than the
2008 allowed number of data bytes. If this means returning fewer than
2009 maxentries then so be it. We assume that the redirector has
2010 enough room for the fixed number of parameter bytes it has
2011 requested. */
2012 struct smb_filename *smb_dname = NULL;
2013 char *params = *pparams;
2014 char *pdata = *ppdata;
2015 char *data_end;
2016 uint32 dirtype;
2017 int maxentries;
2018 uint16 findfirst_flags;
2019 bool close_after_first;
2020 bool close_if_end;
2021 bool requires_resume_key;
2022 int info_level;
2023 char *directory = NULL;
2024 char *mask = NULL;
2025 char *p;
2026 int last_entry_off=0;
2027 int dptr_num = -1;
2028 int numentries = 0;
2029 int i;
2030 bool finished = False;
2031 bool dont_descend = False;
2032 bool out_of_space = False;
2033 int space_remaining;
2034 bool mask_contains_wcard = False;
2035 struct ea_list *ea_list = NULL;
2036 NTSTATUS ntstatus = NT_STATUS_OK;
2037 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2038 TALLOC_CTX *ctx = talloc_tos();
2040 if (total_params < 13) {
2041 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2042 return;
2045 dirtype = SVAL(params,0);
2046 maxentries = SVAL(params,2);
2047 findfirst_flags = SVAL(params,4);
2048 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2049 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2050 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2051 info_level = SVAL(params,6);
2053 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2054 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2055 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2056 info_level, max_data_bytes));
2058 if (!maxentries) {
2059 /* W2K3 seems to treat zero as 1. */
2060 maxentries = 1;
2063 switch (info_level) {
2064 case SMB_FIND_INFO_STANDARD:
2065 case SMB_FIND_EA_SIZE:
2066 case SMB_FIND_EA_LIST:
2067 case SMB_FIND_FILE_DIRECTORY_INFO:
2068 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2069 case SMB_FIND_FILE_NAMES_INFO:
2070 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2071 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2072 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2073 break;
2074 case SMB_FIND_FILE_UNIX:
2075 case SMB_FIND_FILE_UNIX_INFO2:
2076 /* Always use filesystem for UNIX mtime query. */
2077 ask_sharemode = false;
2078 if (!lp_unix_extensions()) {
2079 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2080 return;
2082 break;
2083 default:
2084 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2085 return;
2088 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2089 params+12, total_params - 12,
2090 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2091 if (!NT_STATUS_IS_OK(ntstatus)) {
2092 reply_nterror(req, ntstatus);
2093 return;
2096 ntstatus = resolve_dfspath_wcard(ctx, conn,
2097 req->flags2 & FLAGS2_DFS_PATHNAMES,
2098 directory,
2099 &directory,
2100 &mask_contains_wcard);
2101 if (!NT_STATUS_IS_OK(ntstatus)) {
2102 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2103 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2104 ERRSRV, ERRbadpath);
2105 return;
2107 reply_nterror(req, ntstatus);
2108 return;
2111 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
2112 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
2113 if (!NT_STATUS_IS_OK(ntstatus)) {
2114 reply_nterror(req, ntstatus);
2115 return;
2118 mask = smb_dname->original_lcomp;
2120 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
2121 TALLOC_FREE(smb_dname);
2122 if (!NT_STATUS_IS_OK(ntstatus)) {
2123 reply_nterror(req, ntstatus);
2124 return;
2127 ntstatus = check_name(conn, directory);
2128 if (!NT_STATUS_IS_OK(ntstatus)) {
2129 reply_nterror(req, ntstatus);
2130 return;
2133 p = strrchr_m(directory,'/');
2134 if(p == NULL) {
2135 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2136 if((directory[0] == '.') && (directory[1] == '\0')) {
2137 mask = talloc_strdup(ctx,"*");
2138 if (!mask) {
2139 reply_nterror(req, NT_STATUS_NO_MEMORY);
2140 return;
2142 mask_contains_wcard = True;
2144 directory = talloc_strdup(talloc_tos(), "./");
2145 if (!directory) {
2146 reply_nterror(req, NT_STATUS_NO_MEMORY);
2147 return;
2149 } else {
2150 *p = 0;
2153 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2155 if (info_level == SMB_FIND_EA_LIST) {
2156 uint32 ea_size;
2158 if (total_data < 4) {
2159 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2160 return;
2163 ea_size = IVAL(pdata,0);
2164 if (ea_size != total_data) {
2165 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2166 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2167 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2168 return;
2171 if (!lp_ea_support(SNUM(conn))) {
2172 reply_doserror(req, ERRDOS, ERReasnotsupported);
2173 return;
2176 /* Pull out the list of names. */
2177 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2178 if (!ea_list) {
2179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2180 return;
2184 *ppdata = (char *)SMB_REALLOC(
2185 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2186 if(*ppdata == NULL ) {
2187 reply_nterror(req, NT_STATUS_NO_MEMORY);
2188 return;
2190 pdata = *ppdata;
2191 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2193 /* Realloc the params space */
2194 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2195 if (*pparams == NULL) {
2196 reply_nterror(req, NT_STATUS_NO_MEMORY);
2197 return;
2199 params = *pparams;
2201 /* Save the wildcard match and attribs we are using on this directory -
2202 needed as lanman2 assumes these are being saved between calls */
2204 ntstatus = dptr_create(conn,
2205 directory,
2206 False,
2207 True,
2208 req->smbpid,
2209 mask,
2210 mask_contains_wcard,
2211 dirtype,
2212 &conn->dirptr);
2214 if (!NT_STATUS_IS_OK(ntstatus)) {
2215 reply_nterror(req, ntstatus);
2216 return;
2219 dptr_num = dptr_dnum(conn->dirptr);
2220 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2222 /* Initialize per TRANS2_FIND_FIRST operation data */
2223 dptr_init_search_op(conn->dirptr);
2225 /* We don't need to check for VOL here as this is returned by
2226 a different TRANS2 call. */
2228 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2229 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2230 dont_descend = True;
2232 p = pdata;
2233 space_remaining = max_data_bytes;
2234 out_of_space = False;
2236 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2237 bool got_exact_match = False;
2239 /* this is a heuristic to avoid seeking the dirptr except when
2240 absolutely necessary. It allows for a filename of about 40 chars */
2241 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2242 out_of_space = True;
2243 finished = False;
2244 } else {
2245 finished = !get_lanman2_dir_entry(ctx,
2246 conn,
2247 req->flags2,
2248 mask,dirtype,info_level,
2249 requires_resume_key,dont_descend,
2250 ask_sharemode,
2251 &p,pdata,data_end,
2252 space_remaining, &out_of_space,
2253 &got_exact_match,
2254 &last_entry_off, ea_list);
2257 if (finished && out_of_space)
2258 finished = False;
2260 if (!finished && !out_of_space)
2261 numentries++;
2264 * As an optimisation if we know we aren't looking
2265 * for a wildcard name (ie. the name matches the wildcard exactly)
2266 * then we can finish on any (first) match.
2267 * This speeds up large directory searches. JRA.
2270 if(got_exact_match)
2271 finished = True;
2273 /* Ensure space_remaining never goes -ve. */
2274 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2275 space_remaining = 0;
2276 out_of_space = true;
2277 } else {
2278 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2282 /* Check if we can close the dirptr */
2283 if(close_after_first || (finished && close_if_end)) {
2284 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2285 dptr_close(&dptr_num);
2289 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2290 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2291 * the protocol level is less than NT1. Tested with smbclient. JRA.
2292 * This should fix the OS/2 client bug #2335.
2295 if(numentries == 0) {
2296 dptr_close(&dptr_num);
2297 if (Protocol < PROTOCOL_NT1) {
2298 reply_doserror(req, ERRDOS, ERRnofiles);
2299 return;
2300 } else {
2301 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2302 ERRDOS, ERRbadfile);
2303 return;
2307 /* At this point pdata points to numentries directory entries. */
2309 /* Set up the return parameter block */
2310 SSVAL(params,0,dptr_num);
2311 SSVAL(params,2,numentries);
2312 SSVAL(params,4,finished);
2313 SSVAL(params,6,0); /* Never an EA error */
2314 SSVAL(params,8,last_entry_off);
2316 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2317 max_data_bytes);
2319 if ((! *directory) && dptr_path(dptr_num)) {
2320 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2321 if (!directory) {
2322 reply_nterror(req, NT_STATUS_NO_MEMORY);
2326 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2327 smb_fn_name(req->cmd),
2328 mask, directory, dirtype, numentries ) );
2331 * Force a name mangle here to ensure that the
2332 * mask as an 8.3 name is top of the mangled cache.
2333 * The reasons for this are subtle. Don't remove
2334 * this code unless you know what you are doing
2335 * (see PR#13758). JRA.
2338 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2339 char mangled_name[13];
2340 name_to_8_3(mask, mangled_name, True, conn->params);
2343 return;
2346 /****************************************************************************
2347 Reply to a TRANS2_FINDNEXT.
2348 ****************************************************************************/
2350 static void call_trans2findnext(connection_struct *conn,
2351 struct smb_request *req,
2352 char **pparams, int total_params,
2353 char **ppdata, int total_data,
2354 unsigned int max_data_bytes)
2356 /* We must be careful here that we don't return more than the
2357 allowed number of data bytes. If this means returning fewer than
2358 maxentries then so be it. We assume that the redirector has
2359 enough room for the fixed number of parameter bytes it has
2360 requested. */
2361 char *params = *pparams;
2362 char *pdata = *ppdata;
2363 char *data_end;
2364 int dptr_num;
2365 int maxentries;
2366 uint16 info_level;
2367 uint32 resume_key;
2368 uint16 findnext_flags;
2369 bool close_after_request;
2370 bool close_if_end;
2371 bool requires_resume_key;
2372 bool continue_bit;
2373 bool mask_contains_wcard = False;
2374 char *resume_name = NULL;
2375 const char *mask = NULL;
2376 const char *directory = NULL;
2377 char *p = NULL;
2378 uint16 dirtype;
2379 int numentries = 0;
2380 int i, last_entry_off=0;
2381 bool finished = False;
2382 bool dont_descend = False;
2383 bool out_of_space = False;
2384 int space_remaining;
2385 struct ea_list *ea_list = NULL;
2386 NTSTATUS ntstatus = NT_STATUS_OK;
2387 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2388 TALLOC_CTX *ctx = talloc_tos();
2390 if (total_params < 13) {
2391 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2392 return;
2395 dptr_num = SVAL(params,0);
2396 maxentries = SVAL(params,2);
2397 info_level = SVAL(params,4);
2398 resume_key = IVAL(params,6);
2399 findnext_flags = SVAL(params,10);
2400 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2401 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2402 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2403 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2405 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2406 params+12,
2407 total_params - 12, STR_TERMINATE, &ntstatus,
2408 &mask_contains_wcard);
2409 if (!NT_STATUS_IS_OK(ntstatus)) {
2410 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2411 complain (it thinks we're asking for the directory above the shared
2412 path or an invalid name). Catch this as the resume name is only compared, never used in
2413 a file access. JRA. */
2414 srvstr_pull_talloc(ctx, params, req->flags2,
2415 &resume_name, params+12,
2416 total_params - 12,
2417 STR_TERMINATE);
2419 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2420 reply_nterror(req, ntstatus);
2421 return;
2425 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2426 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2427 resume_key = %d resume name = %s continue=%d level = %d\n",
2428 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2429 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2431 if (!maxentries) {
2432 /* W2K3 seems to treat zero as 1. */
2433 maxentries = 1;
2436 switch (info_level) {
2437 case SMB_FIND_INFO_STANDARD:
2438 case SMB_FIND_EA_SIZE:
2439 case SMB_FIND_EA_LIST:
2440 case SMB_FIND_FILE_DIRECTORY_INFO:
2441 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2442 case SMB_FIND_FILE_NAMES_INFO:
2443 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2444 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2445 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2446 break;
2447 case SMB_FIND_FILE_UNIX:
2448 case SMB_FIND_FILE_UNIX_INFO2:
2449 /* Always use filesystem for UNIX mtime query. */
2450 ask_sharemode = false;
2451 if (!lp_unix_extensions()) {
2452 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2453 return;
2455 break;
2456 default:
2457 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2458 return;
2461 if (info_level == SMB_FIND_EA_LIST) {
2462 uint32 ea_size;
2464 if (total_data < 4) {
2465 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2466 return;
2469 ea_size = IVAL(pdata,0);
2470 if (ea_size != total_data) {
2471 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2472 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2473 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2474 return;
2477 if (!lp_ea_support(SNUM(conn))) {
2478 reply_doserror(req, ERRDOS, ERReasnotsupported);
2479 return;
2482 /* Pull out the list of names. */
2483 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2484 if (!ea_list) {
2485 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2486 return;
2490 *ppdata = (char *)SMB_REALLOC(
2491 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2492 if(*ppdata == NULL) {
2493 reply_nterror(req, NT_STATUS_NO_MEMORY);
2494 return;
2497 pdata = *ppdata;
2498 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2500 /* Realloc the params space */
2501 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2502 if(*pparams == NULL ) {
2503 reply_nterror(req, NT_STATUS_NO_MEMORY);
2504 return;
2507 params = *pparams;
2509 /* Check that the dptr is valid */
2510 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2511 reply_doserror(req, ERRDOS, ERRnofiles);
2512 return;
2515 string_set(&conn->dirpath,dptr_path(dptr_num));
2517 /* Get the wildcard mask from the dptr */
2518 if((p = dptr_wcard(dptr_num))== NULL) {
2519 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2520 reply_doserror(req, ERRDOS, ERRnofiles);
2521 return;
2524 mask = p;
2525 directory = conn->dirpath;
2527 /* Get the attr mask from the dptr */
2528 dirtype = dptr_attr(dptr_num);
2530 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2531 dptr_num, mask, dirtype,
2532 (long)conn->dirptr,
2533 dptr_TellDir(conn->dirptr)));
2535 /* Initialize per TRANS2_FIND_NEXT operation data */
2536 dptr_init_search_op(conn->dirptr);
2538 /* We don't need to check for VOL here as this is returned by
2539 a different TRANS2 call. */
2541 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2542 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2543 dont_descend = True;
2545 p = pdata;
2546 space_remaining = max_data_bytes;
2547 out_of_space = False;
2550 * Seek to the correct position. We no longer use the resume key but
2551 * depend on the last file name instead.
2554 if(*resume_name && !continue_bit) {
2555 SMB_STRUCT_STAT st;
2557 long current_pos = 0;
2559 * Remember, name_to_8_3 is called by
2560 * get_lanman2_dir_entry(), so the resume name
2561 * could be mangled. Ensure we check the unmangled name.
2564 if (mangle_is_mangled(resume_name, conn->params)) {
2565 char *new_resume_name = NULL;
2566 mangle_lookup_name_from_8_3(ctx,
2567 resume_name,
2568 &new_resume_name,
2569 conn->params);
2570 if (new_resume_name) {
2571 resume_name = new_resume_name;
2576 * Fix for NT redirector problem triggered by resume key indexes
2577 * changing between directory scans. We now return a resume key of 0
2578 * and instead look for the filename to continue from (also given
2579 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2580 * findfirst/findnext (as is usual) then the directory pointer
2581 * should already be at the correct place.
2584 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2585 } /* end if resume_name && !continue_bit */
2587 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2588 bool got_exact_match = False;
2590 /* this is a heuristic to avoid seeking the dirptr except when
2591 absolutely necessary. It allows for a filename of about 40 chars */
2592 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2593 out_of_space = True;
2594 finished = False;
2595 } else {
2596 finished = !get_lanman2_dir_entry(ctx,
2597 conn,
2598 req->flags2,
2599 mask,dirtype,info_level,
2600 requires_resume_key,dont_descend,
2601 ask_sharemode,
2602 &p,pdata,data_end,
2603 space_remaining, &out_of_space,
2604 &got_exact_match,
2605 &last_entry_off, ea_list);
2608 if (finished && out_of_space)
2609 finished = False;
2611 if (!finished && !out_of_space)
2612 numentries++;
2615 * As an optimisation if we know we aren't looking
2616 * for a wildcard name (ie. the name matches the wildcard exactly)
2617 * then we can finish on any (first) match.
2618 * This speeds up large directory searches. JRA.
2621 if(got_exact_match)
2622 finished = True;
2624 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2627 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2628 smb_fn_name(req->cmd),
2629 mask, directory, dirtype, numentries ) );
2631 /* Check if we can close the dirptr */
2632 if(close_after_request || (finished && close_if_end)) {
2633 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2634 dptr_close(&dptr_num); /* This frees up the saved mask */
2637 /* Set up the return parameter block */
2638 SSVAL(params,0,numentries);
2639 SSVAL(params,2,finished);
2640 SSVAL(params,4,0); /* Never an EA error */
2641 SSVAL(params,6,last_entry_off);
2643 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2644 max_data_bytes);
2646 return;
2649 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2651 E_md4hash(lp_servicename(SNUM(conn)),objid);
2652 return objid;
2655 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2657 SMB_ASSERT(extended_info != NULL);
2659 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2660 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2661 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2662 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2663 #ifdef SAMBA_VERSION_REVISION
2664 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2665 #endif
2666 extended_info->samba_subversion = 0;
2667 #ifdef SAMBA_VERSION_RC_RELEASE
2668 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2669 #else
2670 #ifdef SAMBA_VERSION_PRE_RELEASE
2671 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2672 #endif
2673 #endif
2674 #ifdef SAMBA_VERSION_VENDOR_PATCH
2675 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2676 #endif
2677 extended_info->samba_gitcommitdate = 0;
2678 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2679 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2680 #endif
2682 memset(extended_info->samba_version_string, 0,
2683 sizeof(extended_info->samba_version_string));
2685 snprintf (extended_info->samba_version_string,
2686 sizeof(extended_info->samba_version_string),
2687 "%s", samba_version_string());
2690 static NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2691 TALLOC_CTX *mem_ctx,
2692 uint16_t info_level,
2693 SMB_STRUCT_STAT st,
2694 uint16_t flags2,
2695 unsigned int max_data_bytes,
2696 char **ppdata,
2697 int *ret_data_len)
2699 char *pdata, *end_data;
2700 int data_len = 0, len;
2701 const char *vname = volume_label(SNUM(conn));
2702 int snum = SNUM(conn);
2703 char *fstype = lp_fstype(SNUM(conn));
2704 uint32 additional_flags = 0;
2706 if (IS_IPC(conn)) {
2707 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2708 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2709 "info level (0x%x) on IPC$.\n",
2710 (unsigned int)info_level));
2711 return NT_STATUS_ACCESS_DENIED;
2715 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2717 *ppdata = (char *)SMB_REALLOC(
2718 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2719 if (*ppdata == NULL) {
2720 return NT_STATUS_NO_MEMORY;
2723 pdata = *ppdata;
2724 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2725 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2727 switch (info_level) {
2728 case SMB_INFO_ALLOCATION:
2730 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2731 data_len = 18;
2732 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2733 return map_nt_error_from_unix(errno);
2736 block_size = lp_block_size(snum);
2737 if (bsize < block_size) {
2738 uint64_t factor = block_size/bsize;
2739 bsize = block_size;
2740 dsize /= factor;
2741 dfree /= factor;
2743 if (bsize > block_size) {
2744 uint64_t factor = bsize/block_size;
2745 bsize = block_size;
2746 dsize *= factor;
2747 dfree *= factor;
2749 bytes_per_sector = 512;
2750 sectors_per_unit = bsize/bytes_per_sector;
2752 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2753 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2754 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2756 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2757 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2758 SIVAL(pdata,l1_cUnit,dsize);
2759 SIVAL(pdata,l1_cUnitAvail,dfree);
2760 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2761 break;
2764 case SMB_INFO_VOLUME:
2765 /* Return volume name */
2767 * Add volume serial number - hash of a combination of
2768 * the called hostname and the service name.
2770 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2772 * Win2k3 and previous mess this up by sending a name length
2773 * one byte short. I believe only older clients (OS/2 Win9x) use
2774 * this call so try fixing this by adding a terminating null to
2775 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2777 len = srvstr_push(
2778 pdata, flags2,
2779 pdata+l2_vol_szVolLabel, vname,
2780 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2781 STR_NOALIGN|STR_TERMINATE);
2782 SCVAL(pdata,l2_vol_cch,len);
2783 data_len = l2_vol_szVolLabel + len;
2784 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2785 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2786 len, vname));
2787 break;
2789 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2790 case SMB_FS_ATTRIBUTE_INFORMATION:
2792 additional_flags = 0;
2793 #if defined(HAVE_SYS_QUOTAS)
2794 additional_flags |= FILE_VOLUME_QUOTAS;
2795 #endif
2797 if(lp_nt_acl_support(SNUM(conn))) {
2798 additional_flags |= FILE_PERSISTENT_ACLS;
2801 /* Capabilities are filled in at connection time through STATVFS call */
2802 additional_flags |= conn->fs_capabilities;
2804 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2805 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2806 additional_flags); /* FS ATTRIBUTES */
2808 SIVAL(pdata,4,255); /* Max filename component length */
2809 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2810 and will think we can't do long filenames */
2811 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2812 PTR_DIFF(end_data, pdata+12),
2813 STR_UNICODE);
2814 SIVAL(pdata,8,len);
2815 data_len = 12 + len;
2816 break;
2818 case SMB_QUERY_FS_LABEL_INFO:
2819 case SMB_FS_LABEL_INFORMATION:
2820 len = srvstr_push(pdata, flags2, pdata+4, vname,
2821 PTR_DIFF(end_data, pdata+4), 0);
2822 data_len = 4 + len;
2823 SIVAL(pdata,0,len);
2824 break;
2826 case SMB_QUERY_FS_VOLUME_INFO:
2827 case SMB_FS_VOLUME_INFORMATION:
2830 * Add volume serial number - hash of a combination of
2831 * the called hostname and the service name.
2833 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2834 (str_checksum(get_local_machine_name())<<16));
2836 /* Max label len is 32 characters. */
2837 len = srvstr_push(pdata, flags2, pdata+18, vname,
2838 PTR_DIFF(end_data, pdata+18),
2839 STR_UNICODE);
2840 SIVAL(pdata,12,len);
2841 data_len = 18+len;
2843 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2844 (int)strlen(vname),vname, lp_servicename(snum)));
2845 break;
2847 case SMB_QUERY_FS_SIZE_INFO:
2848 case SMB_FS_SIZE_INFORMATION:
2850 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2851 data_len = 24;
2852 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2853 return map_nt_error_from_unix(errno);
2855 block_size = lp_block_size(snum);
2856 if (bsize < block_size) {
2857 uint64_t factor = block_size/bsize;
2858 bsize = block_size;
2859 dsize /= factor;
2860 dfree /= factor;
2862 if (bsize > block_size) {
2863 uint64_t factor = bsize/block_size;
2864 bsize = block_size;
2865 dsize *= factor;
2866 dfree *= factor;
2868 bytes_per_sector = 512;
2869 sectors_per_unit = bsize/bytes_per_sector;
2870 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2871 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2872 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2873 SBIG_UINT(pdata,0,dsize);
2874 SBIG_UINT(pdata,8,dfree);
2875 SIVAL(pdata,16,sectors_per_unit);
2876 SIVAL(pdata,20,bytes_per_sector);
2877 break;
2880 case SMB_FS_FULL_SIZE_INFORMATION:
2882 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2883 data_len = 32;
2884 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2885 return map_nt_error_from_unix(errno);
2887 block_size = lp_block_size(snum);
2888 if (bsize < block_size) {
2889 uint64_t factor = block_size/bsize;
2890 bsize = block_size;
2891 dsize /= factor;
2892 dfree /= factor;
2894 if (bsize > block_size) {
2895 uint64_t factor = bsize/block_size;
2896 bsize = block_size;
2897 dsize *= factor;
2898 dfree *= factor;
2900 bytes_per_sector = 512;
2901 sectors_per_unit = bsize/bytes_per_sector;
2902 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2903 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2904 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2905 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2906 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2907 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2908 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2909 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2910 break;
2913 case SMB_QUERY_FS_DEVICE_INFO:
2914 case SMB_FS_DEVICE_INFORMATION:
2915 data_len = 8;
2916 SIVAL(pdata,0,0); /* dev type */
2917 SIVAL(pdata,4,0); /* characteristics */
2918 break;
2920 #ifdef HAVE_SYS_QUOTAS
2921 case SMB_FS_QUOTA_INFORMATION:
2923 * what we have to send --metze:
2925 * Unknown1: 24 NULL bytes
2926 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2927 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2928 * Quota Flags: 2 byte :
2929 * Unknown3: 6 NULL bytes
2931 * 48 bytes total
2933 * details for Quota Flags:
2935 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2936 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2937 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2938 * 0x0001 Enable Quotas: enable quota for this fs
2942 /* we need to fake up a fsp here,
2943 * because its not send in this call
2945 files_struct fsp;
2946 SMB_NTQUOTA_STRUCT quotas;
2948 ZERO_STRUCT(fsp);
2949 ZERO_STRUCT(quotas);
2951 fsp.conn = conn;
2952 fsp.fnum = -1;
2954 /* access check */
2955 if (conn->server_info->utok.uid != 0) {
2956 DEBUG(0,("set_user_quota: access_denied "
2957 "service [%s] user [%s]\n",
2958 lp_servicename(SNUM(conn)),
2959 conn->server_info->unix_name));
2960 return NT_STATUS_DOS(ERRDOS, ERRnoaccess);
2963 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2964 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2965 return NT_STATUS_DOS(ERRSRV, ERRerror);
2968 data_len = 48;
2970 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2971 lp_servicename(SNUM(conn))));
2973 /* Unknown1 24 NULL bytes*/
2974 SBIG_UINT(pdata,0,(uint64_t)0);
2975 SBIG_UINT(pdata,8,(uint64_t)0);
2976 SBIG_UINT(pdata,16,(uint64_t)0);
2978 /* Default Soft Quota 8 bytes */
2979 SBIG_UINT(pdata,24,quotas.softlim);
2981 /* Default Hard Quota 8 bytes */
2982 SBIG_UINT(pdata,32,quotas.hardlim);
2984 /* Quota flag 2 bytes */
2985 SSVAL(pdata,40,quotas.qflags);
2987 /* Unknown3 6 NULL bytes */
2988 SSVAL(pdata,42,0);
2989 SIVAL(pdata,44,0);
2991 break;
2993 #endif /* HAVE_SYS_QUOTAS */
2994 case SMB_FS_OBJECTID_INFORMATION:
2996 unsigned char objid[16];
2997 struct smb_extended_info extended_info;
2998 memcpy(pdata,create_volume_objectid(conn, objid),16);
2999 samba_extended_info_version (&extended_info);
3000 SIVAL(pdata,16,extended_info.samba_magic);
3001 SIVAL(pdata,20,extended_info.samba_version);
3002 SIVAL(pdata,24,extended_info.samba_subversion);
3003 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3004 memcpy(pdata+36,extended_info.samba_version_string,28);
3005 data_len = 64;
3006 break;
3010 * Query the version and capabilities of the CIFS UNIX extensions
3011 * in use.
3014 case SMB_QUERY_CIFS_UNIX_INFO:
3016 bool large_write = lp_min_receive_file_size() &&
3017 !srv_is_signing_active(smbd_server_conn);
3018 bool large_read = !srv_is_signing_active(smbd_server_conn);
3019 int encrypt_caps = 0;
3021 if (!lp_unix_extensions()) {
3022 return NT_STATUS_INVALID_LEVEL;
3025 switch (conn->encrypt_level) {
3026 case 0:
3027 encrypt_caps = 0;
3028 break;
3029 case 1:
3030 case Auto:
3031 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3032 break;
3033 case Required:
3034 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3035 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3036 large_write = false;
3037 large_read = false;
3038 break;
3041 data_len = 12;
3042 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3043 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3045 /* We have POSIX ACLs, pathname, encryption,
3046 * large read/write, and locking capability. */
3048 SBIG_UINT(pdata,4,((uint64_t)(
3049 CIFS_UNIX_POSIX_ACLS_CAP|
3050 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3051 CIFS_UNIX_FCNTL_LOCKS_CAP|
3052 CIFS_UNIX_EXTATTR_CAP|
3053 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3054 encrypt_caps|
3055 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3056 (large_write ?
3057 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3058 break;
3061 case SMB_QUERY_POSIX_FS_INFO:
3063 int rc;
3064 vfs_statvfs_struct svfs;
3066 if (!lp_unix_extensions()) {
3067 return NT_STATUS_INVALID_LEVEL;
3070 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3072 if (!rc) {
3073 data_len = 56;
3074 SIVAL(pdata,0,svfs.OptimalTransferSize);
3075 SIVAL(pdata,4,svfs.BlockSize);
3076 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3077 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3078 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3079 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3080 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3081 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3082 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3083 #ifdef EOPNOTSUPP
3084 } else if (rc == EOPNOTSUPP) {
3085 return NT_STATUS_INVALID_LEVEL;
3086 #endif /* EOPNOTSUPP */
3087 } else {
3088 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3089 return NT_STATUS_DOS(ERRSRV, ERRerror);
3091 break;
3094 case SMB_QUERY_POSIX_WHOAMI:
3096 uint32_t flags = 0;
3097 uint32_t sid_bytes;
3098 int i;
3100 if (!lp_unix_extensions()) {
3101 return NT_STATUS_INVALID_LEVEL;
3104 if (max_data_bytes < 40) {
3105 return NT_STATUS_BUFFER_TOO_SMALL;
3108 /* We ARE guest if global_sid_Builtin_Guests is
3109 * in our list of SIDs.
3111 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3112 conn->server_info->ptok)) {
3113 flags |= SMB_WHOAMI_GUEST;
3116 /* We are NOT guest if global_sid_Authenticated_Users
3117 * is in our list of SIDs.
3119 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3120 conn->server_info->ptok)) {
3121 flags &= ~SMB_WHOAMI_GUEST;
3124 /* NOTE: 8 bytes for UID/GID, irrespective of native
3125 * platform size. This matches
3126 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3128 data_len = 4 /* flags */
3129 + 4 /* flag mask */
3130 + 8 /* uid */
3131 + 8 /* gid */
3132 + 4 /* ngroups */
3133 + 4 /* num_sids */
3134 + 4 /* SID bytes */
3135 + 4 /* pad/reserved */
3136 + (conn->server_info->utok.ngroups * 8)
3137 /* groups list */
3138 + (conn->server_info->ptok->num_sids *
3139 SID_MAX_SIZE)
3140 /* SID list */;
3142 SIVAL(pdata, 0, flags);
3143 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3144 SBIG_UINT(pdata, 8,
3145 (uint64_t)conn->server_info->utok.uid);
3146 SBIG_UINT(pdata, 16,
3147 (uint64_t)conn->server_info->utok.gid);
3150 if (data_len >= max_data_bytes) {
3151 /* Potential overflow, skip the GIDs and SIDs. */
3153 SIVAL(pdata, 24, 0); /* num_groups */
3154 SIVAL(pdata, 28, 0); /* num_sids */
3155 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3156 SIVAL(pdata, 36, 0); /* reserved */
3158 data_len = 40;
3159 break;
3162 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3163 SIVAL(pdata, 28, conn->server_info->num_sids);
3165 /* We walk the SID list twice, but this call is fairly
3166 * infrequent, and I don't expect that it's performance
3167 * sensitive -- jpeach
3169 for (i = 0, sid_bytes = 0;
3170 i < conn->server_info->ptok->num_sids; ++i) {
3171 sid_bytes += ndr_size_dom_sid(
3172 &conn->server_info->ptok->user_sids[i],
3173 NULL,
3177 /* SID list byte count */
3178 SIVAL(pdata, 32, sid_bytes);
3180 /* 4 bytes pad/reserved - must be zero */
3181 SIVAL(pdata, 36, 0);
3182 data_len = 40;
3184 /* GID list */
3185 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3186 SBIG_UINT(pdata, data_len,
3187 (uint64_t)conn->server_info->utok.groups[i]);
3188 data_len += 8;
3191 /* SID list */
3192 for (i = 0;
3193 i < conn->server_info->ptok->num_sids; ++i) {
3194 int sid_len = ndr_size_dom_sid(
3195 &conn->server_info->ptok->user_sids[i],
3196 NULL,
3199 sid_linearize(pdata + data_len, sid_len,
3200 &conn->server_info->ptok->user_sids[i]);
3201 data_len += sid_len;
3204 break;
3207 case SMB_MAC_QUERY_FS_INFO:
3209 * Thursby MAC extension... ONLY on NTFS filesystems
3210 * once we do streams then we don't need this
3212 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3213 data_len = 88;
3214 SIVAL(pdata,84,0x100); /* Don't support mac... */
3215 break;
3217 /* drop through */
3218 default:
3219 return NT_STATUS_INVALID_LEVEL;
3222 *ret_data_len = data_len;
3223 return NT_STATUS_OK;
3226 /****************************************************************************
3227 Reply to a TRANS2_QFSINFO (query filesystem info).
3228 ****************************************************************************/
3230 static void call_trans2qfsinfo(connection_struct *conn,
3231 struct smb_request *req,
3232 char **pparams, int total_params,
3233 char **ppdata, int total_data,
3234 unsigned int max_data_bytes)
3236 char *params = *pparams;
3237 uint16_t info_level;
3238 int data_len = 0;
3239 SMB_STRUCT_STAT st;
3240 NTSTATUS status;
3242 if (total_params < 2) {
3243 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3244 return;
3247 info_level = SVAL(params,0);
3249 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3250 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3251 DEBUG(0,("call_trans2qfsinfo: encryption required "
3252 "and info level 0x%x sent.\n",
3253 (unsigned int)info_level));
3254 exit_server_cleanly("encryption required "
3255 "on connection");
3256 return;
3260 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3262 if(vfs_stat_smb_fname(conn,".",&st)!=0) {
3263 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
3264 reply_doserror(req, ERRSRV, ERRinvdevice);
3265 return;
3268 status = smbd_do_qfsinfo(conn, req,
3269 info_level, st,
3270 req->flags2,
3271 max_data_bytes,
3272 ppdata, &data_len);
3273 if (!NT_STATUS_IS_OK(status)) {
3274 reply_nterror(req, status);
3275 return;
3278 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3279 max_data_bytes);
3281 DEBUG( 4, ( "%s info_level = %d\n",
3282 smb_fn_name(req->cmd), info_level) );
3284 return;
3287 /****************************************************************************
3288 Reply to a TRANS2_SETFSINFO (set filesystem info).
3289 ****************************************************************************/
3291 static void call_trans2setfsinfo(connection_struct *conn,
3292 struct smb_request *req,
3293 char **pparams, int total_params,
3294 char **ppdata, int total_data,
3295 unsigned int max_data_bytes)
3297 char *pdata = *ppdata;
3298 char *params = *pparams;
3299 uint16 info_level;
3301 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3303 /* */
3304 if (total_params < 4) {
3305 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3306 total_params));
3307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3308 return;
3311 info_level = SVAL(params,2);
3313 if (IS_IPC(conn)) {
3314 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3315 info_level != SMB_SET_CIFS_UNIX_INFO) {
3316 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3317 "info level (0x%x) on IPC$.\n",
3318 (unsigned int)info_level));
3319 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3320 return;
3324 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3325 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3326 DEBUG(0,("call_trans2setfsinfo: encryption required "
3327 "and info level 0x%x sent.\n",
3328 (unsigned int)info_level));
3329 exit_server_cleanly("encryption required "
3330 "on connection");
3331 return;
3335 switch(info_level) {
3336 case SMB_SET_CIFS_UNIX_INFO:
3338 uint16 client_unix_major;
3339 uint16 client_unix_minor;
3340 uint32 client_unix_cap_low;
3341 uint32 client_unix_cap_high;
3343 if (!lp_unix_extensions()) {
3344 reply_nterror(req,
3345 NT_STATUS_INVALID_LEVEL);
3346 return;
3349 /* There should be 12 bytes of capabilities set. */
3350 if (total_data < 8) {
3351 reply_nterror(
3352 req,
3353 NT_STATUS_INVALID_PARAMETER);
3354 return;
3356 client_unix_major = SVAL(pdata,0);
3357 client_unix_minor = SVAL(pdata,2);
3358 client_unix_cap_low = IVAL(pdata,4);
3359 client_unix_cap_high = IVAL(pdata,8);
3360 /* Just print these values for now. */
3361 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3362 cap_low = 0x%x, cap_high = 0x%x\n",
3363 (unsigned int)client_unix_major,
3364 (unsigned int)client_unix_minor,
3365 (unsigned int)client_unix_cap_low,
3366 (unsigned int)client_unix_cap_high ));
3368 /* Here is where we must switch to posix pathname processing... */
3369 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3370 lp_set_posix_pathnames();
3371 mangle_change_to_posix();
3374 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3375 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3376 /* Client that knows how to do posix locks,
3377 * but not posix open/mkdir operations. Set a
3378 * default type for read/write checks. */
3380 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3383 break;
3386 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3388 NTSTATUS status;
3389 size_t param_len = 0;
3390 size_t data_len = total_data;
3392 if (!lp_unix_extensions()) {
3393 reply_nterror(
3394 req,
3395 NT_STATUS_INVALID_LEVEL);
3396 return;
3399 if (lp_smb_encrypt(SNUM(conn)) == false) {
3400 reply_nterror(
3401 req,
3402 NT_STATUS_NOT_SUPPORTED);
3403 return;
3406 DEBUG( 4,("call_trans2setfsinfo: "
3407 "request transport encryption.\n"));
3409 status = srv_request_encryption_setup(conn,
3410 (unsigned char **)ppdata,
3411 &data_len,
3412 (unsigned char **)pparams,
3413 &param_len);
3415 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3416 !NT_STATUS_IS_OK(status)) {
3417 reply_nterror(req, status);
3418 return;
3421 send_trans2_replies(conn, req,
3422 *pparams,
3423 param_len,
3424 *ppdata,
3425 data_len,
3426 max_data_bytes);
3428 if (NT_STATUS_IS_OK(status)) {
3429 /* Server-side transport
3430 * encryption is now *on*. */
3431 status = srv_encryption_start(conn);
3432 if (!NT_STATUS_IS_OK(status)) {
3433 exit_server_cleanly(
3434 "Failure in setting "
3435 "up encrypted transport");
3438 return;
3441 case SMB_FS_QUOTA_INFORMATION:
3443 files_struct *fsp = NULL;
3444 SMB_NTQUOTA_STRUCT quotas;
3446 ZERO_STRUCT(quotas);
3448 /* access check */
3449 if ((conn->server_info->utok.uid != 0)
3450 ||!CAN_WRITE(conn)) {
3451 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3452 lp_servicename(SNUM(conn)),
3453 conn->server_info->unix_name));
3454 reply_doserror(req, ERRSRV, ERRaccess);
3455 return;
3458 /* note: normaly there're 48 bytes,
3459 * but we didn't use the last 6 bytes for now
3460 * --metze
3462 fsp = file_fsp(req, SVAL(params,0));
3464 if (!check_fsp_ntquota_handle(conn, req,
3465 fsp)) {
3466 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3467 reply_nterror(
3468 req, NT_STATUS_INVALID_HANDLE);
3469 return;
3472 if (total_data < 42) {
3473 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3474 total_data));
3475 reply_nterror(
3476 req,
3477 NT_STATUS_INVALID_PARAMETER);
3478 return;
3481 /* unknown_1 24 NULL bytes in pdata*/
3483 /* the soft quotas 8 bytes (uint64_t)*/
3484 quotas.softlim = (uint64_t)IVAL(pdata,24);
3485 #ifdef LARGE_SMB_OFF_T
3486 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3487 #else /* LARGE_SMB_OFF_T */
3488 if ((IVAL(pdata,28) != 0)&&
3489 ((quotas.softlim != 0xFFFFFFFF)||
3490 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3491 /* more than 32 bits? */
3492 reply_nterror(
3493 req,
3494 NT_STATUS_INVALID_PARAMETER);
3495 return;
3497 #endif /* LARGE_SMB_OFF_T */
3499 /* the hard quotas 8 bytes (uint64_t)*/
3500 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3501 #ifdef LARGE_SMB_OFF_T
3502 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3503 #else /* LARGE_SMB_OFF_T */
3504 if ((IVAL(pdata,36) != 0)&&
3505 ((quotas.hardlim != 0xFFFFFFFF)||
3506 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3507 /* more than 32 bits? */
3508 reply_nterror(
3509 req,
3510 NT_STATUS_INVALID_PARAMETER);
3511 return;
3513 #endif /* LARGE_SMB_OFF_T */
3515 /* quota_flags 2 bytes **/
3516 quotas.qflags = SVAL(pdata,40);
3518 /* unknown_2 6 NULL bytes follow*/
3520 /* now set the quotas */
3521 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3522 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3523 reply_doserror(req, ERRSRV, ERRerror);
3524 return;
3527 break;
3529 default:
3530 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3531 info_level));
3532 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3533 return;
3534 break;
3538 * sending this reply works fine,
3539 * but I'm not sure it's the same
3540 * like windows do...
3541 * --metze
3543 reply_outbuf(req, 10, 0);
3546 #if defined(HAVE_POSIX_ACLS)
3547 /****************************************************************************
3548 Utility function to count the number of entries in a POSIX acl.
3549 ****************************************************************************/
3551 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3553 unsigned int ace_count = 0;
3554 int entry_id = SMB_ACL_FIRST_ENTRY;
3555 SMB_ACL_ENTRY_T entry;
3557 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3558 /* get_next... */
3559 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3560 entry_id = SMB_ACL_NEXT_ENTRY;
3562 ace_count++;
3564 return ace_count;
3567 /****************************************************************************
3568 Utility function to marshall a POSIX acl into wire format.
3569 ****************************************************************************/
3571 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3573 int entry_id = SMB_ACL_FIRST_ENTRY;
3574 SMB_ACL_ENTRY_T entry;
3576 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3577 SMB_ACL_TAG_T tagtype;
3578 SMB_ACL_PERMSET_T permset;
3579 unsigned char perms = 0;
3580 unsigned int own_grp;
3582 /* get_next... */
3583 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3584 entry_id = SMB_ACL_NEXT_ENTRY;
3587 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3588 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3589 return False;
3592 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3593 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3594 return False;
3597 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3598 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3599 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3601 SCVAL(pdata,1,perms);
3603 switch (tagtype) {
3604 case SMB_ACL_USER_OBJ:
3605 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3606 own_grp = (unsigned int)pst->st_ex_uid;
3607 SIVAL(pdata,2,own_grp);
3608 SIVAL(pdata,6,0);
3609 break;
3610 case SMB_ACL_USER:
3612 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3613 if (!puid) {
3614 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3615 return False;
3617 own_grp = (unsigned int)*puid;
3618 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3619 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3620 SIVAL(pdata,2,own_grp);
3621 SIVAL(pdata,6,0);
3622 break;
3624 case SMB_ACL_GROUP_OBJ:
3625 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3626 own_grp = (unsigned int)pst->st_ex_gid;
3627 SIVAL(pdata,2,own_grp);
3628 SIVAL(pdata,6,0);
3629 break;
3630 case SMB_ACL_GROUP:
3632 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3633 if (!pgid) {
3634 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3635 return False;
3637 own_grp = (unsigned int)*pgid;
3638 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3639 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3640 SIVAL(pdata,2,own_grp);
3641 SIVAL(pdata,6,0);
3642 break;
3644 case SMB_ACL_MASK:
3645 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3646 SIVAL(pdata,2,0xFFFFFFFF);
3647 SIVAL(pdata,6,0xFFFFFFFF);
3648 break;
3649 case SMB_ACL_OTHER:
3650 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3651 SIVAL(pdata,2,0xFFFFFFFF);
3652 SIVAL(pdata,6,0xFFFFFFFF);
3653 break;
3654 default:
3655 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3656 return False;
3658 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3661 return True;
3663 #endif
3665 /****************************************************************************
3666 Store the FILE_UNIX_BASIC info.
3667 ****************************************************************************/
3669 static char *store_file_unix_basic(connection_struct *conn,
3670 char *pdata,
3671 files_struct *fsp,
3672 const SMB_STRUCT_STAT *psbuf)
3674 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3675 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3677 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3678 pdata += 8;
3680 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3681 pdata += 8;
3683 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3684 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3685 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3686 pdata += 24;
3688 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3689 SIVAL(pdata,4,0);
3690 pdata += 8;
3692 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3693 SIVAL(pdata,4,0);
3694 pdata += 8;
3696 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3697 pdata += 4;
3699 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3700 SIVAL(pdata,4,0);
3701 pdata += 8;
3703 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3704 SIVAL(pdata,4,0);
3705 pdata += 8;
3707 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3708 pdata += 8;
3710 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3711 SIVAL(pdata,4,0);
3712 pdata += 8;
3714 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3715 SIVAL(pdata,4,0);
3716 pdata += 8;
3718 return pdata;
3721 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3722 * the chflags(2) (or equivalent) flags.
3724 * XXX: this really should be behind the VFS interface. To do this, we would
3725 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3726 * Each VFS module could then implement its own mapping as appropriate for the
3727 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3729 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3730 info2_flags_map[] =
3732 #ifdef UF_NODUMP
3733 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3734 #endif
3736 #ifdef UF_IMMUTABLE
3737 { UF_IMMUTABLE, EXT_IMMUTABLE },
3738 #endif
3740 #ifdef UF_APPEND
3741 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3742 #endif
3744 #ifdef UF_HIDDEN
3745 { UF_HIDDEN, EXT_HIDDEN },
3746 #endif
3748 /* Do not remove. We need to guarantee that this array has at least one
3749 * entry to build on HP-UX.
3751 { 0, 0 }
3755 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3756 uint32 *smb_fflags, uint32 *smb_fmask)
3758 int i;
3760 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3761 *smb_fmask |= info2_flags_map[i].smb_fflag;
3762 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3763 *smb_fflags |= info2_flags_map[i].smb_fflag;
3768 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3769 const uint32 smb_fflags,
3770 const uint32 smb_fmask,
3771 int *stat_fflags)
3773 uint32 max_fmask = 0;
3774 int i;
3776 *stat_fflags = psbuf->st_ex_flags;
3778 /* For each flags requested in smb_fmask, check the state of the
3779 * corresponding flag in smb_fflags and set or clear the matching
3780 * stat flag.
3783 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3784 max_fmask |= info2_flags_map[i].smb_fflag;
3785 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3786 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3787 *stat_fflags |= info2_flags_map[i].stat_fflag;
3788 } else {
3789 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3794 /* If smb_fmask is asking to set any bits that are not supported by
3795 * our flag mappings, we should fail.
3797 if ((smb_fmask & max_fmask) != smb_fmask) {
3798 return False;
3801 return True;
3805 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3806 * of file flags and birth (create) time.
3808 static char *store_file_unix_basic_info2(connection_struct *conn,
3809 char *pdata,
3810 files_struct *fsp,
3811 const SMB_STRUCT_STAT *psbuf)
3813 uint32 file_flags = 0;
3814 uint32 flags_mask = 0;
3816 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3818 /* Create (birth) time 64 bit */
3819 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3820 pdata += 8;
3822 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3823 SIVAL(pdata, 0, file_flags); /* flags */
3824 SIVAL(pdata, 4, flags_mask); /* mask */
3825 pdata += 8;
3827 return pdata;
3830 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3831 const struct stream_struct *streams,
3832 char *data,
3833 unsigned int max_data_bytes,
3834 unsigned int *data_size)
3836 unsigned int i;
3837 unsigned int ofs = 0;
3839 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3840 unsigned int next_offset;
3841 size_t namelen;
3842 smb_ucs2_t *namebuf;
3844 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3845 streams[i].name, &namelen) ||
3846 namelen <= 2)
3848 return NT_STATUS_INVALID_PARAMETER;
3852 * name_buf is now null-terminated, we need to marshall as not
3853 * terminated
3856 namelen -= 2;
3858 SIVAL(data, ofs+4, namelen);
3859 SOFF_T(data, ofs+8, streams[i].size);
3860 SOFF_T(data, ofs+16, streams[i].alloc_size);
3861 memcpy(data+ofs+24, namebuf, namelen);
3862 TALLOC_FREE(namebuf);
3864 next_offset = ofs + 24 + namelen;
3866 if (i == num_streams-1) {
3867 SIVAL(data, ofs, 0);
3869 else {
3870 unsigned int align = ndr_align_size(next_offset, 8);
3872 memset(data+next_offset, 0, align);
3873 next_offset += align;
3875 SIVAL(data, ofs, next_offset - ofs);
3876 ofs = next_offset;
3879 ofs = next_offset;
3882 *data_size = ofs;
3884 return NT_STATUS_OK;
3887 /****************************************************************************
3888 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3889 ****************************************************************************/
3891 static void call_trans2qpipeinfo(connection_struct *conn,
3892 struct smb_request *req,
3893 unsigned int tran_call,
3894 char **pparams, int total_params,
3895 char **ppdata, int total_data,
3896 unsigned int max_data_bytes)
3898 char *params = *pparams;
3899 char *pdata = *ppdata;
3900 unsigned int data_size = 0;
3901 unsigned int param_size = 2;
3902 uint16 info_level;
3903 files_struct *fsp;
3905 if (!params) {
3906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3907 return;
3910 if (total_params < 4) {
3911 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3912 return;
3915 fsp = file_fsp(req, SVAL(params,0));
3916 if (!fsp_is_np(fsp)) {
3917 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3918 return;
3921 info_level = SVAL(params,2);
3923 *pparams = (char *)SMB_REALLOC(*pparams,2);
3924 if (*pparams == NULL) {
3925 reply_nterror(req, NT_STATUS_NO_MEMORY);
3926 return;
3928 params = *pparams;
3929 SSVAL(params,0,0);
3930 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3931 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3932 if (*ppdata == NULL ) {
3933 reply_nterror(req, NT_STATUS_NO_MEMORY);
3934 return;
3936 pdata = *ppdata;
3938 switch (info_level) {
3939 case SMB_FILE_STANDARD_INFORMATION:
3940 memset(pdata,0,24);
3941 SOFF_T(pdata,0,4096LL);
3942 SIVAL(pdata,16,1);
3943 SIVAL(pdata,20,1);
3944 data_size = 24;
3945 break;
3947 default:
3948 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3949 return;
3952 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3953 max_data_bytes);
3955 return;
3958 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3959 TALLOC_CTX *mem_ctx,
3960 uint16_t info_level,
3961 files_struct *fsp,
3962 const struct smb_filename *smb_fname,
3963 bool delete_pending,
3964 struct timespec write_time_ts,
3965 bool ms_dfs_link,
3966 struct ea_list *ea_list,
3967 int lock_data_count,
3968 char *lock_data,
3969 uint16_t flags2,
3970 unsigned int max_data_bytes,
3971 char **ppdata,
3972 unsigned int *pdata_size)
3974 char *pdata = *ppdata;
3975 char *dstart, *dend;
3976 unsigned int data_size;
3977 struct timespec create_time_ts, mtime_ts, atime_ts;
3978 time_t create_time, mtime, atime;
3979 SMB_STRUCT_STAT sbuf;
3980 char *p;
3981 char *fname;
3982 char *base_name;
3983 char *dos_fname;
3984 int mode;
3985 int nlink;
3986 NTSTATUS status;
3987 uint64_t file_size = 0;
3988 uint64_t pos = 0;
3989 uint64_t allocation_size = 0;
3990 uint64_t file_index = 0;
3991 uint32_t access_mask = 0;
3993 sbuf = smb_fname->st;
3995 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3996 return NT_STATUS_INVALID_LEVEL;
3999 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
4000 if (!NT_STATUS_IS_OK(status)) {
4001 return status;
4004 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4005 fname, fsp ? fsp->fnum : -1, info_level, max_data_bytes));
4007 if (ms_dfs_link) {
4008 mode = dos_mode_msdfs(conn, smb_fname);
4009 } else {
4010 mode = dos_mode(conn, smb_fname);
4012 if (!mode)
4013 mode = FILE_ATTRIBUTE_NORMAL;
4015 nlink = sbuf.st_ex_nlink;
4017 if (nlink && (mode&aDIR)) {
4018 nlink = 1;
4021 if ((nlink > 0) && delete_pending) {
4022 nlink -= 1;
4025 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4026 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4027 if (*ppdata == NULL) {
4028 return NT_STATUS_NO_MEMORY;
4030 pdata = *ppdata;
4031 dstart = pdata;
4032 dend = dstart + data_size - 1;
4034 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4035 update_stat_ex_mtime(&sbuf, write_time_ts);
4038 create_time_ts = sbuf.st_ex_btime;
4039 mtime_ts = sbuf.st_ex_mtime;
4040 atime_ts = sbuf.st_ex_atime;
4042 if (lp_dos_filetime_resolution(SNUM(conn))) {
4043 dos_filetime_timespec(&create_time_ts);
4044 dos_filetime_timespec(&mtime_ts);
4045 dos_filetime_timespec(&atime_ts);
4048 create_time = convert_timespec_to_time_t(create_time_ts);
4049 mtime = convert_timespec_to_time_t(mtime_ts);
4050 atime = convert_timespec_to_time_t(atime_ts);
4052 p = strrchr_m(smb_fname->base_name,'/');
4053 if (!p)
4054 base_name = smb_fname->base_name;
4055 else
4056 base_name = p+1;
4058 /* NT expects the name to be in an exact form of the *full*
4059 filename. See the trans2 torture test */
4060 if (ISDOT(base_name)) {
4061 dos_fname = talloc_strdup(mem_ctx, "\\");
4062 if (!dos_fname) {
4063 return NT_STATUS_NO_MEMORY;
4065 } else {
4066 dos_fname = talloc_asprintf(mem_ctx,
4067 "\\%s",
4068 fname);
4069 if (!dos_fname) {
4070 return NT_STATUS_NO_MEMORY;
4072 string_replace(dos_fname, '/', '\\');
4075 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4077 if (!fsp) {
4078 /* Do we have this path open ? */
4079 files_struct *fsp1;
4080 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4081 fsp1 = file_find_di_first(fileid);
4082 if (fsp1 && fsp1->initial_allocation_size) {
4083 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4087 if (!(mode & aDIR)) {
4088 file_size = get_file_size_stat(&sbuf);
4091 if (fsp && fsp->fh) {
4092 pos = fsp->fh->position_information;
4095 if (fsp) {
4096 access_mask = fsp->access_mask;
4097 } else {
4098 /* GENERIC_EXECUTE mapping from Windows */
4099 access_mask = 0x12019F;
4102 /* This should be an index number - looks like
4103 dev/ino to me :-)
4105 I think this causes us to fail the IFSKIT
4106 BasicFileInformationTest. -tpot */
4107 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4108 file_index |= ((sbuf.st_ex_dev) & UINT32_MAX) << 32; /* FileIndexHigh */
4110 switch (info_level) {
4111 case SMB_INFO_STANDARD:
4112 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4113 data_size = 22;
4114 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4115 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4116 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4117 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4118 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4119 SSVAL(pdata,l1_attrFile,mode);
4120 break;
4122 case SMB_INFO_QUERY_EA_SIZE:
4124 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4125 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4126 data_size = 26;
4127 srv_put_dos_date2(pdata,0,create_time);
4128 srv_put_dos_date2(pdata,4,atime);
4129 srv_put_dos_date2(pdata,8,mtime); /* write time */
4130 SIVAL(pdata,12,(uint32)file_size);
4131 SIVAL(pdata,16,(uint32)allocation_size);
4132 SSVAL(pdata,20,mode);
4133 SIVAL(pdata,22,ea_size);
4134 break;
4137 case SMB_INFO_IS_NAME_VALID:
4138 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4139 if (fsp) {
4140 /* os/2 needs this ? really ?*/
4141 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4143 /* This is only reached for qpathinfo */
4144 data_size = 0;
4145 break;
4147 case SMB_INFO_QUERY_EAS_FROM_LIST:
4149 size_t total_ea_len = 0;
4150 struct ea_list *ea_file_list = NULL;
4152 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4154 ea_file_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4155 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4157 if (!ea_list || (total_ea_len > data_size)) {
4158 data_size = 4;
4159 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4160 break;
4163 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4164 break;
4167 case SMB_INFO_QUERY_ALL_EAS:
4169 /* We have data_size bytes to put EA's into. */
4170 size_t total_ea_len = 0;
4172 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4174 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
4175 if (!ea_list || (total_ea_len > data_size)) {
4176 data_size = 4;
4177 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4178 break;
4181 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4182 break;
4185 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4187 /* We have data_size bytes to put EA's into. */
4188 size_t total_ea_len = 0;
4189 struct ea_list *ea_file_list = NULL;
4191 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4193 /*TODO: add filtering and index handling */
4195 ea_file_list = get_ea_list_from_file(mem_ctx,
4196 conn, fsp,
4197 fname,
4198 &total_ea_len);
4199 if (!ea_file_list) {
4200 return NT_STATUS_NO_EAS_ON_FILE;
4203 status = fill_ea_chained_buffer(mem_ctx,
4204 pdata,
4205 data_size,
4206 &data_size,
4207 conn, ea_file_list);
4208 if (!NT_STATUS_IS_OK(status)) {
4209 return status;
4211 break;
4214 case SMB_FILE_BASIC_INFORMATION:
4215 case SMB_QUERY_FILE_BASIC_INFO:
4217 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4218 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4219 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4220 } else {
4221 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4222 data_size = 40;
4223 SIVAL(pdata,36,0);
4225 put_long_date_timespec(pdata,create_time_ts);
4226 put_long_date_timespec(pdata+8,atime_ts);
4227 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4228 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4229 SIVAL(pdata,32,mode);
4231 DEBUG(5,("SMB_QFBI - "));
4232 DEBUG(5,("create: %s ", ctime(&create_time)));
4233 DEBUG(5,("access: %s ", ctime(&atime)));
4234 DEBUG(5,("write: %s ", ctime(&mtime)));
4235 DEBUG(5,("change: %s ", ctime(&mtime)));
4236 DEBUG(5,("mode: %x\n", mode));
4237 break;
4239 case SMB_FILE_STANDARD_INFORMATION:
4240 case SMB_QUERY_FILE_STANDARD_INFO:
4242 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4243 data_size = 24;
4244 SOFF_T(pdata,0,allocation_size);
4245 SOFF_T(pdata,8,file_size);
4246 SIVAL(pdata,16,nlink);
4247 SCVAL(pdata,20,delete_pending?1:0);
4248 SCVAL(pdata,21,(mode&aDIR)?1:0);
4249 SSVAL(pdata,22,0); /* Padding. */
4250 break;
4252 case SMB_FILE_EA_INFORMATION:
4253 case SMB_QUERY_FILE_EA_INFO:
4255 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4256 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4257 data_size = 4;
4258 SIVAL(pdata,0,ea_size);
4259 break;
4262 /* Get the 8.3 name - used if NT SMB was negotiated. */
4263 case SMB_QUERY_FILE_ALT_NAME_INFO:
4264 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4266 int len;
4267 char mangled_name[13];
4268 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4269 if (!name_to_8_3(base_name,mangled_name,
4270 True,conn->params)) {
4271 return NT_STATUS_NO_MEMORY;
4273 len = srvstr_push(dstart, flags2,
4274 pdata+4, mangled_name,
4275 PTR_DIFF(dend, pdata+4),
4276 STR_UNICODE);
4277 data_size = 4 + len;
4278 SIVAL(pdata,0,len);
4279 break;
4282 case SMB_QUERY_FILE_NAME_INFO:
4284 int len;
4286 this must be *exactly* right for ACLs on mapped drives to work
4288 len = srvstr_push(dstart, flags2,
4289 pdata+4, dos_fname,
4290 PTR_DIFF(dend, pdata+4),
4291 STR_UNICODE);
4292 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4293 data_size = 4 + len;
4294 SIVAL(pdata,0,len);
4295 break;
4298 case SMB_FILE_ALLOCATION_INFORMATION:
4299 case SMB_QUERY_FILE_ALLOCATION_INFO:
4300 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4301 data_size = 8;
4302 SOFF_T(pdata,0,allocation_size);
4303 break;
4305 case SMB_FILE_END_OF_FILE_INFORMATION:
4306 case SMB_QUERY_FILE_END_OF_FILEINFO:
4307 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4308 data_size = 8;
4309 SOFF_T(pdata,0,file_size);
4310 break;
4312 case SMB_QUERY_FILE_ALL_INFO:
4313 case SMB_FILE_ALL_INFORMATION:
4315 int len;
4316 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4317 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4318 put_long_date_timespec(pdata,create_time_ts);
4319 put_long_date_timespec(pdata+8,atime_ts);
4320 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4321 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4322 SIVAL(pdata,32,mode);
4323 SIVAL(pdata,36,0); /* padding. */
4324 pdata += 40;
4325 SOFF_T(pdata,0,allocation_size);
4326 SOFF_T(pdata,8,file_size);
4327 SIVAL(pdata,16,nlink);
4328 SCVAL(pdata,20,delete_pending);
4329 SCVAL(pdata,21,(mode&aDIR)?1:0);
4330 SSVAL(pdata,22,0);
4331 pdata += 24;
4332 SIVAL(pdata,0,ea_size);
4333 pdata += 4; /* EA info */
4334 len = srvstr_push(dstart, flags2,
4335 pdata+4, dos_fname,
4336 PTR_DIFF(dend, pdata+4),
4337 STR_UNICODE);
4338 SIVAL(pdata,0,len);
4339 pdata += 4 + len;
4340 data_size = PTR_DIFF(pdata,(*ppdata));
4341 break;
4344 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4346 int len;
4347 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4348 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4349 put_long_date_timespec(pdata+0x00,create_time_ts);
4350 put_long_date_timespec(pdata+0x08,atime_ts);
4351 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4352 put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
4353 SIVAL(pdata, 0x20, mode);
4354 SIVAL(pdata, 0x24, 0); /* padding. */
4355 SBVAL(pdata, 0x28, allocation_size);
4356 SBVAL(pdata, 0x30, file_size);
4357 SIVAL(pdata, 0x38, nlink);
4358 SCVAL(pdata, 0x3C, delete_pending);
4359 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4360 SSVAL(pdata, 0x3E, 0); /* padding */
4361 SBVAL(pdata, 0x40, file_index);
4362 SIVAL(pdata, 0x48, ea_size);
4363 SIVAL(pdata, 0x4C, access_mask);
4364 SBVAL(pdata, 0x50, pos);
4365 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4366 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4368 pdata += 0x60;
4370 len = srvstr_push(dstart, flags2,
4371 pdata+4, dos_fname,
4372 PTR_DIFF(dend, pdata+4),
4373 STR_UNICODE);
4374 SIVAL(pdata,0,len);
4375 pdata += 4 + len;
4376 data_size = PTR_DIFF(pdata,(*ppdata));
4377 break;
4379 case SMB_FILE_INTERNAL_INFORMATION:
4381 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4382 SBVAL(pdata, 0, file_index);
4383 data_size = 8;
4384 break;
4386 case SMB_FILE_ACCESS_INFORMATION:
4387 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4388 SIVAL(pdata, 0, access_mask);
4389 data_size = 4;
4390 break;
4392 case SMB_FILE_NAME_INFORMATION:
4393 /* Pathname with leading '\'. */
4395 size_t byte_len;
4396 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4397 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4398 SIVAL(pdata,0,byte_len);
4399 data_size = 4 + byte_len;
4400 break;
4403 case SMB_FILE_DISPOSITION_INFORMATION:
4404 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4405 data_size = 1;
4406 SCVAL(pdata,0,delete_pending);
4407 break;
4409 case SMB_FILE_POSITION_INFORMATION:
4410 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4411 data_size = 8;
4412 SOFF_T(pdata,0,pos);
4413 break;
4415 case SMB_FILE_MODE_INFORMATION:
4416 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4417 SIVAL(pdata,0,mode);
4418 data_size = 4;
4419 break;
4421 case SMB_FILE_ALIGNMENT_INFORMATION:
4422 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4423 SIVAL(pdata,0,0); /* No alignment needed. */
4424 data_size = 4;
4425 break;
4428 * NT4 server just returns "invalid query" to this - if we try
4429 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4430 * want this. JRA.
4432 /* The first statement above is false - verified using Thursby
4433 * client against NT4 -- gcolley.
4435 case SMB_QUERY_FILE_STREAM_INFO:
4436 case SMB_FILE_STREAM_INFORMATION: {
4437 unsigned int num_streams;
4438 struct stream_struct *streams;
4440 DEBUG(10,("smbd_do_qfilepathinfo: "
4441 "SMB_FILE_STREAM_INFORMATION\n"));
4443 status = SMB_VFS_STREAMINFO(
4444 conn, fsp, fname, talloc_tos(),
4445 &num_streams, &streams);
4447 if (!NT_STATUS_IS_OK(status)) {
4448 DEBUG(10, ("could not get stream info: %s\n",
4449 nt_errstr(status)));
4450 return status;
4453 status = marshall_stream_info(num_streams, streams,
4454 pdata, max_data_bytes,
4455 &data_size);
4457 if (!NT_STATUS_IS_OK(status)) {
4458 DEBUG(10, ("marshall_stream_info failed: %s\n",
4459 nt_errstr(status)));
4460 return status;
4463 TALLOC_FREE(streams);
4465 break;
4467 case SMB_QUERY_COMPRESSION_INFO:
4468 case SMB_FILE_COMPRESSION_INFORMATION:
4469 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4470 SOFF_T(pdata,0,file_size);
4471 SIVAL(pdata,8,0); /* ??? */
4472 SIVAL(pdata,12,0); /* ??? */
4473 data_size = 16;
4474 break;
4476 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4477 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4478 put_long_date_timespec(pdata,create_time_ts);
4479 put_long_date_timespec(pdata+8,atime_ts);
4480 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4481 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4482 SOFF_T(pdata,32,allocation_size);
4483 SOFF_T(pdata,40,file_size);
4484 SIVAL(pdata,48,mode);
4485 SIVAL(pdata,52,0); /* ??? */
4486 data_size = 56;
4487 break;
4489 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4490 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4491 SIVAL(pdata,0,mode);
4492 SIVAL(pdata,4,0);
4493 data_size = 8;
4494 break;
4497 * CIFS UNIX Extensions.
4500 case SMB_QUERY_FILE_UNIX_BASIC:
4502 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4503 data_size = PTR_DIFF(pdata,(*ppdata));
4506 int i;
4507 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4509 for (i=0; i<100; i++)
4510 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4511 DEBUG(4,("\n"));
4514 break;
4516 case SMB_QUERY_FILE_UNIX_INFO2:
4518 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4519 data_size = PTR_DIFF(pdata,(*ppdata));
4522 int i;
4523 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4525 for (i=0; i<100; i++)
4526 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4527 DEBUG(4,("\n"));
4530 break;
4532 case SMB_QUERY_FILE_UNIX_LINK:
4534 int len;
4535 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4537 if (!buffer) {
4538 return NT_STATUS_NO_MEMORY;
4541 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4542 #ifdef S_ISLNK
4543 if(!S_ISLNK(sbuf.st_ex_mode)) {
4544 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4546 #else
4547 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4548 #endif
4549 len = SMB_VFS_READLINK(conn,fname,
4550 buffer, PATH_MAX);
4551 if (len == -1) {
4552 return map_nt_error_from_unix(errno);
4554 buffer[len] = 0;
4555 len = srvstr_push(dstart, flags2,
4556 pdata, buffer,
4557 PTR_DIFF(dend, pdata),
4558 STR_TERMINATE);
4559 pdata += len;
4560 data_size = PTR_DIFF(pdata,(*ppdata));
4562 break;
4565 #if defined(HAVE_POSIX_ACLS)
4566 case SMB_QUERY_POSIX_ACL:
4568 SMB_ACL_T file_acl = NULL;
4569 SMB_ACL_T def_acl = NULL;
4570 uint16 num_file_acls = 0;
4571 uint16 num_def_acls = 0;
4573 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4574 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4575 } else {
4576 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4579 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4580 DEBUG(5,("smbd_do_qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4581 fname ));
4582 return NT_STATUS_NOT_IMPLEMENTED;
4585 if (S_ISDIR(sbuf.st_ex_mode)) {
4586 if (fsp && fsp->is_directory) {
4587 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4588 } else {
4589 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4591 def_acl = free_empty_sys_acl(conn, def_acl);
4594 num_file_acls = count_acl_entries(conn, file_acl);
4595 num_def_acls = count_acl_entries(conn, def_acl);
4597 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4598 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4599 data_size,
4600 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4601 SMB_POSIX_ACL_HEADER_SIZE) ));
4602 if (file_acl) {
4603 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4605 if (def_acl) {
4606 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4608 return NT_STATUS_BUFFER_TOO_SMALL;
4611 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4612 SSVAL(pdata,2,num_file_acls);
4613 SSVAL(pdata,4,num_def_acls);
4614 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4615 if (file_acl) {
4616 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4618 if (def_acl) {
4619 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4621 return NT_STATUS_INTERNAL_ERROR;
4623 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4624 if (file_acl) {
4625 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4627 if (def_acl) {
4628 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4630 return NT_STATUS_INTERNAL_ERROR;
4633 if (file_acl) {
4634 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4636 if (def_acl) {
4637 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4639 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4640 break;
4642 #endif
4645 case SMB_QUERY_POSIX_LOCK:
4647 uint64_t count;
4648 uint64_t offset;
4649 uint32 lock_pid;
4650 enum brl_type lock_type;
4652 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4653 return NT_STATUS_INVALID_PARAMETER;
4656 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4657 case POSIX_LOCK_TYPE_READ:
4658 lock_type = READ_LOCK;
4659 break;
4660 case POSIX_LOCK_TYPE_WRITE:
4661 lock_type = WRITE_LOCK;
4662 break;
4663 case POSIX_LOCK_TYPE_UNLOCK:
4664 default:
4665 /* There's no point in asking for an unlock... */
4666 return NT_STATUS_INVALID_PARAMETER;
4669 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4670 #if defined(HAVE_LONGLONG)
4671 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4672 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4673 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4674 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4675 #else /* HAVE_LONGLONG */
4676 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4677 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4678 #endif /* HAVE_LONGLONG */
4680 status = query_lock(fsp,
4681 &lock_pid,
4682 &count,
4683 &offset,
4684 &lock_type,
4685 POSIX_LOCK);
4687 if (ERROR_WAS_LOCK_DENIED(status)) {
4688 /* Here we need to report who has it locked... */
4689 data_size = POSIX_LOCK_DATA_SIZE;
4691 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4692 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4693 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4694 #if defined(HAVE_LONGLONG)
4695 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4696 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4697 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4698 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4699 #else /* HAVE_LONGLONG */
4700 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4701 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4702 #endif /* HAVE_LONGLONG */
4704 } else if (NT_STATUS_IS_OK(status)) {
4705 /* For success we just return a copy of what we sent
4706 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4707 data_size = POSIX_LOCK_DATA_SIZE;
4708 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4709 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4710 } else {
4711 return status;
4713 break;
4716 default:
4717 return NT_STATUS_INVALID_LEVEL;
4720 *pdata_size = data_size;
4721 return NT_STATUS_OK;
4724 /****************************************************************************
4725 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4726 file name or file id).
4727 ****************************************************************************/
4729 static void call_trans2qfilepathinfo(connection_struct *conn,
4730 struct smb_request *req,
4731 unsigned int tran_call,
4732 char **pparams, int total_params,
4733 char **ppdata, int total_data,
4734 unsigned int max_data_bytes)
4736 char *params = *pparams;
4737 char *pdata = *ppdata;
4738 uint16 info_level;
4739 unsigned int data_size = 0;
4740 unsigned int param_size = 2;
4741 char *fname = NULL;
4742 struct smb_filename *smb_fname = NULL;
4743 bool delete_pending = False;
4744 struct timespec write_time_ts;
4745 files_struct *fsp = NULL;
4746 struct file_id fileid;
4747 struct ea_list *ea_list = NULL;
4748 int lock_data_count = 0;
4749 char *lock_data = NULL;
4750 bool ms_dfs_link = false;
4751 NTSTATUS status = NT_STATUS_OK;
4753 if (!params) {
4754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4755 return;
4758 ZERO_STRUCT(write_time_ts);
4760 if (tran_call == TRANSACT2_QFILEINFO) {
4761 if (total_params < 4) {
4762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4763 return;
4766 if (IS_IPC(conn)) {
4767 call_trans2qpipeinfo(conn, req, tran_call,
4768 pparams, total_params,
4769 ppdata, total_data,
4770 max_data_bytes);
4771 return;
4774 fsp = file_fsp(req, SVAL(params,0));
4775 info_level = SVAL(params,2);
4777 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4779 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4780 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4781 return;
4784 /* Initial check for valid fsp ptr. */
4785 if (!check_fsp_open(conn, req, fsp)) {
4786 return;
4789 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
4790 if (!fname) {
4791 reply_nterror(req, NT_STATUS_NO_MEMORY);
4792 return;
4795 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
4796 NULL, &smb_fname);
4797 if (!NT_STATUS_IS_OK(status)) {
4798 reply_nterror(req, status);
4799 return;
4802 if(fsp->fake_file_handle) {
4804 * This is actually for the QUOTA_FAKE_FILE --metze
4807 /* We know this name is ok, it's already passed the checks. */
4809 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
4811 * This is actually a QFILEINFO on a directory
4812 * handle (returned from an NT SMB). NT5.0 seems
4813 * to do this call. JRA.
4816 if (INFO_LEVEL_IS_UNIX(info_level)) {
4817 /* Always do lstat for UNIX calls. */
4818 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4819 DEBUG(3,("call_trans2qfilepathinfo: "
4820 "SMB_VFS_LSTAT of %s failed "
4821 "(%s)\n",
4822 smb_fname_str_dbg(smb_fname),
4823 strerror(errno)));
4824 reply_nterror(req,
4825 map_nt_error_from_unix(errno));
4826 return;
4828 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4829 DEBUG(3,("call_trans2qfilepathinfo: "
4830 "SMB_VFS_STAT of %s failed (%s)\n",
4831 smb_fname_str_dbg(smb_fname),
4832 strerror(errno)));
4833 reply_nterror(req,
4834 map_nt_error_from_unix(errno));
4835 return;
4838 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4839 get_file_infos(fileid, &delete_pending, &write_time_ts);
4840 } else {
4842 * Original code - this is an open file.
4844 if (!check_fsp(conn, req, fsp)) {
4845 return;
4848 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4849 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4850 fsp->fnum, strerror(errno)));
4851 reply_nterror(req,
4852 map_nt_error_from_unix(errno));
4853 return;
4855 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4856 get_file_infos(fileid, &delete_pending, &write_time_ts);
4859 } else {
4860 /* qpathinfo */
4861 if (total_params < 7) {
4862 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4863 return;
4866 info_level = SVAL(params,0);
4868 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4870 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4871 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4872 return;
4875 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
4876 total_params - 6,
4877 STR_TERMINATE, &status);
4878 if (!NT_STATUS_IS_OK(status)) {
4879 reply_nterror(req, status);
4880 return;
4883 status = filename_convert(req,
4884 conn,
4885 req->flags2 & FLAGS2_DFS_PATHNAMES,
4886 fname,
4887 &smb_fname,
4888 &fname);
4889 if (!NT_STATUS_IS_OK(status)) {
4890 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4891 reply_botherror(req,
4892 NT_STATUS_PATH_NOT_COVERED,
4893 ERRSRV, ERRbadpath);
4894 return;
4896 reply_nterror(req, status);
4897 return;
4900 /* If this is a stream, check if there is a delete_pending. */
4901 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4902 && is_ntfs_stream_smb_fname(smb_fname)) {
4903 struct smb_filename *smb_fname_base = NULL;
4905 /* Create an smb_filename with stream_name == NULL. */
4906 status =
4907 create_synthetic_smb_fname(talloc_tos(),
4908 smb_fname->base_name,
4909 NULL, NULL,
4910 &smb_fname_base);
4911 if (!NT_STATUS_IS_OK(status)) {
4912 reply_nterror(req, status);
4913 return;
4916 if (INFO_LEVEL_IS_UNIX(info_level)) {
4917 /* Always do lstat for UNIX calls. */
4918 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4919 DEBUG(3,("call_trans2qfilepathinfo: "
4920 "SMB_VFS_LSTAT of %s failed "
4921 "(%s)\n",
4922 smb_fname_str_dbg(smb_fname_base),
4923 strerror(errno)));
4924 TALLOC_FREE(smb_fname_base);
4925 reply_nterror(req,
4926 map_nt_error_from_unix(errno));
4927 return;
4929 } else {
4930 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4931 DEBUG(3,("call_trans2qfilepathinfo: "
4932 "fileinfo of %s failed "
4933 "(%s)\n",
4934 smb_fname_str_dbg(smb_fname_base),
4935 strerror(errno)));
4936 TALLOC_FREE(smb_fname_base);
4937 reply_nterror(req,
4938 map_nt_error_from_unix(errno));
4939 return;
4943 fileid = vfs_file_id_from_sbuf(conn,
4944 &smb_fname_base->st);
4945 TALLOC_FREE(smb_fname_base);
4946 get_file_infos(fileid, &delete_pending, NULL);
4947 if (delete_pending) {
4948 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4949 return;
4953 if (INFO_LEVEL_IS_UNIX(info_level)) {
4954 /* Always do lstat for UNIX calls. */
4955 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4956 DEBUG(3,("call_trans2qfilepathinfo: "
4957 "SMB_VFS_LSTAT of %s failed (%s)\n",
4958 smb_fname_str_dbg(smb_fname),
4959 strerror(errno)));
4960 reply_nterror(req,
4961 map_nt_error_from_unix(errno));
4962 return;
4965 } else if (!VALID_STAT(smb_fname->st) &&
4966 SMB_VFS_STAT(conn, smb_fname) &&
4967 (info_level != SMB_INFO_IS_NAME_VALID)) {
4968 ms_dfs_link = check_msdfs_link(conn, fname,
4969 &smb_fname->st);
4971 if (!ms_dfs_link) {
4972 DEBUG(3,("call_trans2qfilepathinfo: "
4973 "SMB_VFS_STAT of %s failed (%s)\n",
4974 smb_fname_str_dbg(smb_fname),
4975 strerror(errno)));
4976 reply_nterror(req,
4977 map_nt_error_from_unix(errno));
4978 return;
4982 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4983 get_file_infos(fileid, &delete_pending, &write_time_ts);
4984 if (delete_pending) {
4985 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4986 return;
4990 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4991 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4993 /* Pull out any data sent here before we realloc. */
4994 switch (info_level) {
4995 case SMB_INFO_QUERY_EAS_FROM_LIST:
4997 /* Pull any EA list from the data portion. */
4998 uint32 ea_size;
5000 if (total_data < 4) {
5001 reply_nterror(
5002 req, NT_STATUS_INVALID_PARAMETER);
5003 return;
5005 ea_size = IVAL(pdata,0);
5007 if (total_data > 0 && ea_size != total_data) {
5008 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5009 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5010 reply_nterror(
5011 req, NT_STATUS_INVALID_PARAMETER);
5012 return;
5015 if (!lp_ea_support(SNUM(conn))) {
5016 reply_doserror(req, ERRDOS,
5017 ERReasnotsupported);
5018 return;
5021 /* Pull out the list of names. */
5022 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5023 if (!ea_list) {
5024 reply_nterror(
5025 req, NT_STATUS_INVALID_PARAMETER);
5026 return;
5028 break;
5031 case SMB_QUERY_POSIX_LOCK:
5033 if (fsp == NULL || fsp->fh->fd == -1) {
5034 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5035 return;
5038 if (total_data != POSIX_LOCK_DATA_SIZE) {
5039 reply_nterror(
5040 req, NT_STATUS_INVALID_PARAMETER);
5041 return;
5044 /* Copy the lock range data. */
5045 lock_data = (char *)TALLOC_MEMDUP(
5046 req, pdata, total_data);
5047 if (!lock_data) {
5048 reply_nterror(req, NT_STATUS_NO_MEMORY);
5049 return;
5051 lock_data_count = total_data;
5053 default:
5054 break;
5057 *pparams = (char *)SMB_REALLOC(*pparams,2);
5058 if (*pparams == NULL) {
5059 reply_nterror(req, NT_STATUS_NO_MEMORY);
5060 return;
5062 params = *pparams;
5063 SSVAL(params,0,0);
5066 * draft-leach-cifs-v1-spec-02.txt
5067 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5068 * says:
5070 * The requested information is placed in the Data portion of the
5071 * transaction response. For the information levels greater than 0x100,
5072 * the transaction response has 1 parameter word which should be
5073 * ignored by the client.
5075 * However Windows only follows this rule for the IS_NAME_VALID call.
5077 switch (info_level) {
5078 case SMB_INFO_IS_NAME_VALID:
5079 param_size = 0;
5080 break;
5083 if ((info_level & 0xFF00) == 0xFF00) {
5085 * We use levels that start with 0xFF00
5086 * internally to represent SMB2 specific levels
5088 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5089 return;
5092 status = smbd_do_qfilepathinfo(conn, req, info_level,
5093 fsp, smb_fname,
5094 delete_pending, write_time_ts,
5095 ms_dfs_link, ea_list,
5096 lock_data_count, lock_data,
5097 req->flags2, max_data_bytes,
5098 ppdata, &data_size);
5099 if (!NT_STATUS_IS_OK(status)) {
5100 reply_nterror(req, status);
5101 return;
5104 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5105 max_data_bytes);
5107 return;
5110 /****************************************************************************
5111 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5112 code.
5113 ****************************************************************************/
5115 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5116 connection_struct *conn,
5117 const struct smb_filename *smb_fname_old,
5118 const struct smb_filename *smb_fname_new)
5120 char *oldname = NULL;
5121 char *newname = NULL;
5122 NTSTATUS status = NT_STATUS_OK;
5124 /* source must already exist. */
5125 if (!VALID_STAT(smb_fname_old->st)) {
5126 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5129 /* Disallow if newname already exists. */
5130 if (VALID_STAT(smb_fname_new->st)) {
5131 return NT_STATUS_OBJECT_NAME_COLLISION;
5134 /* No links from a directory. */
5135 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5136 return NT_STATUS_FILE_IS_A_DIRECTORY;
5139 status = get_full_smb_filename(ctx, smb_fname_new, &newname);
5140 if (!NT_STATUS_IS_OK(status)) {
5141 goto out;
5143 status = get_full_smb_filename(ctx, smb_fname_old, &oldname);
5144 if (!NT_STATUS_IS_OK(status)) {
5145 goto out;
5148 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
5150 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
5151 status = map_nt_error_from_unix(errno);
5152 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5153 nt_errstr(status), newname, oldname));
5155 out:
5156 TALLOC_FREE(newname);
5157 TALLOC_FREE(oldname);
5158 return status;
5161 /****************************************************************************
5162 Deal with setting the time from any of the setfilepathinfo functions.
5163 ****************************************************************************/
5165 NTSTATUS smb_set_file_time(connection_struct *conn,
5166 files_struct *fsp,
5167 const struct smb_filename *smb_fname,
5168 struct smb_file_time *ft,
5169 bool setting_write_time)
5171 struct smb_filename *smb_fname_base = NULL;
5172 uint32 action =
5173 FILE_NOTIFY_CHANGE_LAST_ACCESS
5174 |FILE_NOTIFY_CHANGE_LAST_WRITE;
5175 NTSTATUS status;
5177 if (!VALID_STAT(smb_fname->st)) {
5178 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5181 /* get some defaults (no modifications) if any info is zero or -1. */
5182 if (null_timespec(ft->atime)) {
5183 ft->atime= smb_fname->st.st_ex_atime;
5184 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5187 if (null_timespec(ft->mtime)) {
5188 ft->mtime = smb_fname->st.st_ex_mtime;
5189 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5192 if (!setting_write_time) {
5193 /* ft->mtime comes from change time, not write time. */
5194 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5197 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5198 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5199 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5200 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5201 if (!null_timespec(ft->create_time)) {
5202 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5203 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5207 * Try and set the times of this file if
5208 * they are different from the current values.
5212 struct timespec mts = smb_fname->st.st_ex_mtime;
5213 struct timespec ats = smb_fname->st.st_ex_atime;
5214 if ((timespec_compare(&ft->atime, &ats) == 0) &&
5215 (timespec_compare(&ft->mtime, &mts) == 0)) {
5216 return NT_STATUS_OK;
5220 if (setting_write_time) {
5222 * This was a Windows setfileinfo on an open file.
5223 * NT does this a lot. We also need to
5224 * set the time here, as it can be read by
5225 * FindFirst/FindNext and with the patch for bug #2045
5226 * in smbd/fileio.c it ensures that this timestamp is
5227 * kept sticky even after a write. We save the request
5228 * away and will set it on file close and after a write. JRA.
5231 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5232 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5234 if (fsp != NULL) {
5235 if (fsp->base_fsp) {
5236 set_sticky_write_time_fsp(fsp->base_fsp,
5237 ft->mtime);
5238 } else {
5239 set_sticky_write_time_fsp(fsp, ft->mtime);
5241 } else {
5242 set_sticky_write_time_path(
5243 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5244 ft->mtime);
5248 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5250 /* Always call ntimes on the base, even if a stream was passed in. */
5251 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5252 NULL, &smb_fname->st,
5253 &smb_fname_base);
5254 if (!NT_STATUS_IS_OK(status)) {
5255 return status;
5258 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5259 TALLOC_FREE(smb_fname_base);
5260 return map_nt_error_from_unix(errno);
5262 TALLOC_FREE(smb_fname_base);
5264 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5265 smb_fname->base_name);
5266 return NT_STATUS_OK;
5269 /****************************************************************************
5270 Deal with setting the dosmode from any of the setfilepathinfo functions.
5271 ****************************************************************************/
5273 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5274 const struct smb_filename *smb_fname,
5275 uint32 dosmode)
5277 struct smb_filename *smb_fname_base = NULL;
5278 NTSTATUS status;
5280 if (!VALID_STAT(smb_fname->st)) {
5281 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5284 /* Always operate on the base_name, even if a stream was passed in. */
5285 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5286 NULL, &smb_fname->st,
5287 &smb_fname_base);
5288 if (!NT_STATUS_IS_OK(status)) {
5289 return status;
5292 if (dosmode) {
5293 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5294 dosmode |= aDIR;
5295 } else {
5296 dosmode &= ~aDIR;
5300 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5302 /* check the mode isn't different, before changing it */
5303 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5304 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5305 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5306 (unsigned int)dosmode));
5308 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5309 false)) {
5310 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5311 "%s failed (%s)\n",
5312 smb_fname_str_dbg(smb_fname_base),
5313 strerror(errno)));
5314 status = map_nt_error_from_unix(errno);
5315 goto out;
5318 status = NT_STATUS_OK;
5319 out:
5320 TALLOC_FREE(smb_fname_base);
5321 return status;
5324 /****************************************************************************
5325 Deal with setting the size from any of the setfilepathinfo functions.
5326 ****************************************************************************/
5328 static NTSTATUS smb_set_file_size(connection_struct *conn,
5329 struct smb_request *req,
5330 files_struct *fsp,
5331 const struct smb_filename *smb_fname,
5332 const SMB_STRUCT_STAT *psbuf,
5333 SMB_OFF_T size)
5335 NTSTATUS status = NT_STATUS_OK;
5336 struct smb_filename *smb_fname_tmp = NULL;
5337 files_struct *new_fsp = NULL;
5339 if (!VALID_STAT(*psbuf)) {
5340 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5343 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5345 if (size == get_file_size_stat(psbuf)) {
5346 return NT_STATUS_OK;
5349 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5350 smb_fname_str_dbg(smb_fname), (double)size));
5352 if (fsp && fsp->fh->fd != -1) {
5353 /* Handle based call. */
5354 if (vfs_set_filelen(fsp, size) == -1) {
5355 return map_nt_error_from_unix(errno);
5357 trigger_write_time_update_immediate(fsp);
5358 return NT_STATUS_OK;
5361 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5362 if (!NT_STATUS_IS_OK(status)) {
5363 return status;
5366 smb_fname_tmp->st = *psbuf;
5368 status = SMB_VFS_CREATE_FILE(
5369 conn, /* conn */
5370 req, /* req */
5371 0, /* root_dir_fid */
5372 smb_fname_tmp, /* fname */
5373 FILE_WRITE_ATTRIBUTES, /* access_mask */
5374 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5375 FILE_SHARE_DELETE),
5376 FILE_OPEN, /* create_disposition*/
5377 0, /* create_options */
5378 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5379 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5380 0, /* allocation_size */
5381 NULL, /* sd */
5382 NULL, /* ea_list */
5383 &new_fsp, /* result */
5384 NULL); /* pinfo */
5386 TALLOC_FREE(smb_fname_tmp);
5388 if (!NT_STATUS_IS_OK(status)) {
5389 /* NB. We check for open_was_deferred in the caller. */
5390 return status;
5393 if (vfs_set_filelen(new_fsp, size) == -1) {
5394 status = map_nt_error_from_unix(errno);
5395 close_file(req, new_fsp,NORMAL_CLOSE);
5396 return status;
5399 trigger_write_time_update_immediate(new_fsp);
5400 close_file(req, new_fsp,NORMAL_CLOSE);
5401 return NT_STATUS_OK;
5404 /****************************************************************************
5405 Deal with SMB_INFO_SET_EA.
5406 ****************************************************************************/
5408 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5409 const char *pdata,
5410 int total_data,
5411 files_struct *fsp,
5412 const struct smb_filename *smb_fname)
5414 struct ea_list *ea_list = NULL;
5415 TALLOC_CTX *ctx = NULL;
5416 NTSTATUS status = NT_STATUS_OK;
5418 if (total_data < 10) {
5420 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5421 length. They seem to have no effect. Bug #3212. JRA */
5423 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5424 /* We're done. We only get EA info in this call. */
5425 return NT_STATUS_OK;
5428 return NT_STATUS_INVALID_PARAMETER;
5431 if (IVAL(pdata,0) > total_data) {
5432 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5433 IVAL(pdata,0), (unsigned int)total_data));
5434 return NT_STATUS_INVALID_PARAMETER;
5437 ctx = talloc_tos();
5438 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5439 if (!ea_list) {
5440 return NT_STATUS_INVALID_PARAMETER;
5442 status = set_ea(conn, fsp, smb_fname, ea_list);
5444 return status;
5447 /****************************************************************************
5448 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5449 ****************************************************************************/
5451 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5452 const char *pdata,
5453 int total_data,
5454 files_struct *fsp,
5455 const struct smb_filename *smb_fname)
5457 NTSTATUS status = NT_STATUS_OK;
5458 bool delete_on_close;
5459 uint32 dosmode = 0;
5461 if (total_data < 1) {
5462 return NT_STATUS_INVALID_PARAMETER;
5465 if (fsp == NULL) {
5466 return NT_STATUS_INVALID_HANDLE;
5469 delete_on_close = (CVAL(pdata,0) ? True : False);
5470 dosmode = dos_mode(conn, smb_fname);
5472 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5473 "delete_on_close = %u\n",
5474 smb_fname_str_dbg(smb_fname),
5475 (unsigned int)dosmode,
5476 (unsigned int)delete_on_close ));
5478 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5480 if (!NT_STATUS_IS_OK(status)) {
5481 return status;
5484 /* The set is across all open files on this dev/inode pair. */
5485 if (!set_delete_on_close(fsp, delete_on_close,
5486 &conn->server_info->utok)) {
5487 return NT_STATUS_ACCESS_DENIED;
5489 return NT_STATUS_OK;
5492 /****************************************************************************
5493 Deal with SMB_FILE_POSITION_INFORMATION.
5494 ****************************************************************************/
5496 static NTSTATUS smb_file_position_information(connection_struct *conn,
5497 const char *pdata,
5498 int total_data,
5499 files_struct *fsp)
5501 uint64_t position_information;
5503 if (total_data < 8) {
5504 return NT_STATUS_INVALID_PARAMETER;
5507 if (fsp == NULL) {
5508 /* Ignore on pathname based set. */
5509 return NT_STATUS_OK;
5512 position_information = (uint64_t)IVAL(pdata,0);
5513 #ifdef LARGE_SMB_OFF_T
5514 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5515 #else /* LARGE_SMB_OFF_T */
5516 if (IVAL(pdata,4) != 0) {
5517 /* more than 32 bits? */
5518 return NT_STATUS_INVALID_PARAMETER;
5520 #endif /* LARGE_SMB_OFF_T */
5522 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5523 fsp->fsp_name, (double)position_information ));
5524 fsp->fh->position_information = position_information;
5525 return NT_STATUS_OK;
5528 /****************************************************************************
5529 Deal with SMB_FILE_MODE_INFORMATION.
5530 ****************************************************************************/
5532 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5533 const char *pdata,
5534 int total_data)
5536 uint32 mode;
5538 if (total_data < 4) {
5539 return NT_STATUS_INVALID_PARAMETER;
5541 mode = IVAL(pdata,0);
5542 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5543 return NT_STATUS_INVALID_PARAMETER;
5545 return NT_STATUS_OK;
5548 /****************************************************************************
5549 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5550 ****************************************************************************/
5552 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5553 struct smb_request *req,
5554 const char *pdata,
5555 int total_data,
5556 const char *fname)
5558 char *link_target = NULL;
5559 const char *newname = fname;
5560 NTSTATUS status = NT_STATUS_OK;
5561 TALLOC_CTX *ctx = talloc_tos();
5563 /* Set a symbolic link. */
5564 /* Don't allow this if follow links is false. */
5566 if (total_data == 0) {
5567 return NT_STATUS_INVALID_PARAMETER;
5570 if (!lp_symlinks(SNUM(conn))) {
5571 return NT_STATUS_ACCESS_DENIED;
5574 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5575 total_data, STR_TERMINATE);
5577 if (!link_target) {
5578 return NT_STATUS_INVALID_PARAMETER;
5581 /* !widelinks forces the target path to be within the share. */
5582 /* This means we can interpret the target as a pathname. */
5583 if (!lp_widelinks(SNUM(conn))) {
5584 char *rel_name = NULL;
5585 char *last_dirp = NULL;
5587 if (*link_target == '/') {
5588 /* No absolute paths allowed. */
5589 return NT_STATUS_ACCESS_DENIED;
5591 rel_name = talloc_strdup(ctx,newname);
5592 if (!rel_name) {
5593 return NT_STATUS_NO_MEMORY;
5595 last_dirp = strrchr_m(rel_name, '/');
5596 if (last_dirp) {
5597 last_dirp[1] = '\0';
5598 } else {
5599 rel_name = talloc_strdup(ctx,"./");
5600 if (!rel_name) {
5601 return NT_STATUS_NO_MEMORY;
5604 rel_name = talloc_asprintf_append(rel_name,
5605 "%s",
5606 link_target);
5607 if (!rel_name) {
5608 return NT_STATUS_NO_MEMORY;
5611 status = check_name(conn, rel_name);
5612 if (!NT_STATUS_IS_OK(status)) {
5613 return status;
5617 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5618 newname, link_target ));
5620 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5621 return map_nt_error_from_unix(errno);
5624 return NT_STATUS_OK;
5627 /****************************************************************************
5628 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5629 ****************************************************************************/
5631 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5632 struct smb_request *req,
5633 const char *pdata, int total_data,
5634 const struct smb_filename *smb_fname_new)
5636 char *oldname = NULL;
5637 struct smb_filename *smb_fname_old = NULL;
5638 TALLOC_CTX *ctx = talloc_tos();
5639 NTSTATUS status = NT_STATUS_OK;
5641 /* Set a hard link. */
5642 if (total_data == 0) {
5643 return NT_STATUS_INVALID_PARAMETER;
5646 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5647 total_data, STR_TERMINATE, &status);
5648 if (!NT_STATUS_IS_OK(status)) {
5649 return status;
5652 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5653 smb_fname_str_dbg(smb_fname_new), oldname));
5655 status = filename_convert(ctx,
5656 conn,
5657 req->flags2 & FLAGS2_DFS_PATHNAMES,
5658 oldname,
5659 &smb_fname_old,
5660 NULL);
5661 if (!NT_STATUS_IS_OK(status)) {
5662 return status;
5665 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5668 /****************************************************************************
5669 Deal with SMB_FILE_RENAME_INFORMATION.
5670 ****************************************************************************/
5672 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5673 struct smb_request *req,
5674 const char *pdata,
5675 int total_data,
5676 files_struct *fsp,
5677 const char *fname)
5679 bool overwrite;
5680 uint32 root_fid;
5681 uint32 len;
5682 char *newname = NULL;
5683 char *base_name = NULL;
5684 struct smb_filename *smb_fname = NULL;
5685 bool dest_has_wcard = False;
5686 NTSTATUS status = NT_STATUS_OK;
5687 char *p;
5688 TALLOC_CTX *ctx = talloc_tos();
5690 if (total_data < 13) {
5691 return NT_STATUS_INVALID_PARAMETER;
5694 overwrite = (CVAL(pdata,0) ? True : False);
5695 root_fid = IVAL(pdata,4);
5696 len = IVAL(pdata,8);
5698 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5699 return NT_STATUS_INVALID_PARAMETER;
5702 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5703 len, 0, &status,
5704 &dest_has_wcard);
5705 if (!NT_STATUS_IS_OK(status)) {
5706 return status;
5709 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5710 newname));
5712 status = resolve_dfspath_wcard(ctx, conn,
5713 req->flags2 & FLAGS2_DFS_PATHNAMES,
5714 newname,
5715 &newname,
5716 &dest_has_wcard);
5717 if (!NT_STATUS_IS_OK(status)) {
5718 return status;
5721 /* Check the new name has no '/' characters. */
5722 if (strchr_m(newname, '/')) {
5723 return NT_STATUS_NOT_SUPPORTED;
5726 if (fsp && fsp->base_fsp) {
5727 /* newname must be a stream name. */
5728 if (newname[0] != ':') {
5729 return NT_STATUS_NOT_SUPPORTED;
5732 /* Create an smb_fname to call rename_internals_fsp() with. */
5733 status = create_synthetic_smb_fname(talloc_tos(),
5734 fsp->base_fsp->fsp_name,
5735 newname, NULL, &smb_fname);
5736 if (!NT_STATUS_IS_OK(status)) {
5737 goto out;
5741 * Set the original last component, since
5742 * rename_internals_fsp() requires it.
5744 smb_fname->original_lcomp = talloc_strdup(smb_fname, newname);
5745 if (smb_fname->original_lcomp == NULL) {
5746 status = NT_STATUS_NO_MEMORY;
5747 goto out;
5750 /* Create a char * to call rename_internals() with. */
5751 base_name = talloc_asprintf(ctx, "%s%s",
5752 fsp->base_fsp->fsp_name,
5753 newname);
5754 if (!base_name) {
5755 status = NT_STATUS_NO_MEMORY;
5756 goto out;
5758 } else {
5759 /* newname must *not* be a stream name. */
5760 if (newname[0] == ':') {
5761 return NT_STATUS_NOT_SUPPORTED;
5764 /* Create the base directory. */
5765 base_name = talloc_strdup(ctx, fname);
5766 if (!base_name) {
5767 return NT_STATUS_NO_MEMORY;
5769 p = strrchr_m(base_name, '/');
5770 if (p) {
5771 p[1] = '\0';
5772 } else {
5773 base_name = talloc_strdup(ctx, "./");
5774 if (!base_name) {
5775 return NT_STATUS_NO_MEMORY;
5778 /* Append the new name. */
5779 base_name = talloc_asprintf_append(base_name,
5780 "%s",
5781 newname);
5782 if (!base_name) {
5783 return NT_STATUS_NO_MEMORY;
5786 status = unix_convert(ctx, conn, base_name, &smb_fname,
5787 UCF_SAVE_LCOMP);
5789 /* If an error we expect this to be
5790 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5792 if (!NT_STATUS_IS_OK(status)) {
5793 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5794 status)) {
5795 goto out;
5797 /* Create an smb_fname to call rename_internals_fsp() */
5798 status = create_synthetic_smb_fname(talloc_tos(),
5799 base_name, NULL,
5800 NULL, &smb_fname);
5801 if (!NT_STATUS_IS_OK(status)) {
5802 goto out;
5808 if (fsp) {
5809 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5810 fsp->fnum, fsp->fsp_name, base_name ));
5811 status = rename_internals_fsp(conn, fsp, smb_fname, 0,
5812 overwrite);
5813 } else {
5814 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5815 fname, base_name ));
5816 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5817 overwrite, False, dest_has_wcard,
5818 FILE_WRITE_ATTRIBUTES);
5820 out:
5821 TALLOC_FREE(smb_fname);
5822 return status;
5825 /****************************************************************************
5826 Deal with SMB_SET_POSIX_ACL.
5827 ****************************************************************************/
5829 #if defined(HAVE_POSIX_ACLS)
5830 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5831 const char *pdata,
5832 int total_data,
5833 files_struct *fsp,
5834 const char *fname,
5835 SMB_STRUCT_STAT *psbuf)
5837 uint16 posix_acl_version;
5838 uint16 num_file_acls;
5839 uint16 num_def_acls;
5840 bool valid_file_acls = True;
5841 bool valid_def_acls = True;
5843 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5844 return NT_STATUS_INVALID_PARAMETER;
5846 posix_acl_version = SVAL(pdata,0);
5847 num_file_acls = SVAL(pdata,2);
5848 num_def_acls = SVAL(pdata,4);
5850 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5851 valid_file_acls = False;
5852 num_file_acls = 0;
5855 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5856 valid_def_acls = False;
5857 num_def_acls = 0;
5860 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5861 return NT_STATUS_INVALID_PARAMETER;
5864 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5865 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5866 return NT_STATUS_INVALID_PARAMETER;
5869 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5870 fname ? fname : fsp->fsp_name,
5871 (unsigned int)num_file_acls,
5872 (unsigned int)num_def_acls));
5874 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5875 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5876 return map_nt_error_from_unix(errno);
5879 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5880 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5881 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5882 return map_nt_error_from_unix(errno);
5884 return NT_STATUS_OK;
5886 #endif
5888 /****************************************************************************
5889 Deal with SMB_SET_POSIX_LOCK.
5890 ****************************************************************************/
5892 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5893 struct smb_request *req,
5894 const char *pdata,
5895 int total_data,
5896 files_struct *fsp)
5898 uint64_t count;
5899 uint64_t offset;
5900 uint32 lock_pid;
5901 bool blocking_lock = False;
5902 enum brl_type lock_type;
5904 NTSTATUS status = NT_STATUS_OK;
5906 if (fsp == NULL || fsp->fh->fd == -1) {
5907 return NT_STATUS_INVALID_HANDLE;
5910 if (total_data != POSIX_LOCK_DATA_SIZE) {
5911 return NT_STATUS_INVALID_PARAMETER;
5914 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5915 case POSIX_LOCK_TYPE_READ:
5916 lock_type = READ_LOCK;
5917 break;
5918 case POSIX_LOCK_TYPE_WRITE:
5919 /* Return the right POSIX-mappable error code for files opened read-only. */
5920 if (!fsp->can_write) {
5921 return NT_STATUS_INVALID_HANDLE;
5923 lock_type = WRITE_LOCK;
5924 break;
5925 case POSIX_LOCK_TYPE_UNLOCK:
5926 lock_type = UNLOCK_LOCK;
5927 break;
5928 default:
5929 return NT_STATUS_INVALID_PARAMETER;
5932 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5933 blocking_lock = False;
5934 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5935 blocking_lock = True;
5936 } else {
5937 return NT_STATUS_INVALID_PARAMETER;
5940 if (!lp_blocking_locks(SNUM(conn))) {
5941 blocking_lock = False;
5944 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5945 #if defined(HAVE_LONGLONG)
5946 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5947 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5948 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5949 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5950 #else /* HAVE_LONGLONG */
5951 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5952 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5953 #endif /* HAVE_LONGLONG */
5955 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5956 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5957 fsp->fsp_name,
5958 (unsigned int)lock_type,
5959 (unsigned int)lock_pid,
5960 (double)count,
5961 (double)offset ));
5963 if (lock_type == UNLOCK_LOCK) {
5964 status = do_unlock(smbd_messaging_context(),
5965 fsp,
5966 lock_pid,
5967 count,
5968 offset,
5969 POSIX_LOCK);
5970 } else {
5971 uint32 block_smbpid;
5973 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5974 fsp,
5975 lock_pid,
5976 count,
5977 offset,
5978 lock_type,
5979 POSIX_LOCK,
5980 blocking_lock,
5981 &status,
5982 &block_smbpid,
5983 NULL);
5985 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5987 * A blocking lock was requested. Package up
5988 * this smb into a queued request and push it
5989 * onto the blocking lock queue.
5991 if(push_blocking_lock_request(br_lck,
5992 req,
5993 fsp,
5994 -1, /* infinite timeout. */
5996 lock_pid,
5997 lock_type,
5998 POSIX_LOCK,
5999 offset,
6000 count,
6001 block_smbpid)) {
6002 TALLOC_FREE(br_lck);
6003 return status;
6006 TALLOC_FREE(br_lck);
6009 return status;
6012 /****************************************************************************
6013 Deal with SMB_INFO_STANDARD.
6014 ****************************************************************************/
6016 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6017 const char *pdata,
6018 int total_data,
6019 files_struct *fsp,
6020 const struct smb_filename *smb_fname)
6022 struct smb_file_time ft;
6023 ZERO_STRUCT(ft);
6025 if (total_data < 12) {
6026 return NT_STATUS_INVALID_PARAMETER;
6029 /* create time */
6030 ft.create_time = interpret_long_date(pdata);
6032 /* access time */
6033 ft.atime = interpret_long_date(pdata + 8);
6035 /* write time */
6036 ft.mtime = interpret_long_date(pdata + 16);
6038 DEBUG(10,("smb_set_info_standard: file %s\n",
6039 smb_fname_str_dbg(smb_fname)));
6041 return smb_set_file_time(conn, fsp, smb_fname, &ft, true);
6044 /****************************************************************************
6045 Deal with SMB_SET_FILE_BASIC_INFO.
6046 ****************************************************************************/
6048 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6049 const char *pdata,
6050 int total_data,
6051 files_struct *fsp,
6052 const struct smb_filename *smb_fname)
6054 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6055 struct timespec write_time;
6056 struct timespec changed_time;
6057 struct smb_file_time ft;
6058 uint32 dosmode = 0;
6059 NTSTATUS status = NT_STATUS_OK;
6060 bool setting_write_time = true;
6062 ZERO_STRUCT(ft);
6064 if (total_data < 36) {
6065 return NT_STATUS_INVALID_PARAMETER;
6068 /* Set the attributes */
6069 dosmode = IVAL(pdata,32);
6070 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6071 if (!NT_STATUS_IS_OK(status)) {
6072 return status;
6075 /* access time */
6076 ft.atime = interpret_long_date(pdata+8);
6078 write_time = interpret_long_date(pdata+16);
6079 changed_time = interpret_long_date(pdata+24);
6081 /* mtime */
6082 ft.mtime = timespec_min(&write_time, &changed_time);
6084 /* create time */
6085 ft.create_time = interpret_long_date(pdata);
6087 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
6088 !null_timespec(write_time)) {
6089 ft.mtime = write_time;
6092 /* Prefer a defined time to an undefined one. */
6093 if (null_timespec(ft.mtime)) {
6094 if (null_timespec(write_time)) {
6095 ft.mtime = changed_time;
6096 setting_write_time = false;
6097 } else {
6098 ft.mtime = write_time;
6102 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6103 smb_fname_str_dbg(smb_fname)));
6105 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6106 setting_write_time);
6109 /****************************************************************************
6110 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6111 ****************************************************************************/
6113 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6114 struct smb_request *req,
6115 const char *pdata,
6116 int total_data,
6117 files_struct *fsp,
6118 struct smb_filename *smb_fname)
6120 uint64_t allocation_size = 0;
6121 NTSTATUS status = NT_STATUS_OK;
6122 files_struct *new_fsp = NULL;
6124 if (!VALID_STAT(smb_fname->st)) {
6125 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6128 if (total_data < 8) {
6129 return NT_STATUS_INVALID_PARAMETER;
6132 allocation_size = (uint64_t)IVAL(pdata,0);
6133 #ifdef LARGE_SMB_OFF_T
6134 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6135 #else /* LARGE_SMB_OFF_T */
6136 if (IVAL(pdata,4) != 0) {
6137 /* more than 32 bits? */
6138 return NT_STATUS_INVALID_PARAMETER;
6140 #endif /* LARGE_SMB_OFF_T */
6142 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6143 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6144 (double)allocation_size));
6146 if (allocation_size) {
6147 allocation_size = smb_roundup(conn, allocation_size);
6150 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6151 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6152 (double)allocation_size));
6154 if (fsp && fsp->fh->fd != -1) {
6155 /* Open file handle. */
6156 /* Only change if needed. */
6157 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6158 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6159 return map_nt_error_from_unix(errno);
6162 /* But always update the time. */
6164 * This is equivalent to a write. Ensure it's seen immediately
6165 * if there are no pending writes.
6167 trigger_write_time_update_immediate(fsp);
6168 return NT_STATUS_OK;
6171 /* Pathname or stat or directory file. */
6172 status = SMB_VFS_CREATE_FILE(
6173 conn, /* conn */
6174 req, /* req */
6175 0, /* root_dir_fid */
6176 smb_fname, /* fname */
6177 FILE_WRITE_DATA, /* access_mask */
6178 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6179 FILE_SHARE_DELETE),
6180 FILE_OPEN, /* create_disposition*/
6181 0, /* create_options */
6182 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6183 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6184 0, /* allocation_size */
6185 NULL, /* sd */
6186 NULL, /* ea_list */
6187 &new_fsp, /* result */
6188 NULL); /* pinfo */
6190 if (!NT_STATUS_IS_OK(status)) {
6191 /* NB. We check for open_was_deferred in the caller. */
6192 return status;
6195 /* Only change if needed. */
6196 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6197 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6198 status = map_nt_error_from_unix(errno);
6199 close_file(req, new_fsp, NORMAL_CLOSE);
6200 return status;
6204 /* Changing the allocation size should set the last mod time. */
6206 * This is equivalent to a write. Ensure it's seen immediately
6207 * if there are no pending writes.
6209 trigger_write_time_update_immediate(new_fsp);
6211 close_file(req, new_fsp, NORMAL_CLOSE);
6212 return NT_STATUS_OK;
6215 /****************************************************************************
6216 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6217 ****************************************************************************/
6219 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6220 struct smb_request *req,
6221 const char *pdata,
6222 int total_data,
6223 files_struct *fsp,
6224 const struct smb_filename *smb_fname)
6226 SMB_OFF_T size;
6228 if (total_data < 8) {
6229 return NT_STATUS_INVALID_PARAMETER;
6232 size = IVAL(pdata,0);
6233 #ifdef LARGE_SMB_OFF_T
6234 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6235 #else /* LARGE_SMB_OFF_T */
6236 if (IVAL(pdata,4) != 0) {
6237 /* more than 32 bits? */
6238 return NT_STATUS_INVALID_PARAMETER;
6240 #endif /* LARGE_SMB_OFF_T */
6241 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6242 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6243 (double)size));
6245 return smb_set_file_size(conn, req,
6246 fsp,
6247 smb_fname,
6248 &smb_fname->st,
6249 size);
6252 /****************************************************************************
6253 Allow a UNIX info mknod.
6254 ****************************************************************************/
6256 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6257 const char *pdata,
6258 int total_data,
6259 const struct smb_filename *smb_fname)
6261 uint32 file_type = IVAL(pdata,56);
6262 #if defined(HAVE_MAKEDEV)
6263 uint32 dev_major = IVAL(pdata,60);
6264 uint32 dev_minor = IVAL(pdata,68);
6265 #endif
6266 SMB_DEV_T dev = (SMB_DEV_T)0;
6267 uint32 raw_unixmode = IVAL(pdata,84);
6268 NTSTATUS status;
6269 mode_t unixmode;
6271 if (total_data < 100) {
6272 return NT_STATUS_INVALID_PARAMETER;
6275 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6276 PERM_NEW_FILE, &unixmode);
6277 if (!NT_STATUS_IS_OK(status)) {
6278 return status;
6281 #if defined(HAVE_MAKEDEV)
6282 dev = makedev(dev_major, dev_minor);
6283 #endif
6285 switch (file_type) {
6286 #if defined(S_IFIFO)
6287 case UNIX_TYPE_FIFO:
6288 unixmode |= S_IFIFO;
6289 break;
6290 #endif
6291 #if defined(S_IFSOCK)
6292 case UNIX_TYPE_SOCKET:
6293 unixmode |= S_IFSOCK;
6294 break;
6295 #endif
6296 #if defined(S_IFCHR)
6297 case UNIX_TYPE_CHARDEV:
6298 unixmode |= S_IFCHR;
6299 break;
6300 #endif
6301 #if defined(S_IFBLK)
6302 case UNIX_TYPE_BLKDEV:
6303 unixmode |= S_IFBLK;
6304 break;
6305 #endif
6306 default:
6307 return NT_STATUS_INVALID_PARAMETER;
6310 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6311 "%.0f mode 0%o for file %s\n", (double)dev,
6312 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6314 /* Ok - do the mknod. */
6315 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6316 return map_nt_error_from_unix(errno);
6319 /* If any of the other "set" calls fail we
6320 * don't want to end up with a half-constructed mknod.
6323 if (lp_inherit_perms(SNUM(conn))) {
6324 char *parent;
6325 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6326 &parent, NULL)) {
6327 return NT_STATUS_NO_MEMORY;
6329 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6330 unixmode);
6331 TALLOC_FREE(parent);
6334 return NT_STATUS_OK;
6337 /****************************************************************************
6338 Deal with SMB_SET_FILE_UNIX_BASIC.
6339 ****************************************************************************/
6341 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6342 struct smb_request *req,
6343 const char *pdata,
6344 int total_data,
6345 files_struct *fsp,
6346 const struct smb_filename *smb_fname)
6348 struct smb_file_time ft;
6349 uint32 raw_unixmode;
6350 mode_t unixmode;
6351 SMB_OFF_T size = 0;
6352 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6353 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6354 NTSTATUS status = NT_STATUS_OK;
6355 bool delete_on_fail = False;
6356 enum perm_type ptype;
6357 files_struct *all_fsps = NULL;
6358 bool modify_mtime = true;
6359 struct file_id id;
6360 SMB_STRUCT_STAT sbuf;
6362 ZERO_STRUCT(ft);
6364 if (total_data < 100) {
6365 return NT_STATUS_INVALID_PARAMETER;
6368 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6369 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6370 size=IVAL(pdata,0); /* first 8 Bytes are size */
6371 #ifdef LARGE_SMB_OFF_T
6372 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6373 #else /* LARGE_SMB_OFF_T */
6374 if (IVAL(pdata,4) != 0) {
6375 /* more than 32 bits? */
6376 return NT_STATUS_INVALID_PARAMETER;
6378 #endif /* LARGE_SMB_OFF_T */
6381 ft.atime = interpret_long_date(pdata+24); /* access_time */
6382 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6383 set_owner = (uid_t)IVAL(pdata,40);
6384 set_grp = (gid_t)IVAL(pdata,48);
6385 raw_unixmode = IVAL(pdata,84);
6387 if (VALID_STAT(smb_fname->st)) {
6388 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6389 ptype = PERM_EXISTING_DIR;
6390 } else {
6391 ptype = PERM_EXISTING_FILE;
6393 } else {
6394 ptype = PERM_NEW_FILE;
6397 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6398 ptype, &unixmode);
6399 if (!NT_STATUS_IS_OK(status)) {
6400 return status;
6403 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6404 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6405 smb_fname_str_dbg(smb_fname), (double)size,
6406 (unsigned int)set_owner, (unsigned int)set_grp,
6407 (int)raw_unixmode));
6409 sbuf = smb_fname->st;
6411 if (!VALID_STAT(sbuf)) {
6412 struct smb_filename *smb_fname_tmp = NULL;
6414 * The only valid use of this is to create character and block
6415 * devices, and named pipes. This is deprecated (IMHO) and
6416 * a new info level should be used for mknod. JRA.
6419 status = smb_unix_mknod(conn,
6420 pdata,
6421 total_data,
6422 smb_fname);
6423 if (!NT_STATUS_IS_OK(status)) {
6424 return status;
6427 status = copy_smb_filename(talloc_tos(), smb_fname,
6428 &smb_fname_tmp);
6429 if (!NT_STATUS_IS_OK(status)) {
6430 return status;
6433 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6434 status = map_nt_error_from_unix(errno);
6435 TALLOC_FREE(smb_fname_tmp);
6436 SMB_VFS_UNLINK(conn, smb_fname);
6437 return status;
6440 sbuf = smb_fname_tmp->st;
6441 TALLOC_FREE(smb_fname_tmp);
6443 /* Ensure we don't try and change anything else. */
6444 raw_unixmode = SMB_MODE_NO_CHANGE;
6445 size = get_file_size_stat(&sbuf);
6446 ft.atime = sbuf.st_ex_atime;
6447 ft.mtime = sbuf.st_ex_mtime;
6449 * We continue here as we might want to change the
6450 * owner uid/gid.
6452 delete_on_fail = True;
6455 #if 1
6456 /* Horrible backwards compatibility hack as an old server bug
6457 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6458 * */
6460 if (!size) {
6461 size = get_file_size_stat(&sbuf);
6463 #endif
6466 * Deal with the UNIX specific mode set.
6469 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6470 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6471 "setting mode 0%o for file %s\n",
6472 (unsigned int)unixmode,
6473 smb_fname_str_dbg(smb_fname)));
6474 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6475 return map_nt_error_from_unix(errno);
6480 * Deal with the UNIX specific uid set.
6483 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6484 (sbuf.st_ex_uid != set_owner)) {
6485 int ret;
6487 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6488 "changing owner %u for path %s\n",
6489 (unsigned int)set_owner,
6490 smb_fname_str_dbg(smb_fname)));
6492 if (S_ISLNK(sbuf.st_ex_mode)) {
6493 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6494 set_owner, (gid_t)-1);
6495 } else {
6496 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6497 set_owner, (gid_t)-1);
6500 if (ret != 0) {
6501 status = map_nt_error_from_unix(errno);
6502 if (delete_on_fail) {
6503 SMB_VFS_UNLINK(conn, smb_fname);
6505 return status;
6510 * Deal with the UNIX specific gid set.
6513 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6514 (sbuf.st_ex_gid != set_grp)) {
6515 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6516 "changing group %u for file %s\n",
6517 (unsigned int)set_owner,
6518 smb_fname_str_dbg(smb_fname)));
6519 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6520 set_grp) != 0) {
6521 status = map_nt_error_from_unix(errno);
6522 if (delete_on_fail) {
6523 SMB_VFS_UNLINK(conn, smb_fname);
6525 return status;
6529 /* Deal with any size changes. */
6531 status = smb_set_file_size(conn, req,
6532 fsp,
6533 smb_fname,
6534 &sbuf,
6535 size);
6536 if (!NT_STATUS_IS_OK(status)) {
6537 return status;
6540 /* Deal with any time changes. */
6541 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6542 /* No change, don't cancel anything. */
6543 return status;
6546 id = vfs_file_id_from_sbuf(conn, &sbuf);
6547 for(all_fsps = file_find_di_first(id); all_fsps;
6548 all_fsps = file_find_di_next(all_fsps)) {
6550 * We're setting the time explicitly for UNIX.
6551 * Cancel any pending changes over all handles.
6553 all_fsps->update_write_time_on_close = false;
6554 TALLOC_FREE(all_fsps->update_write_time_event);
6558 * Override the "setting_write_time"
6559 * parameter here as it almost does what
6560 * we need. Just remember if we modified
6561 * mtime and send the notify ourselves.
6563 if (null_timespec(ft.mtime)) {
6564 modify_mtime = false;
6567 status = smb_set_file_time(conn,
6568 fsp,
6569 smb_fname,
6570 &ft,
6571 false);
6572 if (modify_mtime) {
6573 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6574 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6576 return status;
6579 /****************************************************************************
6580 Deal with SMB_SET_FILE_UNIX_INFO2.
6581 ****************************************************************************/
6583 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6584 struct smb_request *req,
6585 const char *pdata,
6586 int total_data,
6587 files_struct *fsp,
6588 const struct smb_filename *smb_fname)
6590 NTSTATUS status;
6591 uint32 smb_fflags;
6592 uint32 smb_fmask;
6594 if (total_data < 116) {
6595 return NT_STATUS_INVALID_PARAMETER;
6598 /* Start by setting all the fields that are common between UNIX_BASIC
6599 * and UNIX_INFO2.
6601 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6602 fsp, smb_fname);
6603 if (!NT_STATUS_IS_OK(status)) {
6604 return status;
6607 smb_fflags = IVAL(pdata, 108);
6608 smb_fmask = IVAL(pdata, 112);
6610 /* NB: We should only attempt to alter the file flags if the client
6611 * sends a non-zero mask.
6613 if (smb_fmask != 0) {
6614 int stat_fflags = 0;
6616 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6617 smb_fmask, &stat_fflags)) {
6618 /* Client asked to alter a flag we don't understand. */
6619 return NT_STATUS_INVALID_PARAMETER;
6622 if (fsp && fsp->fh->fd != -1) {
6623 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6624 return NT_STATUS_NOT_SUPPORTED;
6625 } else {
6626 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6627 stat_fflags) != 0) {
6628 return map_nt_error_from_unix(errno);
6633 /* XXX: need to add support for changing the create_time here. You
6634 * can do this for paths on Darwin with setattrlist(2). The right way
6635 * to hook this up is probably by extending the VFS utimes interface.
6638 return NT_STATUS_OK;
6641 /****************************************************************************
6642 Create a directory with POSIX semantics.
6643 ****************************************************************************/
6645 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6646 struct smb_request *req,
6647 char **ppdata,
6648 int total_data,
6649 const char *fname,
6650 SMB_STRUCT_STAT *psbuf,
6651 int *pdata_return_size)
6653 struct smb_filename *smb_fname;
6654 NTSTATUS status = NT_STATUS_OK;
6655 uint32 raw_unixmode = 0;
6656 uint32 mod_unixmode = 0;
6657 mode_t unixmode = (mode_t)0;
6658 files_struct *fsp = NULL;
6659 uint16 info_level_return = 0;
6660 int info;
6661 char *pdata = *ppdata;
6663 if (total_data < 18) {
6664 return NT_STATUS_INVALID_PARAMETER;
6667 raw_unixmode = IVAL(pdata,8);
6668 /* Next 4 bytes are not yet defined. */
6670 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6671 if (!NT_STATUS_IS_OK(status)) {
6672 return status;
6675 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6677 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6678 fname, (unsigned int)unixmode ));
6680 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6681 &smb_fname);
6682 if (!NT_STATUS_IS_OK(status)) {
6683 return status;
6686 status = SMB_VFS_CREATE_FILE(
6687 conn, /* conn */
6688 req, /* req */
6689 0, /* root_dir_fid */
6690 smb_fname, /* fname */
6691 FILE_READ_ATTRIBUTES, /* access_mask */
6692 FILE_SHARE_NONE, /* share_access */
6693 FILE_CREATE, /* create_disposition*/
6694 FILE_DIRECTORY_FILE, /* create_options */
6695 mod_unixmode, /* file_attributes */
6696 0, /* oplock_request */
6697 0, /* allocation_size */
6698 NULL, /* sd */
6699 NULL, /* ea_list */
6700 &fsp, /* result */
6701 &info); /* pinfo */
6703 *psbuf = smb_fname->st;
6704 TALLOC_FREE(smb_fname);
6706 if (NT_STATUS_IS_OK(status)) {
6707 close_file(req, fsp, NORMAL_CLOSE);
6710 info_level_return = SVAL(pdata,16);
6712 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6713 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6714 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6715 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6716 } else {
6717 *pdata_return_size = 12;
6720 /* Realloc the data size */
6721 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6722 if (*ppdata == NULL) {
6723 *pdata_return_size = 0;
6724 return NT_STATUS_NO_MEMORY;
6726 pdata = *ppdata;
6728 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6729 SSVAL(pdata,2,0); /* No fnum. */
6730 SIVAL(pdata,4,info); /* Was directory created. */
6732 switch (info_level_return) {
6733 case SMB_QUERY_FILE_UNIX_BASIC:
6734 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6735 SSVAL(pdata,10,0); /* Padding. */
6736 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6737 break;
6738 case SMB_QUERY_FILE_UNIX_INFO2:
6739 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6740 SSVAL(pdata,10,0); /* Padding. */
6741 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6742 break;
6743 default:
6744 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6745 SSVAL(pdata,10,0); /* Padding. */
6746 break;
6749 return status;
6752 /****************************************************************************
6753 Open/Create a file with POSIX semantics.
6754 ****************************************************************************/
6756 static NTSTATUS smb_posix_open(connection_struct *conn,
6757 struct smb_request *req,
6758 char **ppdata,
6759 int total_data,
6760 const char *fname,
6761 SMB_STRUCT_STAT *psbuf,
6762 int *pdata_return_size)
6764 struct smb_filename *smb_fname = NULL;
6765 bool extended_oplock_granted = False;
6766 char *pdata = *ppdata;
6767 uint32 flags = 0;
6768 uint32 wire_open_mode = 0;
6769 uint32 raw_unixmode = 0;
6770 uint32 mod_unixmode = 0;
6771 uint32 create_disp = 0;
6772 uint32 access_mask = 0;
6773 uint32 create_options = 0;
6774 NTSTATUS status = NT_STATUS_OK;
6775 mode_t unixmode = (mode_t)0;
6776 files_struct *fsp = NULL;
6777 int oplock_request = 0;
6778 int info = 0;
6779 uint16 info_level_return = 0;
6781 if (total_data < 18) {
6782 return NT_STATUS_INVALID_PARAMETER;
6785 flags = IVAL(pdata,0);
6786 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6787 if (oplock_request) {
6788 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6791 wire_open_mode = IVAL(pdata,4);
6793 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6794 return smb_posix_mkdir(conn, req,
6795 ppdata,
6796 total_data,
6797 fname,
6798 psbuf,
6799 pdata_return_size);
6802 switch (wire_open_mode & SMB_ACCMODE) {
6803 case SMB_O_RDONLY:
6804 access_mask = FILE_READ_DATA;
6805 break;
6806 case SMB_O_WRONLY:
6807 access_mask = FILE_WRITE_DATA;
6808 break;
6809 case SMB_O_RDWR:
6810 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6811 break;
6812 default:
6813 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6814 (unsigned int)wire_open_mode ));
6815 return NT_STATUS_INVALID_PARAMETER;
6818 wire_open_mode &= ~SMB_ACCMODE;
6820 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6821 create_disp = FILE_CREATE;
6822 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6823 create_disp = FILE_OVERWRITE_IF;
6824 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6825 create_disp = FILE_OPEN_IF;
6826 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6827 create_disp = FILE_OPEN;
6828 } else {
6829 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6830 (unsigned int)wire_open_mode ));
6831 return NT_STATUS_INVALID_PARAMETER;
6834 raw_unixmode = IVAL(pdata,8);
6835 /* Next 4 bytes are not yet defined. */
6837 status = unix_perms_from_wire(conn,
6838 psbuf,
6839 raw_unixmode,
6840 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6841 &unixmode);
6843 if (!NT_STATUS_IS_OK(status)) {
6844 return status;
6847 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6849 if (wire_open_mode & SMB_O_SYNC) {
6850 create_options |= FILE_WRITE_THROUGH;
6852 if (wire_open_mode & SMB_O_APPEND) {
6853 access_mask |= FILE_APPEND_DATA;
6855 if (wire_open_mode & SMB_O_DIRECT) {
6856 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6859 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6860 fname,
6861 (unsigned int)wire_open_mode,
6862 (unsigned int)unixmode ));
6864 status = create_synthetic_smb_fname_split(talloc_tos(), fname, psbuf,
6865 &smb_fname);
6866 if (!NT_STATUS_IS_OK(status)) {
6867 return status;
6870 status = SMB_VFS_CREATE_FILE(
6871 conn, /* conn */
6872 req, /* req */
6873 0, /* root_dir_fid */
6874 smb_fname, /* fname */
6875 access_mask, /* access_mask */
6876 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6877 FILE_SHARE_DELETE),
6878 create_disp, /* create_disposition*/
6879 FILE_NON_DIRECTORY_FILE, /* create_options */
6880 mod_unixmode, /* file_attributes */
6881 oplock_request, /* oplock_request */
6882 0, /* allocation_size */
6883 NULL, /* sd */
6884 NULL, /* ea_list */
6885 &fsp, /* result */
6886 &info); /* pinfo */
6888 *psbuf = smb_fname->st;
6889 TALLOC_FREE(smb_fname);
6891 if (!NT_STATUS_IS_OK(status)) {
6892 return status;
6895 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6896 extended_oplock_granted = True;
6899 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6900 extended_oplock_granted = True;
6903 info_level_return = SVAL(pdata,16);
6905 /* Allocate the correct return size. */
6907 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6908 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6909 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6910 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6911 } else {
6912 *pdata_return_size = 12;
6915 /* Realloc the data size */
6916 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6917 if (*ppdata == NULL) {
6918 close_file(req, fsp, ERROR_CLOSE);
6919 *pdata_return_size = 0;
6920 return NT_STATUS_NO_MEMORY;
6922 pdata = *ppdata;
6924 if (extended_oplock_granted) {
6925 if (flags & REQUEST_BATCH_OPLOCK) {
6926 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6927 } else {
6928 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6930 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6931 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6932 } else {
6933 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6936 SSVAL(pdata,2,fsp->fnum);
6937 SIVAL(pdata,4,info); /* Was file created etc. */
6939 switch (info_level_return) {
6940 case SMB_QUERY_FILE_UNIX_BASIC:
6941 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6942 SSVAL(pdata,10,0); /* padding. */
6943 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6944 break;
6945 case SMB_QUERY_FILE_UNIX_INFO2:
6946 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6947 SSVAL(pdata,10,0); /* padding. */
6948 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6949 break;
6950 default:
6951 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6952 SSVAL(pdata,10,0); /* padding. */
6953 break;
6955 return NT_STATUS_OK;
6958 /****************************************************************************
6959 Delete a file with POSIX semantics.
6960 ****************************************************************************/
6962 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6963 struct smb_request *req,
6964 const char *pdata,
6965 int total_data,
6966 struct smb_filename *smb_fname)
6968 NTSTATUS status = NT_STATUS_OK;
6969 files_struct *fsp = NULL;
6970 uint16 flags = 0;
6971 char del = 1;
6972 int info = 0;
6973 int create_options = 0;
6974 int i;
6975 struct share_mode_lock *lck = NULL;
6977 if (total_data < 2) {
6978 return NT_STATUS_INVALID_PARAMETER;
6981 flags = SVAL(pdata,0);
6983 if (!VALID_STAT(smb_fname->st)) {
6984 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6987 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6988 !VALID_STAT_OF_DIR(smb_fname->st)) {
6989 return NT_STATUS_NOT_A_DIRECTORY;
6992 DEBUG(10,("smb_posix_unlink: %s %s\n",
6993 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6994 smb_fname_str_dbg(smb_fname)));
6996 if (VALID_STAT_OF_DIR(smb_fname->st)) {
6997 create_options |= FILE_DIRECTORY_FILE;
7000 status = SMB_VFS_CREATE_FILE(
7001 conn, /* conn */
7002 req, /* req */
7003 0, /* root_dir_fid */
7004 smb_fname, /* fname */
7005 DELETE_ACCESS, /* access_mask */
7006 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7007 FILE_SHARE_DELETE),
7008 FILE_OPEN, /* create_disposition*/
7009 create_options, /* create_options */
7010 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7011 0, /* oplock_request */
7012 0, /* allocation_size */
7013 NULL, /* sd */
7014 NULL, /* ea_list */
7015 &fsp, /* result */
7016 &info); /* pinfo */
7018 if (!NT_STATUS_IS_OK(status)) {
7019 return status;
7023 * Don't lie to client. If we can't really delete due to
7024 * non-POSIX opens return SHARING_VIOLATION.
7027 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7028 NULL);
7029 if (lck == NULL) {
7030 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7031 "lock for file %s\n", fsp->fsp_name));
7032 close_file(req, fsp, NORMAL_CLOSE);
7033 return NT_STATUS_INVALID_PARAMETER;
7037 * See if others still have the file open. If this is the case, then
7038 * don't delete. If all opens are POSIX delete we can set the delete
7039 * on close disposition.
7041 for (i=0; i<lck->num_share_modes; i++) {
7042 struct share_mode_entry *e = &lck->share_modes[i];
7043 if (is_valid_share_mode_entry(e)) {
7044 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7045 continue;
7047 /* Fail with sharing violation. */
7048 close_file(req, fsp, NORMAL_CLOSE);
7049 TALLOC_FREE(lck);
7050 return NT_STATUS_SHARING_VIOLATION;
7055 * Set the delete on close.
7057 status = smb_set_file_disposition_info(conn,
7058 &del,
7060 fsp,
7061 smb_fname);
7063 if (!NT_STATUS_IS_OK(status)) {
7064 close_file(req, fsp, NORMAL_CLOSE);
7065 TALLOC_FREE(lck);
7066 return status;
7068 TALLOC_FREE(lck);
7069 return close_file(req, fsp, NORMAL_CLOSE);
7072 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7073 struct smb_request *req,
7074 TALLOC_CTX *mem_ctx,
7075 uint16_t info_level,
7076 files_struct *fsp,
7077 struct smb_filename *smb_fname,
7078 char **ppdata, int total_data,
7079 int *ret_data_size)
7081 char *pdata = *ppdata;
7082 SMB_STRUCT_STAT sbuf;
7083 char *fname = NULL;
7084 NTSTATUS status = NT_STATUS_OK;
7085 int data_return_size = 0;
7087 *ret_data_size = 0;
7089 /* Set sbuf for use below. */
7090 sbuf = smb_fname->st;
7092 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7093 return NT_STATUS_INVALID_LEVEL;
7096 if (!CAN_WRITE(conn)) {
7097 /* Allow POSIX opens. The open path will deny
7098 * any non-readonly opens. */
7099 if (info_level != SMB_POSIX_PATH_OPEN) {
7100 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7104 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
7105 if (!NT_STATUS_IS_OK(status)) {
7106 return status;
7109 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d totdata=%d\n",
7110 fname, fsp ? fsp->fnum : -1, info_level, total_data));
7112 switch (info_level) {
7114 case SMB_INFO_STANDARD:
7116 status = smb_set_info_standard(conn,
7117 pdata,
7118 total_data,
7119 fsp,
7120 smb_fname);
7121 break;
7124 case SMB_INFO_SET_EA:
7126 status = smb_info_set_ea(conn,
7127 pdata,
7128 total_data,
7129 fsp,
7130 smb_fname);
7131 break;
7134 case SMB_SET_FILE_BASIC_INFO:
7135 case SMB_FILE_BASIC_INFORMATION:
7137 status = smb_set_file_basic_info(conn,
7138 pdata,
7139 total_data,
7140 fsp,
7141 smb_fname);
7142 break;
7145 case SMB_FILE_ALLOCATION_INFORMATION:
7146 case SMB_SET_FILE_ALLOCATION_INFO:
7148 status = smb_set_file_allocation_info(conn, req,
7149 pdata,
7150 total_data,
7151 fsp,
7152 smb_fname);
7153 break;
7156 case SMB_FILE_END_OF_FILE_INFORMATION:
7157 case SMB_SET_FILE_END_OF_FILE_INFO:
7159 status = smb_set_file_end_of_file_info(conn, req,
7160 pdata,
7161 total_data,
7162 fsp,
7163 smb_fname);
7164 break;
7167 case SMB_FILE_DISPOSITION_INFORMATION:
7168 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7170 #if 0
7171 /* JRA - We used to just ignore this on a path ?
7172 * Shouldn't this be invalid level on a pathname
7173 * based call ?
7175 if (tran_call != TRANSACT2_SETFILEINFO) {
7176 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7178 #endif
7179 status = smb_set_file_disposition_info(conn,
7180 pdata,
7181 total_data,
7182 fsp,
7183 smb_fname);
7184 break;
7187 case SMB_FILE_POSITION_INFORMATION:
7189 status = smb_file_position_information(conn,
7190 pdata,
7191 total_data,
7192 fsp);
7193 break;
7196 /* From tridge Samba4 :
7197 * MODE_INFORMATION in setfileinfo (I have no
7198 * idea what "mode information" on a file is - it takes a value of 0,
7199 * 2, 4 or 6. What could it be?).
7202 case SMB_FILE_MODE_INFORMATION:
7204 status = smb_file_mode_information(conn,
7205 pdata,
7206 total_data);
7207 break;
7211 * CIFS UNIX extensions.
7214 case SMB_SET_FILE_UNIX_BASIC:
7216 status = smb_set_file_unix_basic(conn, req,
7217 pdata,
7218 total_data,
7219 fsp,
7220 smb_fname);
7221 break;
7224 case SMB_SET_FILE_UNIX_INFO2:
7226 status = smb_set_file_unix_info2(conn, req,
7227 pdata,
7228 total_data,
7229 fsp,
7230 smb_fname);
7231 break;
7234 case SMB_SET_FILE_UNIX_LINK:
7236 if (fsp) {
7237 /* We must have a pathname for this. */
7238 return NT_STATUS_INVALID_LEVEL;
7240 status = smb_set_file_unix_link(conn, req, pdata,
7241 total_data, fname);
7242 break;
7245 case SMB_SET_FILE_UNIX_HLINK:
7247 if (fsp || smb_fname == NULL) {
7248 /* We must have a pathname for this. */
7249 return NT_STATUS_INVALID_LEVEL;
7251 status = smb_set_file_unix_hlink(conn, req,
7252 pdata, total_data,
7253 smb_fname);
7254 break;
7257 case SMB_FILE_RENAME_INFORMATION:
7259 status = smb_file_rename_information(conn, req,
7260 pdata, total_data,
7261 fsp, fname);
7262 break;
7265 #if defined(HAVE_POSIX_ACLS)
7266 case SMB_SET_POSIX_ACL:
7268 status = smb_set_posix_acl(conn,
7269 pdata,
7270 total_data,
7271 fsp,
7272 fname,
7273 &sbuf);
7274 break;
7276 #endif
7278 case SMB_SET_POSIX_LOCK:
7280 if (fsp) {
7281 return NT_STATUS_INVALID_LEVEL;
7283 status = smb_set_posix_lock(conn, req,
7284 pdata, total_data, fsp);
7285 break;
7288 case SMB_POSIX_PATH_OPEN:
7290 if (fsp) {
7291 /* We must have a pathname for this. */
7292 return NT_STATUS_INVALID_LEVEL;
7295 status = smb_posix_open(conn, req,
7296 ppdata,
7297 total_data,
7298 fname,
7299 &sbuf,
7300 &data_return_size);
7301 break;
7304 case SMB_POSIX_PATH_UNLINK:
7306 if (fsp) {
7307 /* We must have a pathname for this. */
7308 return NT_STATUS_INVALID_LEVEL;
7311 status = smb_posix_unlink(conn, req,
7312 pdata,
7313 total_data,
7314 smb_fname);
7315 break;
7318 default:
7319 return NT_STATUS_INVALID_LEVEL;
7322 if (!NT_STATUS_IS_OK(status)) {
7323 return status;
7326 *ret_data_size = data_return_size;
7327 return NT_STATUS_OK;
7330 /****************************************************************************
7331 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7332 ****************************************************************************/
7334 static void call_trans2setfilepathinfo(connection_struct *conn,
7335 struct smb_request *req,
7336 unsigned int tran_call,
7337 char **pparams, int total_params,
7338 char **ppdata, int total_data,
7339 unsigned int max_data_bytes)
7341 char *params = *pparams;
7342 char *pdata = *ppdata;
7343 uint16 info_level;
7344 char *fname = NULL;
7345 struct smb_filename *smb_fname = NULL;
7346 files_struct *fsp = NULL;
7347 NTSTATUS status = NT_STATUS_OK;
7348 int data_return_size = 0;
7350 if (!params) {
7351 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7352 return;
7355 if (tran_call == TRANSACT2_SETFILEINFO) {
7356 if (total_params < 4) {
7357 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7358 return;
7361 fsp = file_fsp(req, SVAL(params,0));
7362 /* Basic check for non-null fsp. */
7363 if (!check_fsp_open(conn, req, fsp)) {
7364 return;
7366 info_level = SVAL(params,2);
7368 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
7369 if (!fname) {
7370 reply_nterror(req, NT_STATUS_NO_MEMORY);
7371 return;
7374 status = create_synthetic_smb_fname_split(talloc_tos(), fname,
7375 NULL, &smb_fname);
7376 if (!NT_STATUS_IS_OK(status)) {
7377 reply_nterror(req, status);
7378 return;
7381 if(fsp->is_directory || fsp->fh->fd == -1) {
7383 * This is actually a SETFILEINFO on a directory
7384 * handle (returned from an NT SMB). NT5.0 seems
7385 * to do this call. JRA.
7387 if (INFO_LEVEL_IS_UNIX(info_level)) {
7388 /* Always do lstat for UNIX calls. */
7389 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7390 DEBUG(3,("call_trans2setfilepathinfo: "
7391 "SMB_VFS_LSTAT of %s failed "
7392 "(%s)\n",
7393 smb_fname_str_dbg(smb_fname),
7394 strerror(errno)));
7395 reply_nterror(req, map_nt_error_from_unix(errno));
7396 return;
7398 } else {
7399 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7400 DEBUG(3,("call_trans2setfilepathinfo: "
7401 "fileinfo of %s failed (%s)\n",
7402 smb_fname_str_dbg(smb_fname),
7403 strerror(errno)));
7404 reply_nterror(req, map_nt_error_from_unix(errno));
7405 return;
7408 } else if (fsp->print_file) {
7410 * Doing a DELETE_ON_CLOSE should cancel a print job.
7412 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7413 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7415 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
7417 SSVAL(params,0,0);
7418 send_trans2_replies(conn, req, params, 2,
7419 *ppdata, 0,
7420 max_data_bytes);
7421 return;
7422 } else {
7423 reply_doserror(req, ERRDOS, ERRbadpath);
7424 return;
7426 } else {
7428 * Original code - this is an open file.
7430 if (!check_fsp(conn, req, fsp)) {
7431 return;
7434 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7435 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7436 "of fnum %d failed (%s)\n", fsp->fnum,
7437 strerror(errno)));
7438 reply_nterror(req, map_nt_error_from_unix(errno));
7439 return;
7442 } else {
7443 /* set path info */
7444 if (total_params < 7) {
7445 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7446 return;
7449 info_level = SVAL(params,0);
7450 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7451 total_params - 6, STR_TERMINATE,
7452 &status);
7453 if (!NT_STATUS_IS_OK(status)) {
7454 reply_nterror(req, status);
7455 return;
7458 status = filename_convert(req, conn,
7459 req->flags2 & FLAGS2_DFS_PATHNAMES,
7460 fname,
7461 &smb_fname,
7462 &fname);
7463 if (!NT_STATUS_IS_OK(status)) {
7464 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7465 reply_botherror(req,
7466 NT_STATUS_PATH_NOT_COVERED,
7467 ERRSRV, ERRbadpath);
7468 return;
7470 reply_nterror(req, status);
7471 return;
7474 if (INFO_LEVEL_IS_UNIX(info_level)) {
7476 * For CIFS UNIX extensions the target name may not exist.
7479 /* Always do lstat for UNIX calls. */
7480 SMB_VFS_LSTAT(conn, smb_fname);
7482 } else if (!VALID_STAT(smb_fname->st) &&
7483 SMB_VFS_STAT(conn, smb_fname)) {
7484 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7485 "%s failed (%s)\n",
7486 smb_fname_str_dbg(smb_fname),
7487 strerror(errno)));
7488 reply_nterror(req, map_nt_error_from_unix(errno));
7489 return;
7493 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
7494 tran_call, fname, fsp ? fsp->fnum : -1, info_level,total_data));
7496 /* Realloc the parameter size */
7497 *pparams = (char *)SMB_REALLOC(*pparams,2);
7498 if (*pparams == NULL) {
7499 reply_nterror(req, NT_STATUS_NO_MEMORY);
7500 return;
7502 params = *pparams;
7504 SSVAL(params,0,0);
7506 status = smbd_do_setfilepathinfo(conn, req, req,
7507 info_level,
7508 fsp,
7509 smb_fname,
7510 ppdata, total_data,
7511 &data_return_size);
7512 if (!NT_STATUS_IS_OK(status)) {
7513 if (open_was_deferred(req->mid)) {
7514 /* We have re-scheduled this call. */
7515 return;
7517 if (blocking_lock_was_deferred(req->mid)) {
7518 /* We have re-scheduled this call. */
7519 return;
7521 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7522 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7523 ERRSRV, ERRbadpath);
7524 return;
7526 if (info_level == SMB_POSIX_PATH_OPEN) {
7527 reply_openerror(req, status);
7528 return;
7531 reply_nterror(req, status);
7532 return;
7535 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7536 max_data_bytes);
7538 return;
7541 /****************************************************************************
7542 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7543 ****************************************************************************/
7545 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7546 char **pparams, int total_params,
7547 char **ppdata, int total_data,
7548 unsigned int max_data_bytes)
7550 struct smb_filename *smb_dname = NULL;
7551 char *params = *pparams;
7552 char *pdata = *ppdata;
7553 char *directory = NULL;
7554 NTSTATUS status = NT_STATUS_OK;
7555 struct ea_list *ea_list = NULL;
7556 TALLOC_CTX *ctx = talloc_tos();
7558 if (!CAN_WRITE(conn)) {
7559 reply_doserror(req, ERRSRV, ERRaccess);
7560 return;
7563 if (total_params < 5) {
7564 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7565 return;
7568 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7569 total_params - 4, STR_TERMINATE,
7570 &status);
7571 if (!NT_STATUS_IS_OK(status)) {
7572 reply_nterror(req, status);
7573 return;
7576 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7578 status = filename_convert(ctx,
7579 conn,
7580 req->flags2 & FLAGS2_DFS_PATHNAMES,
7581 directory,
7582 &smb_dname,
7583 NULL);
7585 if (!NT_STATUS_IS_OK(status)) {
7586 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7587 reply_botherror(req,
7588 NT_STATUS_PATH_NOT_COVERED,
7589 ERRSRV, ERRbadpath);
7590 return;
7592 reply_nterror(req, status);
7593 return;
7596 /* Any data in this call is an EA list. */
7597 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7598 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7599 goto out;
7603 * OS/2 workplace shell seems to send SET_EA requests of "null"
7604 * length (4 bytes containing IVAL 4).
7605 * They seem to have no effect. Bug #3212. JRA.
7608 if (total_data != 4) {
7609 if (total_data < 10) {
7610 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7611 goto out;
7614 if (IVAL(pdata,0) > total_data) {
7615 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7616 IVAL(pdata,0), (unsigned int)total_data));
7617 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7618 goto out;
7621 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7622 total_data - 4);
7623 if (!ea_list) {
7624 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7625 goto out;
7628 /* If total_data == 4 Windows doesn't care what values
7629 * are placed in that field, it just ignores them.
7630 * The System i QNTC IBM SMB client puts bad values here,
7631 * so ignore them. */
7633 status = create_directory(conn, req, smb_dname);
7635 if (!NT_STATUS_IS_OK(status)) {
7636 reply_nterror(req, status);
7637 goto out;
7640 /* Try and set any given EA. */
7641 if (ea_list) {
7642 status = set_ea(conn, NULL, smb_dname, ea_list);
7643 if (!NT_STATUS_IS_OK(status)) {
7644 reply_nterror(req, status);
7645 goto out;
7649 /* Realloc the parameter and data sizes */
7650 *pparams = (char *)SMB_REALLOC(*pparams,2);
7651 if(*pparams == NULL) {
7652 reply_nterror(req, NT_STATUS_NO_MEMORY);
7653 goto out;
7655 params = *pparams;
7657 SSVAL(params,0,0);
7659 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7661 out:
7662 TALLOC_FREE(smb_dname);
7663 return;
7666 /****************************************************************************
7667 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7668 We don't actually do this - we just send a null response.
7669 ****************************************************************************/
7671 static void call_trans2findnotifyfirst(connection_struct *conn,
7672 struct smb_request *req,
7673 char **pparams, int total_params,
7674 char **ppdata, int total_data,
7675 unsigned int max_data_bytes)
7677 char *params = *pparams;
7678 uint16 info_level;
7680 if (total_params < 6) {
7681 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7682 return;
7685 info_level = SVAL(params,4);
7686 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7688 switch (info_level) {
7689 case 1:
7690 case 2:
7691 break;
7692 default:
7693 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7694 return;
7697 /* Realloc the parameter and data sizes */
7698 *pparams = (char *)SMB_REALLOC(*pparams,6);
7699 if (*pparams == NULL) {
7700 reply_nterror(req, NT_STATUS_NO_MEMORY);
7701 return;
7703 params = *pparams;
7705 SSVAL(params,0,fnf_handle);
7706 SSVAL(params,2,0); /* No changes */
7707 SSVAL(params,4,0); /* No EA errors */
7709 fnf_handle++;
7711 if(fnf_handle == 0)
7712 fnf_handle = 257;
7714 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7716 return;
7719 /****************************************************************************
7720 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7721 changes). Currently this does nothing.
7722 ****************************************************************************/
7724 static void call_trans2findnotifynext(connection_struct *conn,
7725 struct smb_request *req,
7726 char **pparams, int total_params,
7727 char **ppdata, int total_data,
7728 unsigned int max_data_bytes)
7730 char *params = *pparams;
7732 DEBUG(3,("call_trans2findnotifynext\n"));
7734 /* Realloc the parameter and data sizes */
7735 *pparams = (char *)SMB_REALLOC(*pparams,4);
7736 if (*pparams == NULL) {
7737 reply_nterror(req, NT_STATUS_NO_MEMORY);
7738 return;
7740 params = *pparams;
7742 SSVAL(params,0,0); /* No changes */
7743 SSVAL(params,2,0); /* No EA errors */
7745 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7747 return;
7750 /****************************************************************************
7751 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7752 ****************************************************************************/
7754 static void call_trans2getdfsreferral(connection_struct *conn,
7755 struct smb_request *req,
7756 char **pparams, int total_params,
7757 char **ppdata, int total_data,
7758 unsigned int max_data_bytes)
7760 char *params = *pparams;
7761 char *pathname = NULL;
7762 int reply_size = 0;
7763 int max_referral_level;
7764 NTSTATUS status = NT_STATUS_OK;
7765 TALLOC_CTX *ctx = talloc_tos();
7767 DEBUG(10,("call_trans2getdfsreferral\n"));
7769 if (total_params < 3) {
7770 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7771 return;
7774 max_referral_level = SVAL(params,0);
7776 if(!lp_host_msdfs()) {
7777 reply_doserror(req, ERRDOS, ERRbadfunc);
7778 return;
7781 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7782 total_params - 2, STR_TERMINATE);
7783 if (!pathname) {
7784 reply_nterror(req, NT_STATUS_NOT_FOUND);
7785 return;
7787 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7788 ppdata,&status)) < 0) {
7789 reply_nterror(req, status);
7790 return;
7793 SSVAL(req->inbuf, smb_flg2,
7794 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7795 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7797 return;
7800 #define LMCAT_SPL 0x53
7801 #define LMFUNC_GETJOBID 0x60
7803 /****************************************************************************
7804 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7805 ****************************************************************************/
7807 static void call_trans2ioctl(connection_struct *conn,
7808 struct smb_request *req,
7809 char **pparams, int total_params,
7810 char **ppdata, int total_data,
7811 unsigned int max_data_bytes)
7813 char *pdata = *ppdata;
7814 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7816 /* check for an invalid fid before proceeding */
7818 if (!fsp) {
7819 reply_doserror(req, ERRDOS, ERRbadfid);
7820 return;
7823 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7824 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7825 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7826 if (*ppdata == NULL) {
7827 reply_nterror(req, NT_STATUS_NO_MEMORY);
7828 return;
7830 pdata = *ppdata;
7832 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7833 CAN ACCEPT THIS IN UNICODE. JRA. */
7835 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7836 srvstr_push(pdata, req->flags2, pdata + 2,
7837 global_myname(), 15,
7838 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7839 srvstr_push(pdata, req->flags2, pdata+18,
7840 lp_servicename(SNUM(conn)), 13,
7841 STR_ASCII|STR_TERMINATE); /* Service name */
7842 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7843 max_data_bytes);
7844 return;
7847 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7848 reply_doserror(req, ERRSRV, ERRerror);
7851 /****************************************************************************
7852 Reply to a SMBfindclose (stop trans2 directory search).
7853 ****************************************************************************/
7855 void reply_findclose(struct smb_request *req)
7857 int dptr_num;
7859 START_PROFILE(SMBfindclose);
7861 if (req->wct < 1) {
7862 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7863 END_PROFILE(SMBfindclose);
7864 return;
7867 dptr_num = SVALS(req->vwv+0, 0);
7869 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7871 dptr_close(&dptr_num);
7873 reply_outbuf(req, 0, 0);
7875 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7877 END_PROFILE(SMBfindclose);
7878 return;
7881 /****************************************************************************
7882 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7883 ****************************************************************************/
7885 void reply_findnclose(struct smb_request *req)
7887 int dptr_num;
7889 START_PROFILE(SMBfindnclose);
7891 if (req->wct < 1) {
7892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7893 END_PROFILE(SMBfindnclose);
7894 return;
7897 dptr_num = SVAL(req->vwv+0, 0);
7899 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7901 /* We never give out valid handles for a
7902 findnotifyfirst - so any dptr_num is ok here.
7903 Just ignore it. */
7905 reply_outbuf(req, 0, 0);
7907 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7909 END_PROFILE(SMBfindnclose);
7910 return;
7913 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7914 struct trans_state *state)
7916 if (Protocol >= PROTOCOL_NT1) {
7917 req->flags2 |= 0x40; /* IS_LONG_NAME */
7918 SSVAL(req->inbuf,smb_flg2,req->flags2);
7921 if (conn->encrypt_level == Required && !req->encrypted) {
7922 if (state->call != TRANSACT2_QFSINFO &&
7923 state->call != TRANSACT2_SETFSINFO) {
7924 DEBUG(0,("handle_trans2: encryption required "
7925 "with call 0x%x\n",
7926 (unsigned int)state->call));
7927 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7928 return;
7932 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7934 /* Now we must call the relevant TRANS2 function */
7935 switch(state->call) {
7936 case TRANSACT2_OPEN:
7938 START_PROFILE(Trans2_open);
7939 call_trans2open(conn, req,
7940 &state->param, state->total_param,
7941 &state->data, state->total_data,
7942 state->max_data_return);
7943 END_PROFILE(Trans2_open);
7944 break;
7947 case TRANSACT2_FINDFIRST:
7949 START_PROFILE(Trans2_findfirst);
7950 call_trans2findfirst(conn, req,
7951 &state->param, state->total_param,
7952 &state->data, state->total_data,
7953 state->max_data_return);
7954 END_PROFILE(Trans2_findfirst);
7955 break;
7958 case TRANSACT2_FINDNEXT:
7960 START_PROFILE(Trans2_findnext);
7961 call_trans2findnext(conn, req,
7962 &state->param, state->total_param,
7963 &state->data, state->total_data,
7964 state->max_data_return);
7965 END_PROFILE(Trans2_findnext);
7966 break;
7969 case TRANSACT2_QFSINFO:
7971 START_PROFILE(Trans2_qfsinfo);
7972 call_trans2qfsinfo(conn, req,
7973 &state->param, state->total_param,
7974 &state->data, state->total_data,
7975 state->max_data_return);
7976 END_PROFILE(Trans2_qfsinfo);
7977 break;
7980 case TRANSACT2_SETFSINFO:
7982 START_PROFILE(Trans2_setfsinfo);
7983 call_trans2setfsinfo(conn, req,
7984 &state->param, state->total_param,
7985 &state->data, state->total_data,
7986 state->max_data_return);
7987 END_PROFILE(Trans2_setfsinfo);
7988 break;
7991 case TRANSACT2_QPATHINFO:
7992 case TRANSACT2_QFILEINFO:
7994 START_PROFILE(Trans2_qpathinfo);
7995 call_trans2qfilepathinfo(conn, req, state->call,
7996 &state->param, state->total_param,
7997 &state->data, state->total_data,
7998 state->max_data_return);
7999 END_PROFILE(Trans2_qpathinfo);
8000 break;
8003 case TRANSACT2_SETPATHINFO:
8004 case TRANSACT2_SETFILEINFO:
8006 START_PROFILE(Trans2_setpathinfo);
8007 call_trans2setfilepathinfo(conn, req, state->call,
8008 &state->param, state->total_param,
8009 &state->data, state->total_data,
8010 state->max_data_return);
8011 END_PROFILE(Trans2_setpathinfo);
8012 break;
8015 case TRANSACT2_FINDNOTIFYFIRST:
8017 START_PROFILE(Trans2_findnotifyfirst);
8018 call_trans2findnotifyfirst(conn, req,
8019 &state->param, state->total_param,
8020 &state->data, state->total_data,
8021 state->max_data_return);
8022 END_PROFILE(Trans2_findnotifyfirst);
8023 break;
8026 case TRANSACT2_FINDNOTIFYNEXT:
8028 START_PROFILE(Trans2_findnotifynext);
8029 call_trans2findnotifynext(conn, req,
8030 &state->param, state->total_param,
8031 &state->data, state->total_data,
8032 state->max_data_return);
8033 END_PROFILE(Trans2_findnotifynext);
8034 break;
8037 case TRANSACT2_MKDIR:
8039 START_PROFILE(Trans2_mkdir);
8040 call_trans2mkdir(conn, req,
8041 &state->param, state->total_param,
8042 &state->data, state->total_data,
8043 state->max_data_return);
8044 END_PROFILE(Trans2_mkdir);
8045 break;
8048 case TRANSACT2_GET_DFS_REFERRAL:
8050 START_PROFILE(Trans2_get_dfs_referral);
8051 call_trans2getdfsreferral(conn, req,
8052 &state->param, state->total_param,
8053 &state->data, state->total_data,
8054 state->max_data_return);
8055 END_PROFILE(Trans2_get_dfs_referral);
8056 break;
8059 case TRANSACT2_IOCTL:
8061 START_PROFILE(Trans2_ioctl);
8062 call_trans2ioctl(conn, req,
8063 &state->param, state->total_param,
8064 &state->data, state->total_data,
8065 state->max_data_return);
8066 END_PROFILE(Trans2_ioctl);
8067 break;
8070 default:
8071 /* Error in request */
8072 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8073 reply_doserror(req, ERRSRV,ERRerror);
8077 /****************************************************************************
8078 Reply to a SMBtrans2.
8079 ****************************************************************************/
8081 void reply_trans2(struct smb_request *req)
8083 connection_struct *conn = req->conn;
8084 unsigned int dsoff;
8085 unsigned int dscnt;
8086 unsigned int psoff;
8087 unsigned int pscnt;
8088 unsigned int tran_call;
8089 struct trans_state *state;
8090 NTSTATUS result;
8092 START_PROFILE(SMBtrans2);
8094 if (req->wct < 14) {
8095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8096 END_PROFILE(SMBtrans2);
8097 return;
8100 dsoff = SVAL(req->vwv+12, 0);
8101 dscnt = SVAL(req->vwv+11, 0);
8102 psoff = SVAL(req->vwv+10, 0);
8103 pscnt = SVAL(req->vwv+9, 0);
8104 tran_call = SVAL(req->vwv+14, 0);
8106 result = allow_new_trans(conn->pending_trans, req->mid);
8107 if (!NT_STATUS_IS_OK(result)) {
8108 DEBUG(2, ("Got invalid trans2 request: %s\n",
8109 nt_errstr(result)));
8110 reply_nterror(req, result);
8111 END_PROFILE(SMBtrans2);
8112 return;
8115 if (IS_IPC(conn)) {
8116 switch (tran_call) {
8117 /* List the allowed trans2 calls on IPC$ */
8118 case TRANSACT2_OPEN:
8119 case TRANSACT2_GET_DFS_REFERRAL:
8120 case TRANSACT2_QFILEINFO:
8121 case TRANSACT2_QFSINFO:
8122 case TRANSACT2_SETFSINFO:
8123 break;
8124 default:
8125 reply_doserror(req, ERRSRV, ERRaccess);
8126 END_PROFILE(SMBtrans2);
8127 return;
8131 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8132 DEBUG(0, ("talloc failed\n"));
8133 reply_nterror(req, NT_STATUS_NO_MEMORY);
8134 END_PROFILE(SMBtrans2);
8135 return;
8138 state->cmd = SMBtrans2;
8140 state->mid = req->mid;
8141 state->vuid = req->vuid;
8142 state->setup_count = SVAL(req->vwv+13, 0);
8143 state->setup = NULL;
8144 state->total_param = SVAL(req->vwv+0, 0);
8145 state->param = NULL;
8146 state->total_data = SVAL(req->vwv+1, 0);
8147 state->data = NULL;
8148 state->max_param_return = SVAL(req->vwv+2, 0);
8149 state->max_data_return = SVAL(req->vwv+3, 0);
8150 state->max_setup_return = SVAL(req->vwv+4, 0);
8151 state->close_on_completion = BITSETW(req->vwv+5, 0);
8152 state->one_way = BITSETW(req->vwv+5, 1);
8154 state->call = tran_call;
8156 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8157 is so as a sanity check */
8158 if (state->setup_count != 1) {
8160 * Need to have rc=0 for ioctl to get job id for OS/2.
8161 * Network printing will fail if function is not successful.
8162 * Similar function in reply.c will be used if protocol
8163 * is LANMAN1.0 instead of LM1.2X002.
8164 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8165 * outbuf doesn't have to be set(only job id is used).
8167 if ( (state->setup_count == 4)
8168 && (tran_call == TRANSACT2_IOCTL)
8169 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8170 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8171 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8172 } else {
8173 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8174 DEBUG(2,("Transaction is %d\n",tran_call));
8175 TALLOC_FREE(state);
8176 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8177 END_PROFILE(SMBtrans2);
8178 return;
8182 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8183 goto bad_param;
8185 if (state->total_data) {
8187 if (trans_oob(state->total_data, 0, dscnt)
8188 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8189 goto bad_param;
8192 /* Can't use talloc here, the core routines do realloc on the
8193 * params and data. */
8194 state->data = (char *)SMB_MALLOC(state->total_data);
8195 if (state->data == NULL) {
8196 DEBUG(0,("reply_trans2: data malloc fail for %u "
8197 "bytes !\n", (unsigned int)state->total_data));
8198 TALLOC_FREE(state);
8199 reply_nterror(req, NT_STATUS_NO_MEMORY);
8200 END_PROFILE(SMBtrans2);
8201 return;
8204 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8207 if (state->total_param) {
8209 if (trans_oob(state->total_param, 0, pscnt)
8210 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8211 goto bad_param;
8214 /* Can't use talloc here, the core routines do realloc on the
8215 * params and data. */
8216 state->param = (char *)SMB_MALLOC(state->total_param);
8217 if (state->param == NULL) {
8218 DEBUG(0,("reply_trans: param malloc fail for %u "
8219 "bytes !\n", (unsigned int)state->total_param));
8220 SAFE_FREE(state->data);
8221 TALLOC_FREE(state);
8222 reply_nterror(req, NT_STATUS_NO_MEMORY);
8223 END_PROFILE(SMBtrans2);
8224 return;
8227 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8230 state->received_data = dscnt;
8231 state->received_param = pscnt;
8233 if ((state->received_param == state->total_param) &&
8234 (state->received_data == state->total_data)) {
8236 handle_trans2(conn, req, state);
8238 SAFE_FREE(state->data);
8239 SAFE_FREE(state->param);
8240 TALLOC_FREE(state);
8241 END_PROFILE(SMBtrans2);
8242 return;
8245 DLIST_ADD(conn->pending_trans, state);
8247 /* We need to send an interim response then receive the rest
8248 of the parameter/data bytes */
8249 reply_outbuf(req, 0, 0);
8250 show_msg((char *)req->outbuf);
8251 END_PROFILE(SMBtrans2);
8252 return;
8254 bad_param:
8256 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8257 SAFE_FREE(state->data);
8258 SAFE_FREE(state->param);
8259 TALLOC_FREE(state);
8260 END_PROFILE(SMBtrans2);
8261 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8265 /****************************************************************************
8266 Reply to a SMBtranss2
8267 ****************************************************************************/
8269 void reply_transs2(struct smb_request *req)
8271 connection_struct *conn = req->conn;
8272 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8273 struct trans_state *state;
8275 START_PROFILE(SMBtranss2);
8277 show_msg((char *)req->inbuf);
8279 if (req->wct < 8) {
8280 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8281 END_PROFILE(SMBtranss2);
8282 return;
8285 for (state = conn->pending_trans; state != NULL;
8286 state = state->next) {
8287 if (state->mid == req->mid) {
8288 break;
8292 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8293 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8294 END_PROFILE(SMBtranss2);
8295 return;
8298 /* Revise state->total_param and state->total_data in case they have
8299 changed downwards */
8301 if (SVAL(req->vwv+0, 0) < state->total_param)
8302 state->total_param = SVAL(req->vwv+0, 0);
8303 if (SVAL(req->vwv+1, 0) < state->total_data)
8304 state->total_data = SVAL(req->vwv+1, 0);
8306 pcnt = SVAL(req->vwv+2, 0);
8307 poff = SVAL(req->vwv+3, 0);
8308 pdisp = SVAL(req->vwv+4, 0);
8310 dcnt = SVAL(req->vwv+5, 0);
8311 doff = SVAL(req->vwv+6, 0);
8312 ddisp = SVAL(req->vwv+7, 0);
8314 state->received_param += pcnt;
8315 state->received_data += dcnt;
8317 if ((state->received_data > state->total_data) ||
8318 (state->received_param > state->total_param))
8319 goto bad_param;
8321 if (pcnt) {
8322 if (trans_oob(state->total_param, pdisp, pcnt)
8323 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8324 goto bad_param;
8326 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8329 if (dcnt) {
8330 if (trans_oob(state->total_data, ddisp, dcnt)
8331 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8332 goto bad_param;
8334 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8337 if ((state->received_param < state->total_param) ||
8338 (state->received_data < state->total_data)) {
8339 END_PROFILE(SMBtranss2);
8340 return;
8343 handle_trans2(conn, req, state);
8345 DLIST_REMOVE(conn->pending_trans, state);
8346 SAFE_FREE(state->data);
8347 SAFE_FREE(state->param);
8348 TALLOC_FREE(state);
8350 END_PROFILE(SMBtranss2);
8351 return;
8353 bad_param:
8355 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8356 DLIST_REMOVE(conn->pending_trans, state);
8357 SAFE_FREE(state->data);
8358 SAFE_FREE(state->param);
8359 TALLOC_FREE(state);
8360 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8361 END_PROFILE(SMBtranss2);
8362 return;