Move the checks for null timestamps down below the VFS_NTIMES
[Samba/fernandojvsilva.git] / source3 / smbd / trans2.c
blob2e47eab4f072656ed6fe8454ae8822b213b3a35c
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;
475 if (!lp_ea_support(SNUM(conn))) {
476 return NT_STATUS_EAS_NOT_SUPPORTED;
479 /* For now setting EAs on streams isn't supported. */
480 fname = smb_fname->base_name;
482 for (;ea_list; ea_list = ea_list->next) {
483 int ret;
484 fstring unix_ea_name;
486 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
487 fstrcat(unix_ea_name, ea_list->ea.name);
489 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
491 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
493 if (samba_private_attr_name(unix_ea_name)) {
494 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
495 return NT_STATUS_ACCESS_DENIED;
498 if (ea_list->ea.value.length == 0) {
499 /* Remove the attribute. */
500 if (fsp && (fsp->fh->fd != -1)) {
501 DEBUG(10,("set_ea: deleting ea name %s on "
502 "file %s by file descriptor.\n",
503 unix_ea_name, fsp_str_dbg(fsp)));
504 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
505 } else {
506 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
507 unix_ea_name, fname));
508 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
510 #ifdef ENOATTR
511 /* Removing a non existent attribute always succeeds. */
512 if (ret == -1 && errno == ENOATTR) {
513 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
514 unix_ea_name));
515 ret = 0;
517 #endif
518 } else {
519 if (fsp && (fsp->fh->fd != -1)) {
520 DEBUG(10,("set_ea: setting ea name %s on file "
521 "%s by file descriptor.\n",
522 unix_ea_name, fsp_str_dbg(fsp)));
523 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
524 ea_list->ea.value.data, ea_list->ea.value.length, 0);
525 } else {
526 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
527 unix_ea_name, fname));
528 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
529 ea_list->ea.value.data, ea_list->ea.value.length, 0);
533 if (ret == -1) {
534 #ifdef ENOTSUP
535 if (errno == ENOTSUP) {
536 return NT_STATUS_EAS_NOT_SUPPORTED;
538 #endif
539 return map_nt_error_from_unix(errno);
543 return NT_STATUS_OK;
545 /****************************************************************************
546 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
547 ****************************************************************************/
549 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
551 struct ea_list *ea_list_head = NULL;
552 size_t converted_size, offset = 0;
554 while (offset + 2 < data_size) {
555 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
556 unsigned int namelen = CVAL(pdata,offset);
558 offset++; /* Go past the namelen byte. */
560 /* integer wrap paranioa. */
561 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
562 (offset > data_size) || (namelen > data_size) ||
563 (offset + namelen >= data_size)) {
564 break;
566 /* Ensure the name is null terminated. */
567 if (pdata[offset + namelen] != '\0') {
568 return NULL;
570 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
571 &converted_size)) {
572 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
573 "failed: %s", strerror(errno)));
575 if (!eal->ea.name) {
576 return NULL;
579 offset += (namelen + 1); /* Go past the name + terminating zero. */
580 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
581 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
584 return ea_list_head;
587 /****************************************************************************
588 Read one EA list entry from the buffer.
589 ****************************************************************************/
591 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
593 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
594 uint16 val_len;
595 unsigned int namelen;
596 size_t converted_size;
598 if (!eal) {
599 return NULL;
602 if (data_size < 6) {
603 return NULL;
606 eal->ea.flags = CVAL(pdata,0);
607 namelen = CVAL(pdata,1);
608 val_len = SVAL(pdata,2);
610 if (4 + namelen + 1 + val_len > data_size) {
611 return NULL;
614 /* Ensure the name is null terminated. */
615 if (pdata[namelen + 4] != '\0') {
616 return NULL;
618 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
619 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
620 strerror(errno)));
622 if (!eal->ea.name) {
623 return NULL;
626 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
627 if (!eal->ea.value.data) {
628 return NULL;
631 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
633 /* Ensure we're null terminated just in case we print the value. */
634 eal->ea.value.data[val_len] = '\0';
635 /* But don't count the null. */
636 eal->ea.value.length--;
638 if (pbytes_used) {
639 *pbytes_used = 4 + namelen + 1 + val_len;
642 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
643 dump_data(10, eal->ea.value.data, eal->ea.value.length);
645 return eal;
648 /****************************************************************************
649 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
650 ****************************************************************************/
652 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
654 struct ea_list *ea_list_head = NULL;
655 size_t offset = 0;
656 size_t bytes_used = 0;
658 while (offset < data_size) {
659 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
661 if (!eal) {
662 return NULL;
665 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
666 offset += bytes_used;
669 return ea_list_head;
672 /****************************************************************************
673 Count the total EA size needed.
674 ****************************************************************************/
676 static size_t ea_list_size(struct ea_list *ealist)
678 fstring dos_ea_name;
679 struct ea_list *listp;
680 size_t ret = 0;
682 for (listp = ealist; listp; listp = listp->next) {
683 push_ascii_fstring(dos_ea_name, listp->ea.name);
684 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
686 /* Add on 4 for total length. */
687 if (ret) {
688 ret += 4;
691 return ret;
694 /****************************************************************************
695 Return a union of EA's from a file list and a list of names.
696 The TALLOC context for the two lists *MUST* be identical as we steal
697 memory from one list to add to another. JRA.
698 ****************************************************************************/
700 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
702 struct ea_list *nlistp, *flistp;
704 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
705 for (flistp = file_list; flistp; flistp = flistp->next) {
706 if (strequal(nlistp->ea.name, flistp->ea.name)) {
707 break;
711 if (flistp) {
712 /* Copy the data from this entry. */
713 nlistp->ea.flags = flistp->ea.flags;
714 nlistp->ea.value = flistp->ea.value;
715 } else {
716 /* Null entry. */
717 nlistp->ea.flags = 0;
718 ZERO_STRUCT(nlistp->ea.value);
722 *total_ea_len = ea_list_size(name_list);
723 return name_list;
726 /****************************************************************************
727 Send the required number of replies back.
728 We assume all fields other than the data fields are
729 set correctly for the type of call.
730 HACK ! Always assumes smb_setup field is zero.
731 ****************************************************************************/
733 void send_trans2_replies(connection_struct *conn,
734 struct smb_request *req,
735 const char *params,
736 int paramsize,
737 const char *pdata,
738 int datasize,
739 int max_data_bytes)
741 /* As we are using a protocol > LANMAN1 then the max_send
742 variable must have been set in the sessetupX call.
743 This takes precedence over the max_xmit field in the
744 global struct. These different max_xmit variables should
745 be merged as this is now too confusing */
747 int data_to_send = datasize;
748 int params_to_send = paramsize;
749 int useable_space;
750 const char *pp = params;
751 const char *pd = pdata;
752 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
753 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
754 int data_alignment_offset = 0;
755 bool overflow = False;
756 struct smbd_server_connection *sconn = smbd_server_conn;
757 int max_send = sconn->smb1.sessions.max_send;
759 /* Modify the data_to_send and datasize and set the error if
760 we're trying to send more than max_data_bytes. We still send
761 the part of the packet(s) that fit. Strange, but needed
762 for OS/2. */
764 if (max_data_bytes > 0 && datasize > max_data_bytes) {
765 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
766 max_data_bytes, datasize ));
767 datasize = data_to_send = max_data_bytes;
768 overflow = True;
771 /* If there genuinely are no parameters or data to send just send the empty packet */
773 if(params_to_send == 0 && data_to_send == 0) {
774 reply_outbuf(req, 10, 0);
775 show_msg((char *)req->outbuf);
776 if (!srv_send_smb(smbd_server_fd(),
777 (char *)req->outbuf,
778 true, req->seqnum+1,
779 IS_CONN_ENCRYPTED(conn),
780 &req->pcd)) {
781 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
783 TALLOC_FREE(req->outbuf);
784 return;
787 /* When sending params and data ensure that both are nicely aligned */
788 /* Only do this alignment when there is also data to send - else
789 can cause NT redirector problems. */
791 if (((params_to_send % 4) != 0) && (data_to_send != 0))
792 data_alignment_offset = 4 - (params_to_send % 4);
794 /* Space is bufsize minus Netbios over TCP header minus SMB header */
795 /* The alignment_offset is to align the param bytes on an even byte
796 boundary. NT 4.0 Beta needs this to work correctly. */
798 useable_space = max_send - (smb_size
799 + 2 * 10 /* wct */
800 + alignment_offset
801 + data_alignment_offset);
803 if (useable_space < 0) {
804 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
805 "= %d!!!", useable_space));
806 exit_server_cleanly("send_trans2_replies: Not enough space");
809 while (params_to_send || data_to_send) {
810 /* Calculate whether we will totally or partially fill this packet */
812 total_sent_thistime = params_to_send + data_to_send;
814 /* We can never send more than useable_space */
816 * Note that 'useable_space' does not include the alignment offsets,
817 * but we must include the alignment offsets in the calculation of
818 * the length of the data we send over the wire, as the alignment offsets
819 * are sent here. Fix from Marc_Jacobsen@hp.com.
822 total_sent_thistime = MIN(total_sent_thistime, useable_space);
824 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
825 + data_alignment_offset);
828 * We might have SMBtrans2s in req which was transferred to
829 * the outbuf, fix that.
831 SCVAL(req->outbuf, smb_com, SMBtrans2);
833 /* Set total params and data to be sent */
834 SSVAL(req->outbuf,smb_tprcnt,paramsize);
835 SSVAL(req->outbuf,smb_tdrcnt,datasize);
837 /* Calculate how many parameters and data we can fit into
838 * this packet. Parameters get precedence
841 params_sent_thistime = MIN(params_to_send,useable_space);
842 data_sent_thistime = useable_space - params_sent_thistime;
843 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
845 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
847 /* smb_proff is the offset from the start of the SMB header to the
848 parameter bytes, however the first 4 bytes of outbuf are
849 the Netbios over TCP header. Thus use smb_base() to subtract
850 them from the calculation */
852 SSVAL(req->outbuf,smb_proff,
853 ((smb_buf(req->outbuf)+alignment_offset)
854 - smb_base(req->outbuf)));
856 if(params_sent_thistime == 0)
857 SSVAL(req->outbuf,smb_prdisp,0);
858 else
859 /* Absolute displacement of param bytes sent in this packet */
860 SSVAL(req->outbuf,smb_prdisp,pp - params);
862 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
863 if(data_sent_thistime == 0) {
864 SSVAL(req->outbuf,smb_droff,0);
865 SSVAL(req->outbuf,smb_drdisp, 0);
866 } else {
867 /* The offset of the data bytes is the offset of the
868 parameter bytes plus the number of parameters being sent this time */
869 SSVAL(req->outbuf, smb_droff,
870 ((smb_buf(req->outbuf)+alignment_offset)
871 - smb_base(req->outbuf))
872 + params_sent_thistime + data_alignment_offset);
873 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
876 /* Initialize the padding for alignment */
878 if (alignment_offset != 0) {
879 memset(smb_buf(req->outbuf), 0, alignment_offset);
882 /* Copy the param bytes into the packet */
884 if(params_sent_thistime) {
885 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
886 params_sent_thistime);
889 /* Copy in the data bytes */
890 if(data_sent_thistime) {
891 if (data_alignment_offset != 0) {
892 memset((smb_buf(req->outbuf)+alignment_offset+
893 params_sent_thistime), 0,
894 data_alignment_offset);
896 memcpy(smb_buf(req->outbuf)+alignment_offset
897 +params_sent_thistime+data_alignment_offset,
898 pd,data_sent_thistime);
901 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
902 params_sent_thistime, data_sent_thistime, useable_space));
903 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
904 params_to_send, data_to_send, paramsize, datasize));
906 if (overflow) {
907 error_packet_set((char *)req->outbuf,
908 ERRDOS,ERRbufferoverflow,
909 STATUS_BUFFER_OVERFLOW,
910 __LINE__,__FILE__);
913 /* Send the packet */
914 show_msg((char *)req->outbuf);
915 if (!srv_send_smb(smbd_server_fd(),
916 (char *)req->outbuf,
917 true, req->seqnum+1,
918 IS_CONN_ENCRYPTED(conn),
919 &req->pcd))
920 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
922 TALLOC_FREE(req->outbuf);
924 pp += params_sent_thistime;
925 pd += data_sent_thistime;
927 params_to_send -= params_sent_thistime;
928 data_to_send -= data_sent_thistime;
930 /* Sanity check */
931 if(params_to_send < 0 || data_to_send < 0) {
932 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
933 params_to_send, data_to_send));
934 return;
938 return;
941 /****************************************************************************
942 Reply to a TRANSACT2_OPEN.
943 ****************************************************************************/
945 static void call_trans2open(connection_struct *conn,
946 struct smb_request *req,
947 char **pparams, int total_params,
948 char **ppdata, int total_data,
949 unsigned int max_data_bytes)
951 struct smb_filename *smb_fname = NULL;
952 char *params = *pparams;
953 char *pdata = *ppdata;
954 int deny_mode;
955 int32 open_attr;
956 bool oplock_request;
957 #if 0
958 bool return_additional_info;
959 int16 open_sattr;
960 time_t open_time;
961 #endif
962 int open_ofun;
963 uint32 open_size;
964 char *pname;
965 char *fname = NULL;
966 SMB_OFF_T size=0;
967 int fattr=0,mtime=0;
968 SMB_INO_T inode = 0;
969 int smb_action = 0;
970 files_struct *fsp;
971 struct ea_list *ea_list = NULL;
972 uint16 flags = 0;
973 NTSTATUS status;
974 uint32 access_mask;
975 uint32 share_mode;
976 uint32 create_disposition;
977 uint32 create_options = 0;
978 TALLOC_CTX *ctx = talloc_tos();
981 * Ensure we have enough parameters to perform the operation.
984 if (total_params < 29) {
985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
986 goto out;
989 flags = SVAL(params, 0);
990 deny_mode = SVAL(params, 2);
991 open_attr = SVAL(params,6);
992 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
993 if (oplock_request) {
994 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
997 #if 0
998 return_additional_info = BITSETW(params,0);
999 open_sattr = SVAL(params, 4);
1000 open_time = make_unix_date3(params+8);
1001 #endif
1002 open_ofun = SVAL(params,12);
1003 open_size = IVAL(params,14);
1004 pname = &params[28];
1006 if (IS_IPC(conn)) {
1007 reply_doserror(req, ERRSRV, ERRaccess);
1008 goto out;
1011 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1012 total_params - 28, STR_TERMINATE,
1013 &status);
1014 if (!NT_STATUS_IS_OK(status)) {
1015 reply_nterror(req, status);
1016 goto out;
1019 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1020 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1021 (unsigned int)open_ofun, open_size));
1023 status = filename_convert(ctx,
1024 conn,
1025 req->flags2 & FLAGS2_DFS_PATHNAMES,
1026 fname,
1028 NULL,
1029 &smb_fname);
1030 if (!NT_STATUS_IS_OK(status)) {
1031 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1032 reply_botherror(req,
1033 NT_STATUS_PATH_NOT_COVERED,
1034 ERRSRV, ERRbadpath);
1035 goto out;
1037 reply_nterror(req, status);
1038 goto out;
1041 if (open_ofun == 0) {
1042 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1043 goto out;
1046 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1047 &access_mask, &share_mode,
1048 &create_disposition,
1049 &create_options)) {
1050 reply_doserror(req, ERRDOS, ERRbadaccess);
1051 goto out;
1054 /* Any data in this call is an EA list. */
1055 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1056 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1057 goto out;
1060 if (total_data != 4) {
1061 if (total_data < 10) {
1062 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1063 goto out;
1066 if (IVAL(pdata,0) > total_data) {
1067 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1068 IVAL(pdata,0), (unsigned int)total_data));
1069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1070 goto out;
1073 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1074 total_data - 4);
1075 if (!ea_list) {
1076 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1077 goto out;
1079 } else if (IVAL(pdata,0) != 4) {
1080 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1081 goto out;
1084 status = SMB_VFS_CREATE_FILE(
1085 conn, /* conn */
1086 req, /* req */
1087 0, /* root_dir_fid */
1088 smb_fname, /* fname */
1089 access_mask, /* access_mask */
1090 share_mode, /* share_access */
1091 create_disposition, /* create_disposition*/
1092 create_options, /* create_options */
1093 open_attr, /* file_attributes */
1094 oplock_request, /* oplock_request */
1095 open_size, /* allocation_size */
1096 NULL, /* sd */
1097 ea_list, /* ea_list */
1098 &fsp, /* result */
1099 &smb_action); /* psbuf */
1101 if (!NT_STATUS_IS_OK(status)) {
1102 if (open_was_deferred(req->mid)) {
1103 /* We have re-scheduled this call. */
1104 goto out;
1106 reply_openerror(req, status);
1107 goto out;
1110 size = get_file_size_stat(&smb_fname->st);
1111 fattr = dos_mode(conn, smb_fname);
1112 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1113 inode = smb_fname->st.st_ex_ino;
1114 if (fattr & aDIR) {
1115 close_file(req, fsp, ERROR_CLOSE);
1116 reply_doserror(req, ERRDOS,ERRnoaccess);
1117 goto out;
1120 /* Realloc the size of parameters and data we will return */
1121 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1122 if(*pparams == NULL ) {
1123 reply_nterror(req, NT_STATUS_NO_MEMORY);
1124 goto out;
1126 params = *pparams;
1128 SSVAL(params,0,fsp->fnum);
1129 SSVAL(params,2,fattr);
1130 srv_put_dos_date2(params,4, mtime);
1131 SIVAL(params,8, (uint32)size);
1132 SSVAL(params,12,deny_mode);
1133 SSVAL(params,14,0); /* open_type - file or directory. */
1134 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1136 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1137 smb_action |= EXTENDED_OPLOCK_GRANTED;
1140 SSVAL(params,18,smb_action);
1143 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1145 SIVAL(params,20,inode);
1146 SSVAL(params,24,0); /* Padding. */
1147 if (flags & 8) {
1148 uint32 ea_size = estimate_ea_size(conn, fsp,
1149 fsp->fsp_name->base_name);
1150 SIVAL(params, 26, ea_size);
1151 } else {
1152 SIVAL(params, 26, 0);
1155 /* Send the required number of replies */
1156 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1157 out:
1158 TALLOC_FREE(smb_fname);
1161 /*********************************************************
1162 Routine to check if a given string matches exactly.
1163 as a special case a mask of "." does NOT match. That
1164 is required for correct wildcard semantics
1165 Case can be significant or not.
1166 **********************************************************/
1168 static bool exact_match(bool has_wild,
1169 bool case_sensitive,
1170 const char *str,
1171 const char *mask)
1173 if (mask[0] == '.' && mask[1] == 0) {
1174 return false;
1177 if (has_wild) {
1178 return false;
1181 if (case_sensitive) {
1182 return strcmp(str,mask)==0;
1183 } else {
1184 return StrCaseCmp(str,mask) == 0;
1188 /****************************************************************************
1189 Return the filetype for UNIX extensions.
1190 ****************************************************************************/
1192 static uint32 unix_filetype(mode_t mode)
1194 if(S_ISREG(mode))
1195 return UNIX_TYPE_FILE;
1196 else if(S_ISDIR(mode))
1197 return UNIX_TYPE_DIR;
1198 #ifdef S_ISLNK
1199 else if(S_ISLNK(mode))
1200 return UNIX_TYPE_SYMLINK;
1201 #endif
1202 #ifdef S_ISCHR
1203 else if(S_ISCHR(mode))
1204 return UNIX_TYPE_CHARDEV;
1205 #endif
1206 #ifdef S_ISBLK
1207 else if(S_ISBLK(mode))
1208 return UNIX_TYPE_BLKDEV;
1209 #endif
1210 #ifdef S_ISFIFO
1211 else if(S_ISFIFO(mode))
1212 return UNIX_TYPE_FIFO;
1213 #endif
1214 #ifdef S_ISSOCK
1215 else if(S_ISSOCK(mode))
1216 return UNIX_TYPE_SOCKET;
1217 #endif
1219 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1220 return UNIX_TYPE_UNKNOWN;
1223 /****************************************************************************
1224 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1225 ****************************************************************************/
1227 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1229 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1230 const SMB_STRUCT_STAT *psbuf,
1231 uint32 perms,
1232 enum perm_type ptype,
1233 mode_t *ret_perms)
1235 mode_t ret = 0;
1237 if (perms == SMB_MODE_NO_CHANGE) {
1238 if (!VALID_STAT(*psbuf)) {
1239 return NT_STATUS_INVALID_PARAMETER;
1240 } else {
1241 *ret_perms = psbuf->st_ex_mode;
1242 return NT_STATUS_OK;
1246 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1247 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1248 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1249 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1250 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1251 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1252 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1253 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1254 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1255 #ifdef S_ISVTX
1256 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1257 #endif
1258 #ifdef S_ISGID
1259 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1260 #endif
1261 #ifdef S_ISUID
1262 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1263 #endif
1265 switch (ptype) {
1266 case PERM_NEW_FILE:
1267 /* Apply mode mask */
1268 ret &= lp_create_mask(SNUM(conn));
1269 /* Add in force bits */
1270 ret |= lp_force_create_mode(SNUM(conn));
1271 break;
1272 case PERM_NEW_DIR:
1273 ret &= lp_dir_mask(SNUM(conn));
1274 /* Add in force bits */
1275 ret |= lp_force_dir_mode(SNUM(conn));
1276 break;
1277 case PERM_EXISTING_FILE:
1278 /* Apply mode mask */
1279 ret &= lp_security_mask(SNUM(conn));
1280 /* Add in force bits */
1281 ret |= lp_force_security_mode(SNUM(conn));
1282 break;
1283 case PERM_EXISTING_DIR:
1284 /* Apply mode mask */
1285 ret &= lp_dir_security_mask(SNUM(conn));
1286 /* Add in force bits */
1287 ret |= lp_force_dir_security_mode(SNUM(conn));
1288 break;
1291 *ret_perms = ret;
1292 return NT_STATUS_OK;
1295 /****************************************************************************
1296 Needed to show the msdfs symlinks as directories. Modifies psbuf
1297 to be a directory if it's a msdfs link.
1298 ****************************************************************************/
1300 static bool check_msdfs_link(connection_struct *conn,
1301 const char *pathname,
1302 SMB_STRUCT_STAT *psbuf)
1304 int saved_errno = errno;
1305 if(lp_host_msdfs() &&
1306 lp_msdfs_root(SNUM(conn)) &&
1307 is_msdfs_link(conn, pathname, psbuf)) {
1309 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1310 "as a directory\n",
1311 pathname));
1312 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1313 errno = saved_errno;
1314 return true;
1316 errno = saved_errno;
1317 return false;
1321 /****************************************************************************
1322 Get a level dependent lanman2 dir entry.
1323 ****************************************************************************/
1325 struct smbd_dirptr_lanman2_state {
1326 connection_struct *conn;
1327 uint32_t info_level;
1328 bool check_mangled_names;
1329 bool has_wild;
1330 bool got_exact_match;
1333 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1334 void *private_data,
1335 const char *dname,
1336 const char *mask,
1337 char **_fname)
1339 struct smbd_dirptr_lanman2_state *state =
1340 (struct smbd_dirptr_lanman2_state *)private_data;
1341 bool ok;
1342 char mangled_name[13]; /* mangled 8.3 name. */
1343 bool got_match;
1344 const char *fname;
1346 /* Mangle fname if it's an illegal name. */
1347 if (mangle_must_mangle(dname, state->conn->params)) {
1348 ok = name_to_8_3(dname, mangled_name,
1349 true, state->conn->params);
1350 if (!ok) {
1351 return false;
1353 fname = mangled_name;
1354 } else {
1355 fname = dname;
1358 got_match = exact_match(state->has_wild,
1359 state->conn->case_sensitive,
1360 fname, mask);
1361 state->got_exact_match = got_match;
1362 if (!got_match) {
1363 got_match = mask_match(fname, mask,
1364 state->conn->case_sensitive);
1367 if(!got_match && state->check_mangled_names &&
1368 !mangle_is_8_3(fname, false, state->conn->params)) {
1370 * It turns out that NT matches wildcards against
1371 * both long *and* short names. This may explain some
1372 * of the wildcard wierdness from old DOS clients
1373 * that some people have been seeing.... JRA.
1375 /* Force the mangling into 8.3. */
1376 ok = name_to_8_3(fname, mangled_name,
1377 false, state->conn->params);
1378 if (!ok) {
1379 return false;
1382 got_match = exact_match(state->has_wild,
1383 state->conn->case_sensitive,
1384 mangled_name, mask);
1385 state->got_exact_match = got_match;
1386 if (!got_match) {
1387 got_match = mask_match(mangled_name, mask,
1388 state->conn->case_sensitive);
1392 if (!got_match) {
1393 return false;
1396 *_fname = talloc_strdup(ctx, fname);
1397 if (*_fname == NULL) {
1398 return false;
1401 return true;
1404 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1405 void *private_data,
1406 struct smb_filename *smb_fname,
1407 uint32_t *_mode)
1409 struct smbd_dirptr_lanman2_state *state =
1410 (struct smbd_dirptr_lanman2_state *)private_data;
1411 bool ms_dfs_link = false;
1412 uint32_t mode = 0;
1414 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1415 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1416 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1417 "Couldn't lstat [%s] (%s)\n",
1418 smb_fname_str_dbg(smb_fname),
1419 strerror(errno)));
1420 return false;
1422 } else if (!VALID_STAT(smb_fname->st) &&
1423 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1424 /* Needed to show the msdfs symlinks as
1425 * directories */
1427 ms_dfs_link = check_msdfs_link(state->conn,
1428 smb_fname->base_name,
1429 &smb_fname->st);
1430 if (!ms_dfs_link) {
1431 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1432 "Couldn't stat [%s] (%s)\n",
1433 smb_fname_str_dbg(smb_fname),
1434 strerror(errno)));
1435 return false;
1439 if (ms_dfs_link) {
1440 mode = dos_mode_msdfs(state->conn, smb_fname);
1441 } else {
1442 mode = dos_mode(state->conn, smb_fname);
1445 *_mode = mode;
1446 return true;
1449 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1450 connection_struct *conn,
1451 uint16_t flags2,
1452 uint32_t info_level,
1453 struct ea_list *name_list,
1454 bool check_mangled_names,
1455 bool requires_resume_key,
1456 uint32_t mode,
1457 const char *fname,
1458 const struct smb_filename *smb_fname,
1459 uint64_t space_remaining,
1460 char *base_data,
1461 char **ppdata,
1462 char *end_data,
1463 bool *out_of_space,
1464 uint64_t *last_entry_off)
1466 char *p, *q, *pdata = *ppdata;
1467 uint32_t reskey=0;
1468 uint64_t file_size = 0;
1469 uint64_t allocation_size = 0;
1470 uint32_t len;
1471 struct timespec mdate_ts, adate_ts, create_date_ts;
1472 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1473 char *nameptr;
1474 char *last_entry_ptr;
1475 bool was_8_3;
1476 uint32_t nt_extmode; /* Used for NT connections instead of mode */
1478 *out_of_space = false;
1480 ZERO_STRUCT(mdate_ts);
1481 ZERO_STRUCT(adate_ts);
1482 ZERO_STRUCT(create_date_ts);
1484 if (!(mode & aDIR)) {
1485 file_size = get_file_size_stat(&smb_fname->st);
1487 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1489 mdate_ts = smb_fname->st.st_ex_mtime;
1490 adate_ts = smb_fname->st.st_ex_atime;
1491 create_date_ts = smb_fname->st.st_ex_btime;
1493 if (lp_dos_filetime_resolution(SNUM(conn))) {
1494 dos_filetime_timespec(&create_date_ts);
1495 dos_filetime_timespec(&mdate_ts);
1496 dos_filetime_timespec(&adate_ts);
1499 create_date = convert_timespec_to_time_t(create_date_ts);
1500 mdate = convert_timespec_to_time_t(mdate_ts);
1501 adate = convert_timespec_to_time_t(adate_ts);
1503 p = pdata;
1504 last_entry_ptr = p;
1506 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1508 switch (info_level) {
1509 case SMB_FIND_INFO_STANDARD:
1510 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1511 if(requires_resume_key) {
1512 SIVAL(p,0,reskey);
1513 p += 4;
1515 srv_put_dos_date2(p,0,create_date);
1516 srv_put_dos_date2(p,4,adate);
1517 srv_put_dos_date2(p,8,mdate);
1518 SIVAL(p,12,(uint32)file_size);
1519 SIVAL(p,16,(uint32)allocation_size);
1520 SSVAL(p,20,mode);
1521 p += 23;
1522 nameptr = p;
1523 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1524 p += ucs2_align(base_data, p, 0);
1526 len = srvstr_push(base_data, flags2, p,
1527 fname, PTR_DIFF(end_data, p),
1528 STR_TERMINATE);
1529 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1530 if (len > 2) {
1531 SCVAL(nameptr, -1, len - 2);
1532 } else {
1533 SCVAL(nameptr, -1, 0);
1535 } else {
1536 if (len > 1) {
1537 SCVAL(nameptr, -1, len - 1);
1538 } else {
1539 SCVAL(nameptr, -1, 0);
1542 p += len;
1543 break;
1545 case SMB_FIND_EA_SIZE:
1546 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1547 if (requires_resume_key) {
1548 SIVAL(p,0,reskey);
1549 p += 4;
1551 srv_put_dos_date2(p,0,create_date);
1552 srv_put_dos_date2(p,4,adate);
1553 srv_put_dos_date2(p,8,mdate);
1554 SIVAL(p,12,(uint32)file_size);
1555 SIVAL(p,16,(uint32)allocation_size);
1556 SSVAL(p,20,mode);
1558 unsigned int ea_size = estimate_ea_size(conn, NULL,
1559 smb_fname->base_name);
1560 SIVAL(p,22,ea_size); /* Extended attributes */
1562 p += 27;
1563 nameptr = p - 1;
1564 len = srvstr_push(base_data, flags2,
1565 p, fname, PTR_DIFF(end_data, p),
1566 STR_TERMINATE | STR_NOALIGN);
1567 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1568 if (len > 2) {
1569 len -= 2;
1570 } else {
1571 len = 0;
1573 } else {
1574 if (len > 1) {
1575 len -= 1;
1576 } else {
1577 len = 0;
1580 SCVAL(nameptr,0,len);
1581 p += len;
1582 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1583 break;
1585 case SMB_FIND_EA_LIST:
1587 struct ea_list *file_list = NULL;
1588 size_t ea_len = 0;
1590 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1591 if (!name_list) {
1592 return false;
1594 if (requires_resume_key) {
1595 SIVAL(p,0,reskey);
1596 p += 4;
1598 srv_put_dos_date2(p,0,create_date);
1599 srv_put_dos_date2(p,4,adate);
1600 srv_put_dos_date2(p,8,mdate);
1601 SIVAL(p,12,(uint32)file_size);
1602 SIVAL(p,16,(uint32)allocation_size);
1603 SSVAL(p,20,mode);
1604 p += 22; /* p now points to the EA area. */
1606 file_list = get_ea_list_from_file(ctx, conn, NULL,
1607 smb_fname->base_name,
1608 &ea_len);
1609 name_list = ea_list_union(name_list, file_list, &ea_len);
1611 /* We need to determine if this entry will fit in the space available. */
1612 /* Max string size is 255 bytes. */
1613 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1614 *out_of_space = true;
1615 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1616 return False; /* Not finished - just out of space */
1619 /* Push the ea_data followed by the name. */
1620 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1621 nameptr = p;
1622 len = srvstr_push(base_data, flags2,
1623 p + 1, fname, PTR_DIFF(end_data, p+1),
1624 STR_TERMINATE | STR_NOALIGN);
1625 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1626 if (len > 2) {
1627 len -= 2;
1628 } else {
1629 len = 0;
1631 } else {
1632 if (len > 1) {
1633 len -= 1;
1634 } else {
1635 len = 0;
1638 SCVAL(nameptr,0,len);
1639 p += len + 1;
1640 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1641 break;
1644 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1645 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1646 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1647 p += 4;
1648 SIVAL(p,0,reskey); p += 4;
1649 put_long_date_timespec(p,create_date_ts); p += 8;
1650 put_long_date_timespec(p,adate_ts); p += 8;
1651 put_long_date_timespec(p,mdate_ts); p += 8;
1652 put_long_date_timespec(p,mdate_ts); p += 8;
1653 SOFF_T(p,0,file_size); p += 8;
1654 SOFF_T(p,0,allocation_size); p += 8;
1655 SIVAL(p,0,nt_extmode); p += 4;
1656 q = p; p += 4; /* q is placeholder for name length. */
1658 unsigned int ea_size = estimate_ea_size(conn, NULL,
1659 smb_fname->base_name);
1660 SIVAL(p,0,ea_size); /* Extended attributes */
1661 p += 4;
1663 /* Clear the short name buffer. This is
1664 * IMPORTANT as not doing so will trigger
1665 * a Win2k client bug. JRA.
1667 if (!was_8_3 && check_mangled_names) {
1668 char mangled_name[13]; /* mangled 8.3 name. */
1669 if (!name_to_8_3(fname,mangled_name,True,
1670 conn->params)) {
1671 /* Error - mangle failed ! */
1672 memset(mangled_name,'\0',12);
1674 mangled_name[12] = 0;
1675 len = srvstr_push(base_data, flags2,
1676 p+2, mangled_name, 24,
1677 STR_UPPER|STR_UNICODE);
1678 if (len < 24) {
1679 memset(p + 2 + len,'\0',24 - len);
1681 SSVAL(p, 0, len);
1682 } else {
1683 memset(p,'\0',26);
1685 p += 2 + 24;
1686 len = srvstr_push(base_data, flags2, p,
1687 fname, PTR_DIFF(end_data, p),
1688 STR_TERMINATE_ASCII);
1689 SIVAL(q,0,len);
1690 p += len;
1691 SIVAL(p,0,0); /* Ensure any padding is null. */
1692 len = PTR_DIFF(p, pdata);
1693 len = (len + 3) & ~3;
1694 SIVAL(pdata,0,len);
1695 p = pdata + len;
1696 break;
1698 case SMB_FIND_FILE_DIRECTORY_INFO:
1699 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1700 p += 4;
1701 SIVAL(p,0,reskey); p += 4;
1702 put_long_date_timespec(p,create_date_ts); p += 8;
1703 put_long_date_timespec(p,adate_ts); p += 8;
1704 put_long_date_timespec(p,mdate_ts); p += 8;
1705 put_long_date_timespec(p,mdate_ts); p += 8;
1706 SOFF_T(p,0,file_size); p += 8;
1707 SOFF_T(p,0,allocation_size); p += 8;
1708 SIVAL(p,0,nt_extmode); p += 4;
1709 len = srvstr_push(base_data, flags2,
1710 p + 4, fname, PTR_DIFF(end_data, p+4),
1711 STR_TERMINATE_ASCII);
1712 SIVAL(p,0,len);
1713 p += 4 + len;
1714 SIVAL(p,0,0); /* Ensure any padding is null. */
1715 len = PTR_DIFF(p, pdata);
1716 len = (len + 3) & ~3;
1717 SIVAL(pdata,0,len);
1718 p = pdata + len;
1719 break;
1721 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1722 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1723 p += 4;
1724 SIVAL(p,0,reskey); p += 4;
1725 put_long_date_timespec(p,create_date_ts); p += 8;
1726 put_long_date_timespec(p,adate_ts); p += 8;
1727 put_long_date_timespec(p,mdate_ts); p += 8;
1728 put_long_date_timespec(p,mdate_ts); p += 8;
1729 SOFF_T(p,0,file_size); p += 8;
1730 SOFF_T(p,0,allocation_size); p += 8;
1731 SIVAL(p,0,nt_extmode); p += 4;
1732 q = p; p += 4; /* q is placeholder for name length. */
1734 unsigned int ea_size = estimate_ea_size(conn, NULL,
1735 smb_fname->base_name);
1736 SIVAL(p,0,ea_size); /* Extended attributes */
1737 p +=4;
1739 len = srvstr_push(base_data, flags2, p,
1740 fname, PTR_DIFF(end_data, p),
1741 STR_TERMINATE_ASCII);
1742 SIVAL(q, 0, len);
1743 p += len;
1745 SIVAL(p,0,0); /* Ensure any padding is null. */
1746 len = PTR_DIFF(p, pdata);
1747 len = (len + 3) & ~3;
1748 SIVAL(pdata,0,len);
1749 p = pdata + len;
1750 break;
1752 case SMB_FIND_FILE_NAMES_INFO:
1753 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1754 p += 4;
1755 SIVAL(p,0,reskey); p += 4;
1756 p += 4;
1757 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1758 acl on a dir (tridge) */
1759 len = srvstr_push(base_data, flags2, p,
1760 fname, PTR_DIFF(end_data, p),
1761 STR_TERMINATE_ASCII);
1762 SIVAL(p, -4, len);
1763 p += len;
1764 SIVAL(p,0,0); /* Ensure any padding is null. */
1765 len = PTR_DIFF(p, pdata);
1766 len = (len + 3) & ~3;
1767 SIVAL(pdata,0,len);
1768 p = pdata + len;
1769 break;
1771 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1772 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1773 p += 4;
1774 SIVAL(p,0,reskey); p += 4;
1775 put_long_date_timespec(p,create_date_ts); p += 8;
1776 put_long_date_timespec(p,adate_ts); p += 8;
1777 put_long_date_timespec(p,mdate_ts); p += 8;
1778 put_long_date_timespec(p,mdate_ts); p += 8;
1779 SOFF_T(p,0,file_size); p += 8;
1780 SOFF_T(p,0,allocation_size); p += 8;
1781 SIVAL(p,0,nt_extmode); p += 4;
1782 q = p; p += 4; /* q is placeholder for name length. */
1784 unsigned int ea_size = estimate_ea_size(conn, NULL,
1785 smb_fname->base_name);
1786 SIVAL(p,0,ea_size); /* Extended attributes */
1787 p +=4;
1789 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1790 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1791 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1792 len = srvstr_push(base_data, flags2, p,
1793 fname, PTR_DIFF(end_data, p),
1794 STR_TERMINATE_ASCII);
1795 SIVAL(q, 0, len);
1796 p += len;
1797 SIVAL(p,0,0); /* Ensure any padding is null. */
1798 len = PTR_DIFF(p, pdata);
1799 len = (len + 3) & ~3;
1800 SIVAL(pdata,0,len);
1801 p = pdata + len;
1802 break;
1804 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1805 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1806 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1807 p += 4;
1808 SIVAL(p,0,reskey); p += 4;
1809 put_long_date_timespec(p,create_date_ts); p += 8;
1810 put_long_date_timespec(p,adate_ts); p += 8;
1811 put_long_date_timespec(p,mdate_ts); p += 8;
1812 put_long_date_timespec(p,mdate_ts); p += 8;
1813 SOFF_T(p,0,file_size); p += 8;
1814 SOFF_T(p,0,allocation_size); p += 8;
1815 SIVAL(p,0,nt_extmode); p += 4;
1816 q = p; p += 4; /* q is placeholder for name length */
1818 unsigned int ea_size = estimate_ea_size(conn, NULL,
1819 smb_fname->base_name);
1820 SIVAL(p,0,ea_size); /* Extended attributes */
1821 p +=4;
1823 /* Clear the short name buffer. This is
1824 * IMPORTANT as not doing so will trigger
1825 * a Win2k client bug. JRA.
1827 if (!was_8_3 && check_mangled_names) {
1828 char mangled_name[13]; /* mangled 8.3 name. */
1829 if (!name_to_8_3(fname,mangled_name,True,
1830 conn->params)) {
1831 /* Error - mangle failed ! */
1832 memset(mangled_name,'\0',12);
1834 mangled_name[12] = 0;
1835 len = srvstr_push(base_data, flags2,
1836 p+2, mangled_name, 24,
1837 STR_UPPER|STR_UNICODE);
1838 SSVAL(p, 0, len);
1839 if (len < 24) {
1840 memset(p + 2 + len,'\0',24 - len);
1842 SSVAL(p, 0, len);
1843 } else {
1844 memset(p,'\0',26);
1846 p += 26;
1847 SSVAL(p,0,0); p += 2; /* Reserved ? */
1848 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1849 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1850 len = srvstr_push(base_data, flags2, p,
1851 fname, PTR_DIFF(end_data, p),
1852 STR_TERMINATE_ASCII);
1853 SIVAL(q,0,len);
1854 p += len;
1855 SIVAL(p,0,0); /* Ensure any padding is null. */
1856 len = PTR_DIFF(p, pdata);
1857 len = (len + 3) & ~3;
1858 SIVAL(pdata,0,len);
1859 p = pdata + len;
1860 break;
1862 /* CIFS UNIX Extension. */
1864 case SMB_FIND_FILE_UNIX:
1865 case SMB_FIND_FILE_UNIX_INFO2:
1866 p+= 4;
1867 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1869 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1871 if (info_level == SMB_FIND_FILE_UNIX) {
1872 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1873 p = store_file_unix_basic(conn, p,
1874 NULL, &smb_fname->st);
1875 len = srvstr_push(base_data, flags2, p,
1876 fname, PTR_DIFF(end_data, p),
1877 STR_TERMINATE);
1878 } else {
1879 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1880 p = store_file_unix_basic_info2(conn, p,
1881 NULL, &smb_fname->st);
1882 nameptr = p;
1883 p += 4;
1884 len = srvstr_push(base_data, flags2, p, fname,
1885 PTR_DIFF(end_data, p), 0);
1886 SIVAL(nameptr, 0, len);
1889 p += len;
1890 SIVAL(p,0,0); /* Ensure any padding is null. */
1892 len = PTR_DIFF(p, pdata);
1893 len = (len + 3) & ~3;
1894 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1895 p = pdata + len;
1896 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1898 break;
1900 default:
1901 return false;
1904 if (PTR_DIFF(p,pdata) > space_remaining) {
1905 *out_of_space = true;
1906 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1907 return false; /* Not finished - just out of space */
1910 /* Setup the last entry pointer, as an offset from base_data */
1911 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1912 /* Advance the data pointer to the next slot */
1913 *ppdata = p;
1915 return true;
1918 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1919 connection_struct *conn,
1920 struct dptr_struct *dirptr,
1921 uint16 flags2,
1922 const char *path_mask,
1923 uint32 dirtype,
1924 int info_level,
1925 int requires_resume_key,
1926 bool dont_descend,
1927 bool ask_sharemode,
1928 char **ppdata,
1929 char *base_data,
1930 char *end_data,
1931 int space_remaining,
1932 bool *out_of_space,
1933 bool *got_exact_match,
1934 int *_last_entry_off,
1935 struct ea_list *name_list)
1937 const char *p;
1938 const char *mask = NULL;
1939 long prev_dirpos = 0;
1940 uint32_t mode = 0;
1941 char *fname = NULL;
1942 struct smb_filename *smb_fname = NULL;
1943 struct smbd_dirptr_lanman2_state state;
1944 bool ok;
1945 uint64_t last_entry_off = 0;
1947 ZERO_STRUCT(state);
1948 state.conn = conn;
1949 state.info_level = info_level;
1950 state.check_mangled_names = lp_manglednames(conn->params);
1951 state.has_wild = dptr_has_wild(dirptr);
1952 state.got_exact_match = false;
1954 *out_of_space = false;
1955 *got_exact_match = false;
1957 p = strrchr_m(path_mask,'/');
1958 if(p != NULL) {
1959 if(p[1] == '\0') {
1960 mask = "*.*";
1961 } else {
1962 mask = p+1;
1964 } else {
1965 mask = path_mask;
1968 ok = smbd_dirptr_get_entry(ctx,
1969 dirptr,
1970 mask,
1971 dirtype,
1972 dont_descend,
1973 ask_sharemode,
1974 smbd_dirptr_lanman2_match_fn,
1975 smbd_dirptr_lanman2_mode_fn,
1976 &state,
1977 &fname,
1978 &smb_fname,
1979 &mode,
1980 &prev_dirpos);
1981 if (!ok) {
1982 return false;
1985 *got_exact_match = state.got_exact_match;
1987 ok = smbd_marshall_dir_entry(ctx,
1988 conn,
1989 flags2,
1990 info_level,
1991 name_list,
1992 state.check_mangled_names,
1993 requires_resume_key,
1994 mode,
1995 fname,
1996 smb_fname,
1997 space_remaining,
1998 base_data,
1999 ppdata,
2000 end_data,
2001 out_of_space,
2002 &last_entry_off);
2003 TALLOC_FREE(fname);
2004 TALLOC_FREE(smb_fname);
2005 if (*out_of_space) {
2006 dptr_SeekDir(dirptr, prev_dirpos);
2007 return false;
2009 if (!ok) {
2010 return false;
2013 *_last_entry_off = last_entry_off;
2014 return true;
2017 /****************************************************************************
2018 Reply to a TRANS2_FINDFIRST.
2019 ****************************************************************************/
2021 static void call_trans2findfirst(connection_struct *conn,
2022 struct smb_request *req,
2023 char **pparams, int total_params,
2024 char **ppdata, int total_data,
2025 unsigned int max_data_bytes)
2027 /* We must be careful here that we don't return more than the
2028 allowed number of data bytes. If this means returning fewer than
2029 maxentries then so be it. We assume that the redirector has
2030 enough room for the fixed number of parameter bytes it has
2031 requested. */
2032 struct smb_filename *smb_dname = NULL;
2033 char *params = *pparams;
2034 char *pdata = *ppdata;
2035 char *data_end;
2036 uint32 dirtype;
2037 int maxentries;
2038 uint16 findfirst_flags;
2039 bool close_after_first;
2040 bool close_if_end;
2041 bool requires_resume_key;
2042 int info_level;
2043 char *directory = NULL;
2044 char *mask = NULL;
2045 char *p;
2046 int last_entry_off=0;
2047 int dptr_num = -1;
2048 int numentries = 0;
2049 int i;
2050 bool finished = False;
2051 bool dont_descend = False;
2052 bool out_of_space = False;
2053 int space_remaining;
2054 bool mask_contains_wcard = False;
2055 struct ea_list *ea_list = NULL;
2056 NTSTATUS ntstatus = NT_STATUS_OK;
2057 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2058 TALLOC_CTX *ctx = talloc_tos();
2059 struct dptr_struct *dirptr = NULL;
2060 struct smbd_server_connection *sconn = smbd_server_conn;
2062 if (total_params < 13) {
2063 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2064 goto out;
2067 dirtype = SVAL(params,0);
2068 maxentries = SVAL(params,2);
2069 findfirst_flags = SVAL(params,4);
2070 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2071 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2072 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2073 info_level = SVAL(params,6);
2075 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2076 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2077 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2078 info_level, max_data_bytes));
2080 if (!maxentries) {
2081 /* W2K3 seems to treat zero as 1. */
2082 maxentries = 1;
2085 switch (info_level) {
2086 case SMB_FIND_INFO_STANDARD:
2087 case SMB_FIND_EA_SIZE:
2088 case SMB_FIND_EA_LIST:
2089 case SMB_FIND_FILE_DIRECTORY_INFO:
2090 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2091 case SMB_FIND_FILE_NAMES_INFO:
2092 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2093 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2094 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2095 break;
2096 case SMB_FIND_FILE_UNIX:
2097 case SMB_FIND_FILE_UNIX_INFO2:
2098 /* Always use filesystem for UNIX mtime query. */
2099 ask_sharemode = false;
2100 if (!lp_unix_extensions()) {
2101 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2102 goto out;
2104 break;
2105 default:
2106 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2107 goto out;
2110 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2111 params+12, total_params - 12,
2112 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2113 if (!NT_STATUS_IS_OK(ntstatus)) {
2114 reply_nterror(req, ntstatus);
2115 goto out;
2118 ntstatus = filename_convert(ctx, conn,
2119 req->flags2 & FLAGS2_DFS_PATHNAMES,
2120 directory,
2121 (UCF_SAVE_LCOMP |
2122 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2123 &mask_contains_wcard,
2124 &smb_dname);
2125 if (!NT_STATUS_IS_OK(ntstatus)) {
2126 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2127 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2128 ERRSRV, ERRbadpath);
2129 goto out;
2131 reply_nterror(req, ntstatus);
2132 goto out;
2135 mask = smb_dname->original_lcomp;
2137 directory = smb_dname->base_name;
2139 p = strrchr_m(directory,'/');
2140 if(p == NULL) {
2141 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2142 if((directory[0] == '.') && (directory[1] == '\0')) {
2143 mask = talloc_strdup(ctx,"*");
2144 if (!mask) {
2145 reply_nterror(req, NT_STATUS_NO_MEMORY);
2146 goto out;
2148 mask_contains_wcard = True;
2150 directory = talloc_strdup(talloc_tos(), "./");
2151 if (!directory) {
2152 reply_nterror(req, NT_STATUS_NO_MEMORY);
2153 goto out;
2155 } else {
2156 *p = 0;
2159 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2161 if (info_level == SMB_FIND_EA_LIST) {
2162 uint32 ea_size;
2164 if (total_data < 4) {
2165 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2166 goto out;
2169 ea_size = IVAL(pdata,0);
2170 if (ea_size != total_data) {
2171 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2172 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2173 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2174 goto out;
2177 if (!lp_ea_support(SNUM(conn))) {
2178 reply_doserror(req, ERRDOS, ERReasnotsupported);
2179 goto out;
2182 /* Pull out the list of names. */
2183 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2184 if (!ea_list) {
2185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2186 goto out;
2190 *ppdata = (char *)SMB_REALLOC(
2191 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2192 if(*ppdata == NULL ) {
2193 reply_nterror(req, NT_STATUS_NO_MEMORY);
2194 goto out;
2196 pdata = *ppdata;
2197 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2199 /* Realloc the params space */
2200 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2201 if (*pparams == NULL) {
2202 reply_nterror(req, NT_STATUS_NO_MEMORY);
2203 goto out;
2205 params = *pparams;
2207 /* Save the wildcard match and attribs we are using on this directory -
2208 needed as lanman2 assumes these are being saved between calls */
2210 ntstatus = dptr_create(conn,
2211 directory,
2212 False,
2213 True,
2214 req->smbpid,
2215 mask,
2216 mask_contains_wcard,
2217 dirtype,
2218 &dirptr);
2220 if (!NT_STATUS_IS_OK(ntstatus)) {
2221 reply_nterror(req, ntstatus);
2222 goto out;
2225 dptr_num = dptr_dnum(dirptr);
2226 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2228 /* Initialize per TRANS2_FIND_FIRST operation data */
2229 dptr_init_search_op(dirptr);
2231 /* We don't need to check for VOL here as this is returned by
2232 a different TRANS2 call. */
2234 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2235 directory,lp_dontdescend(SNUM(conn))));
2236 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2237 dont_descend = True;
2239 p = pdata;
2240 space_remaining = max_data_bytes;
2241 out_of_space = False;
2243 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2244 bool got_exact_match = False;
2246 /* this is a heuristic to avoid seeking the dirptr except when
2247 absolutely necessary. It allows for a filename of about 40 chars */
2248 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2249 out_of_space = True;
2250 finished = False;
2251 } else {
2252 finished = !get_lanman2_dir_entry(ctx,
2253 conn,
2254 dirptr,
2255 req->flags2,
2256 mask,dirtype,info_level,
2257 requires_resume_key,dont_descend,
2258 ask_sharemode,
2259 &p,pdata,data_end,
2260 space_remaining, &out_of_space,
2261 &got_exact_match,
2262 &last_entry_off, ea_list);
2265 if (finished && out_of_space)
2266 finished = False;
2268 if (!finished && !out_of_space)
2269 numentries++;
2272 * As an optimisation if we know we aren't looking
2273 * for a wildcard name (ie. the name matches the wildcard exactly)
2274 * then we can finish on any (first) match.
2275 * This speeds up large directory searches. JRA.
2278 if(got_exact_match)
2279 finished = True;
2281 /* Ensure space_remaining never goes -ve. */
2282 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2283 space_remaining = 0;
2284 out_of_space = true;
2285 } else {
2286 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2290 /* Check if we can close the dirptr */
2291 if(close_after_first || (finished && close_if_end)) {
2292 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2293 dptr_close(sconn, &dptr_num);
2297 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2298 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2299 * the protocol level is less than NT1. Tested with smbclient. JRA.
2300 * This should fix the OS/2 client bug #2335.
2303 if(numentries == 0) {
2304 dptr_close(sconn, &dptr_num);
2305 if (Protocol < PROTOCOL_NT1) {
2306 reply_doserror(req, ERRDOS, ERRnofiles);
2307 goto out;
2308 } else {
2309 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2310 ERRDOS, ERRbadfile);
2311 goto out;
2315 /* At this point pdata points to numentries directory entries. */
2317 /* Set up the return parameter block */
2318 SSVAL(params,0,dptr_num);
2319 SSVAL(params,2,numentries);
2320 SSVAL(params,4,finished);
2321 SSVAL(params,6,0); /* Never an EA error */
2322 SSVAL(params,8,last_entry_off);
2324 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2325 max_data_bytes);
2327 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2328 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2329 if (!directory) {
2330 reply_nterror(req, NT_STATUS_NO_MEMORY);
2334 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2335 smb_fn_name(req->cmd),
2336 mask, directory, dirtype, numentries ) );
2339 * Force a name mangle here to ensure that the
2340 * mask as an 8.3 name is top of the mangled cache.
2341 * The reasons for this are subtle. Don't remove
2342 * this code unless you know what you are doing
2343 * (see PR#13758). JRA.
2346 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2347 char mangled_name[13];
2348 name_to_8_3(mask, mangled_name, True, conn->params);
2350 out:
2351 TALLOC_FREE(smb_dname);
2352 return;
2355 /****************************************************************************
2356 Reply to a TRANS2_FINDNEXT.
2357 ****************************************************************************/
2359 static void call_trans2findnext(connection_struct *conn,
2360 struct smb_request *req,
2361 char **pparams, int total_params,
2362 char **ppdata, int total_data,
2363 unsigned int max_data_bytes)
2365 /* We must be careful here that we don't return more than the
2366 allowed number of data bytes. If this means returning fewer than
2367 maxentries then so be it. We assume that the redirector has
2368 enough room for the fixed number of parameter bytes it has
2369 requested. */
2370 char *params = *pparams;
2371 char *pdata = *ppdata;
2372 char *data_end;
2373 int dptr_num;
2374 int maxentries;
2375 uint16 info_level;
2376 uint32 resume_key;
2377 uint16 findnext_flags;
2378 bool close_after_request;
2379 bool close_if_end;
2380 bool requires_resume_key;
2381 bool continue_bit;
2382 bool mask_contains_wcard = False;
2383 char *resume_name = NULL;
2384 const char *mask = NULL;
2385 const char *directory = NULL;
2386 char *p = NULL;
2387 uint16 dirtype;
2388 int numentries = 0;
2389 int i, last_entry_off=0;
2390 bool finished = False;
2391 bool dont_descend = False;
2392 bool out_of_space = False;
2393 int space_remaining;
2394 struct ea_list *ea_list = NULL;
2395 NTSTATUS ntstatus = NT_STATUS_OK;
2396 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2397 TALLOC_CTX *ctx = talloc_tos();
2398 struct dptr_struct *dirptr;
2399 struct smbd_server_connection *sconn = smbd_server_conn;
2401 if (total_params < 13) {
2402 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2403 return;
2406 dptr_num = SVAL(params,0);
2407 maxentries = SVAL(params,2);
2408 info_level = SVAL(params,4);
2409 resume_key = IVAL(params,6);
2410 findnext_flags = SVAL(params,10);
2411 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2412 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2413 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2414 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2416 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2417 params+12,
2418 total_params - 12, STR_TERMINATE, &ntstatus,
2419 &mask_contains_wcard);
2420 if (!NT_STATUS_IS_OK(ntstatus)) {
2421 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2422 complain (it thinks we're asking for the directory above the shared
2423 path or an invalid name). Catch this as the resume name is only compared, never used in
2424 a file access. JRA. */
2425 srvstr_pull_talloc(ctx, params, req->flags2,
2426 &resume_name, params+12,
2427 total_params - 12,
2428 STR_TERMINATE);
2430 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2431 reply_nterror(req, ntstatus);
2432 return;
2436 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2437 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2438 resume_key = %d resume name = %s continue=%d level = %d\n",
2439 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2440 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2442 if (!maxentries) {
2443 /* W2K3 seems to treat zero as 1. */
2444 maxentries = 1;
2447 switch (info_level) {
2448 case SMB_FIND_INFO_STANDARD:
2449 case SMB_FIND_EA_SIZE:
2450 case SMB_FIND_EA_LIST:
2451 case SMB_FIND_FILE_DIRECTORY_INFO:
2452 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2453 case SMB_FIND_FILE_NAMES_INFO:
2454 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2455 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2456 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2457 break;
2458 case SMB_FIND_FILE_UNIX:
2459 case SMB_FIND_FILE_UNIX_INFO2:
2460 /* Always use filesystem for UNIX mtime query. */
2461 ask_sharemode = false;
2462 if (!lp_unix_extensions()) {
2463 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2464 return;
2466 break;
2467 default:
2468 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2469 return;
2472 if (info_level == SMB_FIND_EA_LIST) {
2473 uint32 ea_size;
2475 if (total_data < 4) {
2476 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2477 return;
2480 ea_size = IVAL(pdata,0);
2481 if (ea_size != total_data) {
2482 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2483 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2484 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2485 return;
2488 if (!lp_ea_support(SNUM(conn))) {
2489 reply_doserror(req, ERRDOS, ERReasnotsupported);
2490 return;
2493 /* Pull out the list of names. */
2494 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2495 if (!ea_list) {
2496 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2497 return;
2501 *ppdata = (char *)SMB_REALLOC(
2502 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2503 if(*ppdata == NULL) {
2504 reply_nterror(req, NT_STATUS_NO_MEMORY);
2505 return;
2508 pdata = *ppdata;
2509 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2511 /* Realloc the params space */
2512 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2513 if(*pparams == NULL ) {
2514 reply_nterror(req, NT_STATUS_NO_MEMORY);
2515 return;
2518 params = *pparams;
2520 /* Check that the dptr is valid */
2521 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2522 reply_doserror(req, ERRDOS, ERRnofiles);
2523 return;
2526 directory = dptr_path(sconn, dptr_num);
2528 /* Get the wildcard mask from the dptr */
2529 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2530 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2531 reply_doserror(req, ERRDOS, ERRnofiles);
2532 return;
2535 mask = p;
2537 /* Get the attr mask from the dptr */
2538 dirtype = dptr_attr(sconn, dptr_num);
2540 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2541 dptr_num, mask, dirtype,
2542 (long)dirptr,
2543 dptr_TellDir(dirptr)));
2545 /* Initialize per TRANS2_FIND_NEXT operation data */
2546 dptr_init_search_op(dirptr);
2548 /* We don't need to check for VOL here as this is returned by
2549 a different TRANS2 call. */
2551 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2552 directory,lp_dontdescend(SNUM(conn))));
2553 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2554 dont_descend = True;
2556 p = pdata;
2557 space_remaining = max_data_bytes;
2558 out_of_space = False;
2561 * Seek to the correct position. We no longer use the resume key but
2562 * depend on the last file name instead.
2565 if(*resume_name && !continue_bit) {
2566 SMB_STRUCT_STAT st;
2568 long current_pos = 0;
2570 * Remember, name_to_8_3 is called by
2571 * get_lanman2_dir_entry(), so the resume name
2572 * could be mangled. Ensure we check the unmangled name.
2575 if (mangle_is_mangled(resume_name, conn->params)) {
2576 char *new_resume_name = NULL;
2577 mangle_lookup_name_from_8_3(ctx,
2578 resume_name,
2579 &new_resume_name,
2580 conn->params);
2581 if (new_resume_name) {
2582 resume_name = new_resume_name;
2587 * Fix for NT redirector problem triggered by resume key indexes
2588 * changing between directory scans. We now return a resume key of 0
2589 * and instead look for the filename to continue from (also given
2590 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2591 * findfirst/findnext (as is usual) then the directory pointer
2592 * should already be at the correct place.
2595 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2596 } /* end if resume_name && !continue_bit */
2598 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2599 bool got_exact_match = False;
2601 /* this is a heuristic to avoid seeking the dirptr except when
2602 absolutely necessary. It allows for a filename of about 40 chars */
2603 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2604 out_of_space = True;
2605 finished = False;
2606 } else {
2607 finished = !get_lanman2_dir_entry(ctx,
2608 conn,
2609 dirptr,
2610 req->flags2,
2611 mask,dirtype,info_level,
2612 requires_resume_key,dont_descend,
2613 ask_sharemode,
2614 &p,pdata,data_end,
2615 space_remaining, &out_of_space,
2616 &got_exact_match,
2617 &last_entry_off, ea_list);
2620 if (finished && out_of_space)
2621 finished = False;
2623 if (!finished && !out_of_space)
2624 numentries++;
2627 * As an optimisation if we know we aren't looking
2628 * for a wildcard name (ie. the name matches the wildcard exactly)
2629 * then we can finish on any (first) match.
2630 * This speeds up large directory searches. JRA.
2633 if(got_exact_match)
2634 finished = True;
2636 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2639 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2640 smb_fn_name(req->cmd),
2641 mask, directory, dirtype, numentries ) );
2643 /* Check if we can close the dirptr */
2644 if(close_after_request || (finished && close_if_end)) {
2645 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2646 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2649 /* Set up the return parameter block */
2650 SSVAL(params,0,numentries);
2651 SSVAL(params,2,finished);
2652 SSVAL(params,4,0); /* Never an EA error */
2653 SSVAL(params,6,last_entry_off);
2655 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2656 max_data_bytes);
2658 return;
2661 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2663 E_md4hash(lp_servicename(SNUM(conn)),objid);
2664 return objid;
2667 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2669 SMB_ASSERT(extended_info != NULL);
2671 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2672 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2673 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2674 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2675 #ifdef SAMBA_VERSION_REVISION
2676 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2677 #endif
2678 extended_info->samba_subversion = 0;
2679 #ifdef SAMBA_VERSION_RC_RELEASE
2680 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2681 #else
2682 #ifdef SAMBA_VERSION_PRE_RELEASE
2683 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2684 #endif
2685 #endif
2686 #ifdef SAMBA_VERSION_VENDOR_PATCH
2687 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2688 #endif
2689 extended_info->samba_gitcommitdate = 0;
2690 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2691 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2692 #endif
2694 memset(extended_info->samba_version_string, 0,
2695 sizeof(extended_info->samba_version_string));
2697 snprintf (extended_info->samba_version_string,
2698 sizeof(extended_info->samba_version_string),
2699 "%s", samba_version_string());
2702 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2703 TALLOC_CTX *mem_ctx,
2704 uint16_t info_level,
2705 uint16_t flags2,
2706 unsigned int max_data_bytes,
2707 char **ppdata,
2708 int *ret_data_len)
2710 char *pdata, *end_data;
2711 int data_len = 0, len;
2712 const char *vname = volume_label(SNUM(conn));
2713 int snum = SNUM(conn);
2714 char *fstype = lp_fstype(SNUM(conn));
2715 uint32 additional_flags = 0;
2716 struct smb_filename *smb_fname_dot = NULL;
2717 SMB_STRUCT_STAT st;
2718 NTSTATUS status;
2720 if (IS_IPC(conn)) {
2721 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2722 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2723 "info level (0x%x) on IPC$.\n",
2724 (unsigned int)info_level));
2725 return NT_STATUS_ACCESS_DENIED;
2729 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2731 status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL,
2732 &smb_fname_dot);
2733 if (!NT_STATUS_IS_OK(status)) {
2734 return status;
2737 if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) {
2738 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2739 TALLOC_FREE(smb_fname_dot);
2740 return map_nt_error_from_unix(errno);
2743 st = smb_fname_dot->st;
2744 TALLOC_FREE(smb_fname_dot);
2746 *ppdata = (char *)SMB_REALLOC(
2747 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2748 if (*ppdata == NULL) {
2749 return NT_STATUS_NO_MEMORY;
2752 pdata = *ppdata;
2753 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2754 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2756 switch (info_level) {
2757 case SMB_INFO_ALLOCATION:
2759 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2760 data_len = 18;
2761 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2762 return map_nt_error_from_unix(errno);
2765 block_size = lp_block_size(snum);
2766 if (bsize < block_size) {
2767 uint64_t factor = block_size/bsize;
2768 bsize = block_size;
2769 dsize /= factor;
2770 dfree /= factor;
2772 if (bsize > block_size) {
2773 uint64_t factor = bsize/block_size;
2774 bsize = block_size;
2775 dsize *= factor;
2776 dfree *= factor;
2778 bytes_per_sector = 512;
2779 sectors_per_unit = bsize/bytes_per_sector;
2781 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2782 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2783 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2785 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2786 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2787 SIVAL(pdata,l1_cUnit,dsize);
2788 SIVAL(pdata,l1_cUnitAvail,dfree);
2789 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2790 break;
2793 case SMB_INFO_VOLUME:
2794 /* Return volume name */
2796 * Add volume serial number - hash of a combination of
2797 * the called hostname and the service name.
2799 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2801 * Win2k3 and previous mess this up by sending a name length
2802 * one byte short. I believe only older clients (OS/2 Win9x) use
2803 * this call so try fixing this by adding a terminating null to
2804 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2806 len = srvstr_push(
2807 pdata, flags2,
2808 pdata+l2_vol_szVolLabel, vname,
2809 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2810 STR_NOALIGN|STR_TERMINATE);
2811 SCVAL(pdata,l2_vol_cch,len);
2812 data_len = l2_vol_szVolLabel + len;
2813 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2814 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2815 len, vname));
2816 break;
2818 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2819 case SMB_FS_ATTRIBUTE_INFORMATION:
2821 additional_flags = 0;
2822 #if defined(HAVE_SYS_QUOTAS)
2823 additional_flags |= FILE_VOLUME_QUOTAS;
2824 #endif
2826 if(lp_nt_acl_support(SNUM(conn))) {
2827 additional_flags |= FILE_PERSISTENT_ACLS;
2830 /* Capabilities are filled in at connection time through STATVFS call */
2831 additional_flags |= conn->fs_capabilities;
2833 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2834 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2835 additional_flags); /* FS ATTRIBUTES */
2837 SIVAL(pdata,4,255); /* Max filename component length */
2838 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2839 and will think we can't do long filenames */
2840 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2841 PTR_DIFF(end_data, pdata+12),
2842 STR_UNICODE);
2843 SIVAL(pdata,8,len);
2844 data_len = 12 + len;
2845 break;
2847 case SMB_QUERY_FS_LABEL_INFO:
2848 case SMB_FS_LABEL_INFORMATION:
2849 len = srvstr_push(pdata, flags2, pdata+4, vname,
2850 PTR_DIFF(end_data, pdata+4), 0);
2851 data_len = 4 + len;
2852 SIVAL(pdata,0,len);
2853 break;
2855 case SMB_QUERY_FS_VOLUME_INFO:
2856 case SMB_FS_VOLUME_INFORMATION:
2859 * Add volume serial number - hash of a combination of
2860 * the called hostname and the service name.
2862 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2863 (str_checksum(get_local_machine_name())<<16));
2865 /* Max label len is 32 characters. */
2866 len = srvstr_push(pdata, flags2, pdata+18, vname,
2867 PTR_DIFF(end_data, pdata+18),
2868 STR_UNICODE);
2869 SIVAL(pdata,12,len);
2870 data_len = 18+len;
2872 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2873 (int)strlen(vname),vname, lp_servicename(snum)));
2874 break;
2876 case SMB_QUERY_FS_SIZE_INFO:
2877 case SMB_FS_SIZE_INFORMATION:
2879 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2880 data_len = 24;
2881 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2882 return map_nt_error_from_unix(errno);
2884 block_size = lp_block_size(snum);
2885 if (bsize < block_size) {
2886 uint64_t factor = block_size/bsize;
2887 bsize = block_size;
2888 dsize /= factor;
2889 dfree /= factor;
2891 if (bsize > block_size) {
2892 uint64_t factor = bsize/block_size;
2893 bsize = block_size;
2894 dsize *= factor;
2895 dfree *= factor;
2897 bytes_per_sector = 512;
2898 sectors_per_unit = bsize/bytes_per_sector;
2899 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2900 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2901 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2902 SBIG_UINT(pdata,0,dsize);
2903 SBIG_UINT(pdata,8,dfree);
2904 SIVAL(pdata,16,sectors_per_unit);
2905 SIVAL(pdata,20,bytes_per_sector);
2906 break;
2909 case SMB_FS_FULL_SIZE_INFORMATION:
2911 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2912 data_len = 32;
2913 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2914 return map_nt_error_from_unix(errno);
2916 block_size = lp_block_size(snum);
2917 if (bsize < block_size) {
2918 uint64_t factor = block_size/bsize;
2919 bsize = block_size;
2920 dsize /= factor;
2921 dfree /= factor;
2923 if (bsize > block_size) {
2924 uint64_t factor = bsize/block_size;
2925 bsize = block_size;
2926 dsize *= factor;
2927 dfree *= factor;
2929 bytes_per_sector = 512;
2930 sectors_per_unit = bsize/bytes_per_sector;
2931 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2932 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2933 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2934 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2935 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2936 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2937 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2938 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2939 break;
2942 case SMB_QUERY_FS_DEVICE_INFO:
2943 case SMB_FS_DEVICE_INFORMATION:
2944 data_len = 8;
2945 SIVAL(pdata,0,0); /* dev type */
2946 SIVAL(pdata,4,0); /* characteristics */
2947 break;
2949 #ifdef HAVE_SYS_QUOTAS
2950 case SMB_FS_QUOTA_INFORMATION:
2952 * what we have to send --metze:
2954 * Unknown1: 24 NULL bytes
2955 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2956 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2957 * Quota Flags: 2 byte :
2958 * Unknown3: 6 NULL bytes
2960 * 48 bytes total
2962 * details for Quota Flags:
2964 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2965 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2966 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2967 * 0x0001 Enable Quotas: enable quota for this fs
2971 /* we need to fake up a fsp here,
2972 * because its not send in this call
2974 files_struct fsp;
2975 SMB_NTQUOTA_STRUCT quotas;
2977 ZERO_STRUCT(fsp);
2978 ZERO_STRUCT(quotas);
2980 fsp.conn = conn;
2981 fsp.fnum = -1;
2983 /* access check */
2984 if (conn->server_info->utok.uid != sec_initial_uid()) {
2985 DEBUG(0,("set_user_quota: access_denied "
2986 "service [%s] user [%s]\n",
2987 lp_servicename(SNUM(conn)),
2988 conn->server_info->unix_name));
2989 return NT_STATUS_ACCESS_DENIED;
2992 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2993 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2994 return map_nt_error_from_unix(errno);
2997 data_len = 48;
2999 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3000 lp_servicename(SNUM(conn))));
3002 /* Unknown1 24 NULL bytes*/
3003 SBIG_UINT(pdata,0,(uint64_t)0);
3004 SBIG_UINT(pdata,8,(uint64_t)0);
3005 SBIG_UINT(pdata,16,(uint64_t)0);
3007 /* Default Soft Quota 8 bytes */
3008 SBIG_UINT(pdata,24,quotas.softlim);
3010 /* Default Hard Quota 8 bytes */
3011 SBIG_UINT(pdata,32,quotas.hardlim);
3013 /* Quota flag 2 bytes */
3014 SSVAL(pdata,40,quotas.qflags);
3016 /* Unknown3 6 NULL bytes */
3017 SSVAL(pdata,42,0);
3018 SIVAL(pdata,44,0);
3020 break;
3022 #endif /* HAVE_SYS_QUOTAS */
3023 case SMB_FS_OBJECTID_INFORMATION:
3025 unsigned char objid[16];
3026 struct smb_extended_info extended_info;
3027 memcpy(pdata,create_volume_objectid(conn, objid),16);
3028 samba_extended_info_version (&extended_info);
3029 SIVAL(pdata,16,extended_info.samba_magic);
3030 SIVAL(pdata,20,extended_info.samba_version);
3031 SIVAL(pdata,24,extended_info.samba_subversion);
3032 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3033 memcpy(pdata+36,extended_info.samba_version_string,28);
3034 data_len = 64;
3035 break;
3039 * Query the version and capabilities of the CIFS UNIX extensions
3040 * in use.
3043 case SMB_QUERY_CIFS_UNIX_INFO:
3045 bool large_write = lp_min_receive_file_size() &&
3046 !srv_is_signing_active(smbd_server_conn);
3047 bool large_read = !srv_is_signing_active(smbd_server_conn);
3048 int encrypt_caps = 0;
3050 if (!lp_unix_extensions()) {
3051 return NT_STATUS_INVALID_LEVEL;
3054 switch (conn->encrypt_level) {
3055 case 0:
3056 encrypt_caps = 0;
3057 break;
3058 case 1:
3059 case Auto:
3060 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3061 break;
3062 case Required:
3063 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3064 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3065 large_write = false;
3066 large_read = false;
3067 break;
3070 data_len = 12;
3071 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3072 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3074 /* We have POSIX ACLs, pathname, encryption,
3075 * large read/write, and locking capability. */
3077 SBIG_UINT(pdata,4,((uint64_t)(
3078 CIFS_UNIX_POSIX_ACLS_CAP|
3079 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3080 CIFS_UNIX_FCNTL_LOCKS_CAP|
3081 CIFS_UNIX_EXTATTR_CAP|
3082 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3083 encrypt_caps|
3084 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3085 (large_write ?
3086 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3087 break;
3090 case SMB_QUERY_POSIX_FS_INFO:
3092 int rc;
3093 vfs_statvfs_struct svfs;
3095 if (!lp_unix_extensions()) {
3096 return NT_STATUS_INVALID_LEVEL;
3099 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3101 if (!rc) {
3102 data_len = 56;
3103 SIVAL(pdata,0,svfs.OptimalTransferSize);
3104 SIVAL(pdata,4,svfs.BlockSize);
3105 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3106 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3107 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3108 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3109 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3110 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3111 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3112 #ifdef EOPNOTSUPP
3113 } else if (rc == EOPNOTSUPP) {
3114 return NT_STATUS_INVALID_LEVEL;
3115 #endif /* EOPNOTSUPP */
3116 } else {
3117 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3118 return NT_STATUS_DOS(ERRSRV, ERRerror);
3120 break;
3123 case SMB_QUERY_POSIX_WHOAMI:
3125 uint32_t flags = 0;
3126 uint32_t sid_bytes;
3127 int i;
3129 if (!lp_unix_extensions()) {
3130 return NT_STATUS_INVALID_LEVEL;
3133 if (max_data_bytes < 40) {
3134 return NT_STATUS_BUFFER_TOO_SMALL;
3137 /* We ARE guest if global_sid_Builtin_Guests is
3138 * in our list of SIDs.
3140 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3141 conn->server_info->ptok)) {
3142 flags |= SMB_WHOAMI_GUEST;
3145 /* We are NOT guest if global_sid_Authenticated_Users
3146 * is in our list of SIDs.
3148 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3149 conn->server_info->ptok)) {
3150 flags &= ~SMB_WHOAMI_GUEST;
3153 /* NOTE: 8 bytes for UID/GID, irrespective of native
3154 * platform size. This matches
3155 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3157 data_len = 4 /* flags */
3158 + 4 /* flag mask */
3159 + 8 /* uid */
3160 + 8 /* gid */
3161 + 4 /* ngroups */
3162 + 4 /* num_sids */
3163 + 4 /* SID bytes */
3164 + 4 /* pad/reserved */
3165 + (conn->server_info->utok.ngroups * 8)
3166 /* groups list */
3167 + (conn->server_info->ptok->num_sids *
3168 SID_MAX_SIZE)
3169 /* SID list */;
3171 SIVAL(pdata, 0, flags);
3172 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3173 SBIG_UINT(pdata, 8,
3174 (uint64_t)conn->server_info->utok.uid);
3175 SBIG_UINT(pdata, 16,
3176 (uint64_t)conn->server_info->utok.gid);
3179 if (data_len >= max_data_bytes) {
3180 /* Potential overflow, skip the GIDs and SIDs. */
3182 SIVAL(pdata, 24, 0); /* num_groups */
3183 SIVAL(pdata, 28, 0); /* num_sids */
3184 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3185 SIVAL(pdata, 36, 0); /* reserved */
3187 data_len = 40;
3188 break;
3191 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3192 SIVAL(pdata, 28, conn->server_info->num_sids);
3194 /* We walk the SID list twice, but this call is fairly
3195 * infrequent, and I don't expect that it's performance
3196 * sensitive -- jpeach
3198 for (i = 0, sid_bytes = 0;
3199 i < conn->server_info->ptok->num_sids; ++i) {
3200 sid_bytes += ndr_size_dom_sid(
3201 &conn->server_info->ptok->user_sids[i],
3202 NULL,
3206 /* SID list byte count */
3207 SIVAL(pdata, 32, sid_bytes);
3209 /* 4 bytes pad/reserved - must be zero */
3210 SIVAL(pdata, 36, 0);
3211 data_len = 40;
3213 /* GID list */
3214 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3215 SBIG_UINT(pdata, data_len,
3216 (uint64_t)conn->server_info->utok.groups[i]);
3217 data_len += 8;
3220 /* SID list */
3221 for (i = 0;
3222 i < conn->server_info->ptok->num_sids; ++i) {
3223 int sid_len = ndr_size_dom_sid(
3224 &conn->server_info->ptok->user_sids[i],
3225 NULL,
3228 sid_linearize(pdata + data_len, sid_len,
3229 &conn->server_info->ptok->user_sids[i]);
3230 data_len += sid_len;
3233 break;
3236 case SMB_MAC_QUERY_FS_INFO:
3238 * Thursby MAC extension... ONLY on NTFS filesystems
3239 * once we do streams then we don't need this
3241 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3242 data_len = 88;
3243 SIVAL(pdata,84,0x100); /* Don't support mac... */
3244 break;
3246 /* drop through */
3247 default:
3248 return NT_STATUS_INVALID_LEVEL;
3251 *ret_data_len = data_len;
3252 return NT_STATUS_OK;
3255 /****************************************************************************
3256 Reply to a TRANS2_QFSINFO (query filesystem info).
3257 ****************************************************************************/
3259 static void call_trans2qfsinfo(connection_struct *conn,
3260 struct smb_request *req,
3261 char **pparams, int total_params,
3262 char **ppdata, int total_data,
3263 unsigned int max_data_bytes)
3265 char *params = *pparams;
3266 uint16_t info_level;
3267 int data_len = 0;
3268 NTSTATUS status;
3270 if (total_params < 2) {
3271 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3272 return;
3275 info_level = SVAL(params,0);
3277 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3278 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3279 DEBUG(0,("call_trans2qfsinfo: encryption required "
3280 "and info level 0x%x sent.\n",
3281 (unsigned int)info_level));
3282 exit_server_cleanly("encryption required "
3283 "on connection");
3284 return;
3288 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3290 status = smbd_do_qfsinfo(conn, req,
3291 info_level,
3292 req->flags2,
3293 max_data_bytes,
3294 ppdata, &data_len);
3295 if (!NT_STATUS_IS_OK(status)) {
3296 reply_nterror(req, status);
3297 return;
3300 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3301 max_data_bytes);
3303 DEBUG( 4, ( "%s info_level = %d\n",
3304 smb_fn_name(req->cmd), info_level) );
3306 return;
3309 /****************************************************************************
3310 Reply to a TRANS2_SETFSINFO (set filesystem info).
3311 ****************************************************************************/
3313 static void call_trans2setfsinfo(connection_struct *conn,
3314 struct smb_request *req,
3315 char **pparams, int total_params,
3316 char **ppdata, int total_data,
3317 unsigned int max_data_bytes)
3319 char *pdata = *ppdata;
3320 char *params = *pparams;
3321 uint16 info_level;
3323 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3325 /* */
3326 if (total_params < 4) {
3327 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3328 total_params));
3329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3330 return;
3333 info_level = SVAL(params,2);
3335 if (IS_IPC(conn)) {
3336 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3337 info_level != SMB_SET_CIFS_UNIX_INFO) {
3338 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3339 "info level (0x%x) on IPC$.\n",
3340 (unsigned int)info_level));
3341 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3342 return;
3346 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3347 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3348 DEBUG(0,("call_trans2setfsinfo: encryption required "
3349 "and info level 0x%x sent.\n",
3350 (unsigned int)info_level));
3351 exit_server_cleanly("encryption required "
3352 "on connection");
3353 return;
3357 switch(info_level) {
3358 case SMB_SET_CIFS_UNIX_INFO:
3360 uint16 client_unix_major;
3361 uint16 client_unix_minor;
3362 uint32 client_unix_cap_low;
3363 uint32 client_unix_cap_high;
3365 if (!lp_unix_extensions()) {
3366 reply_nterror(req,
3367 NT_STATUS_INVALID_LEVEL);
3368 return;
3371 /* There should be 12 bytes of capabilities set. */
3372 if (total_data < 8) {
3373 reply_nterror(
3374 req,
3375 NT_STATUS_INVALID_PARAMETER);
3376 return;
3378 client_unix_major = SVAL(pdata,0);
3379 client_unix_minor = SVAL(pdata,2);
3380 client_unix_cap_low = IVAL(pdata,4);
3381 client_unix_cap_high = IVAL(pdata,8);
3382 /* Just print these values for now. */
3383 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3384 cap_low = 0x%x, cap_high = 0x%x\n",
3385 (unsigned int)client_unix_major,
3386 (unsigned int)client_unix_minor,
3387 (unsigned int)client_unix_cap_low,
3388 (unsigned int)client_unix_cap_high ));
3390 /* Here is where we must switch to posix pathname processing... */
3391 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3392 lp_set_posix_pathnames();
3393 mangle_change_to_posix();
3396 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3397 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3398 /* Client that knows how to do posix locks,
3399 * but not posix open/mkdir operations. Set a
3400 * default type for read/write checks. */
3402 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3405 break;
3408 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3410 NTSTATUS status;
3411 size_t param_len = 0;
3412 size_t data_len = total_data;
3414 if (!lp_unix_extensions()) {
3415 reply_nterror(
3416 req,
3417 NT_STATUS_INVALID_LEVEL);
3418 return;
3421 if (lp_smb_encrypt(SNUM(conn)) == false) {
3422 reply_nterror(
3423 req,
3424 NT_STATUS_NOT_SUPPORTED);
3425 return;
3428 DEBUG( 4,("call_trans2setfsinfo: "
3429 "request transport encryption.\n"));
3431 status = srv_request_encryption_setup(conn,
3432 (unsigned char **)ppdata,
3433 &data_len,
3434 (unsigned char **)pparams,
3435 &param_len);
3437 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3438 !NT_STATUS_IS_OK(status)) {
3439 reply_nterror(req, status);
3440 return;
3443 send_trans2_replies(conn, req,
3444 *pparams,
3445 param_len,
3446 *ppdata,
3447 data_len,
3448 max_data_bytes);
3450 if (NT_STATUS_IS_OK(status)) {
3451 /* Server-side transport
3452 * encryption is now *on*. */
3453 status = srv_encryption_start(conn);
3454 if (!NT_STATUS_IS_OK(status)) {
3455 exit_server_cleanly(
3456 "Failure in setting "
3457 "up encrypted transport");
3460 return;
3463 case SMB_FS_QUOTA_INFORMATION:
3465 files_struct *fsp = NULL;
3466 SMB_NTQUOTA_STRUCT quotas;
3468 ZERO_STRUCT(quotas);
3470 /* access check */
3471 if ((conn->server_info->utok.uid != sec_initial_uid())
3472 ||!CAN_WRITE(conn)) {
3473 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3474 lp_servicename(SNUM(conn)),
3475 conn->server_info->unix_name));
3476 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3477 return;
3480 /* note: normaly there're 48 bytes,
3481 * but we didn't use the last 6 bytes for now
3482 * --metze
3484 fsp = file_fsp(req, SVAL(params,0));
3486 if (!check_fsp_ntquota_handle(conn, req,
3487 fsp)) {
3488 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3489 reply_nterror(
3490 req, NT_STATUS_INVALID_HANDLE);
3491 return;
3494 if (total_data < 42) {
3495 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3496 total_data));
3497 reply_nterror(
3498 req,
3499 NT_STATUS_INVALID_PARAMETER);
3500 return;
3503 /* unknown_1 24 NULL bytes in pdata*/
3505 /* the soft quotas 8 bytes (uint64_t)*/
3506 quotas.softlim = (uint64_t)IVAL(pdata,24);
3507 #ifdef LARGE_SMB_OFF_T
3508 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3509 #else /* LARGE_SMB_OFF_T */
3510 if ((IVAL(pdata,28) != 0)&&
3511 ((quotas.softlim != 0xFFFFFFFF)||
3512 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3513 /* more than 32 bits? */
3514 reply_nterror(
3515 req,
3516 NT_STATUS_INVALID_PARAMETER);
3517 return;
3519 #endif /* LARGE_SMB_OFF_T */
3521 /* the hard quotas 8 bytes (uint64_t)*/
3522 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3523 #ifdef LARGE_SMB_OFF_T
3524 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3525 #else /* LARGE_SMB_OFF_T */
3526 if ((IVAL(pdata,36) != 0)&&
3527 ((quotas.hardlim != 0xFFFFFFFF)||
3528 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3529 /* more than 32 bits? */
3530 reply_nterror(
3531 req,
3532 NT_STATUS_INVALID_PARAMETER);
3533 return;
3535 #endif /* LARGE_SMB_OFF_T */
3537 /* quota_flags 2 bytes **/
3538 quotas.qflags = SVAL(pdata,40);
3540 /* unknown_2 6 NULL bytes follow*/
3542 /* now set the quotas */
3543 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3544 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3545 reply_nterror(req, map_nt_error_from_unix(errno));
3546 return;
3549 break;
3551 default:
3552 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3553 info_level));
3554 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3555 return;
3556 break;
3560 * sending this reply works fine,
3561 * but I'm not sure it's the same
3562 * like windows do...
3563 * --metze
3565 reply_outbuf(req, 10, 0);
3568 #if defined(HAVE_POSIX_ACLS)
3569 /****************************************************************************
3570 Utility function to count the number of entries in a POSIX acl.
3571 ****************************************************************************/
3573 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3575 unsigned int ace_count = 0;
3576 int entry_id = SMB_ACL_FIRST_ENTRY;
3577 SMB_ACL_ENTRY_T entry;
3579 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3580 /* get_next... */
3581 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3582 entry_id = SMB_ACL_NEXT_ENTRY;
3584 ace_count++;
3586 return ace_count;
3589 /****************************************************************************
3590 Utility function to marshall a POSIX acl into wire format.
3591 ****************************************************************************/
3593 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3595 int entry_id = SMB_ACL_FIRST_ENTRY;
3596 SMB_ACL_ENTRY_T entry;
3598 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3599 SMB_ACL_TAG_T tagtype;
3600 SMB_ACL_PERMSET_T permset;
3601 unsigned char perms = 0;
3602 unsigned int own_grp;
3604 /* get_next... */
3605 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3606 entry_id = SMB_ACL_NEXT_ENTRY;
3609 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3610 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3611 return False;
3614 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3615 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3616 return False;
3619 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3620 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3621 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3623 SCVAL(pdata,1,perms);
3625 switch (tagtype) {
3626 case SMB_ACL_USER_OBJ:
3627 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3628 own_grp = (unsigned int)pst->st_ex_uid;
3629 SIVAL(pdata,2,own_grp);
3630 SIVAL(pdata,6,0);
3631 break;
3632 case SMB_ACL_USER:
3634 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3635 if (!puid) {
3636 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3637 return False;
3639 own_grp = (unsigned int)*puid;
3640 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3641 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3642 SIVAL(pdata,2,own_grp);
3643 SIVAL(pdata,6,0);
3644 break;
3646 case SMB_ACL_GROUP_OBJ:
3647 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3648 own_grp = (unsigned int)pst->st_ex_gid;
3649 SIVAL(pdata,2,own_grp);
3650 SIVAL(pdata,6,0);
3651 break;
3652 case SMB_ACL_GROUP:
3654 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3655 if (!pgid) {
3656 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3657 return False;
3659 own_grp = (unsigned int)*pgid;
3660 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3661 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3662 SIVAL(pdata,2,own_grp);
3663 SIVAL(pdata,6,0);
3664 break;
3666 case SMB_ACL_MASK:
3667 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3668 SIVAL(pdata,2,0xFFFFFFFF);
3669 SIVAL(pdata,6,0xFFFFFFFF);
3670 break;
3671 case SMB_ACL_OTHER:
3672 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3673 SIVAL(pdata,2,0xFFFFFFFF);
3674 SIVAL(pdata,6,0xFFFFFFFF);
3675 break;
3676 default:
3677 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3678 return False;
3680 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3683 return True;
3685 #endif
3687 /****************************************************************************
3688 Store the FILE_UNIX_BASIC info.
3689 ****************************************************************************/
3691 static char *store_file_unix_basic(connection_struct *conn,
3692 char *pdata,
3693 files_struct *fsp,
3694 const SMB_STRUCT_STAT *psbuf)
3696 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3697 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3699 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3700 pdata += 8;
3702 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3703 pdata += 8;
3705 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3706 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3707 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3708 pdata += 24;
3710 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3711 SIVAL(pdata,4,0);
3712 pdata += 8;
3714 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3715 SIVAL(pdata,4,0);
3716 pdata += 8;
3718 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3719 pdata += 4;
3721 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3722 SIVAL(pdata,4,0);
3723 pdata += 8;
3725 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3726 SIVAL(pdata,4,0);
3727 pdata += 8;
3729 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3730 pdata += 8;
3732 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3733 SIVAL(pdata,4,0);
3734 pdata += 8;
3736 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3737 SIVAL(pdata,4,0);
3738 pdata += 8;
3740 return pdata;
3743 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3744 * the chflags(2) (or equivalent) flags.
3746 * XXX: this really should be behind the VFS interface. To do this, we would
3747 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3748 * Each VFS module could then implement its own mapping as appropriate for the
3749 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3751 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3752 info2_flags_map[] =
3754 #ifdef UF_NODUMP
3755 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3756 #endif
3758 #ifdef UF_IMMUTABLE
3759 { UF_IMMUTABLE, EXT_IMMUTABLE },
3760 #endif
3762 #ifdef UF_APPEND
3763 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3764 #endif
3766 #ifdef UF_HIDDEN
3767 { UF_HIDDEN, EXT_HIDDEN },
3768 #endif
3770 /* Do not remove. We need to guarantee that this array has at least one
3771 * entry to build on HP-UX.
3773 { 0, 0 }
3777 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3778 uint32 *smb_fflags, uint32 *smb_fmask)
3780 int i;
3782 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3783 *smb_fmask |= info2_flags_map[i].smb_fflag;
3784 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3785 *smb_fflags |= info2_flags_map[i].smb_fflag;
3790 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3791 const uint32 smb_fflags,
3792 const uint32 smb_fmask,
3793 int *stat_fflags)
3795 uint32 max_fmask = 0;
3796 int i;
3798 *stat_fflags = psbuf->st_ex_flags;
3800 /* For each flags requested in smb_fmask, check the state of the
3801 * corresponding flag in smb_fflags and set or clear the matching
3802 * stat flag.
3805 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3806 max_fmask |= info2_flags_map[i].smb_fflag;
3807 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3808 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3809 *stat_fflags |= info2_flags_map[i].stat_fflag;
3810 } else {
3811 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3816 /* If smb_fmask is asking to set any bits that are not supported by
3817 * our flag mappings, we should fail.
3819 if ((smb_fmask & max_fmask) != smb_fmask) {
3820 return False;
3823 return True;
3827 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3828 * of file flags and birth (create) time.
3830 static char *store_file_unix_basic_info2(connection_struct *conn,
3831 char *pdata,
3832 files_struct *fsp,
3833 const SMB_STRUCT_STAT *psbuf)
3835 uint32 file_flags = 0;
3836 uint32 flags_mask = 0;
3838 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3840 /* Create (birth) time 64 bit */
3841 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3842 pdata += 8;
3844 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3845 SIVAL(pdata, 0, file_flags); /* flags */
3846 SIVAL(pdata, 4, flags_mask); /* mask */
3847 pdata += 8;
3849 return pdata;
3852 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3853 const struct stream_struct *streams,
3854 char *data,
3855 unsigned int max_data_bytes,
3856 unsigned int *data_size)
3858 unsigned int i;
3859 unsigned int ofs = 0;
3861 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3862 unsigned int next_offset;
3863 size_t namelen;
3864 smb_ucs2_t *namebuf;
3866 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3867 streams[i].name, &namelen) ||
3868 namelen <= 2)
3870 return NT_STATUS_INVALID_PARAMETER;
3874 * name_buf is now null-terminated, we need to marshall as not
3875 * terminated
3878 namelen -= 2;
3880 SIVAL(data, ofs+4, namelen);
3881 SOFF_T(data, ofs+8, streams[i].size);
3882 SOFF_T(data, ofs+16, streams[i].alloc_size);
3883 memcpy(data+ofs+24, namebuf, namelen);
3884 TALLOC_FREE(namebuf);
3886 next_offset = ofs + 24 + namelen;
3888 if (i == num_streams-1) {
3889 SIVAL(data, ofs, 0);
3891 else {
3892 unsigned int align = ndr_align_size(next_offset, 8);
3894 memset(data+next_offset, 0, align);
3895 next_offset += align;
3897 SIVAL(data, ofs, next_offset - ofs);
3898 ofs = next_offset;
3901 ofs = next_offset;
3904 *data_size = ofs;
3906 return NT_STATUS_OK;
3909 /****************************************************************************
3910 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3911 ****************************************************************************/
3913 static void call_trans2qpipeinfo(connection_struct *conn,
3914 struct smb_request *req,
3915 unsigned int tran_call,
3916 char **pparams, int total_params,
3917 char **ppdata, int total_data,
3918 unsigned int max_data_bytes)
3920 char *params = *pparams;
3921 char *pdata = *ppdata;
3922 unsigned int data_size = 0;
3923 unsigned int param_size = 2;
3924 uint16 info_level;
3925 files_struct *fsp;
3927 if (!params) {
3928 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3929 return;
3932 if (total_params < 4) {
3933 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3934 return;
3937 fsp = file_fsp(req, SVAL(params,0));
3938 if (!fsp_is_np(fsp)) {
3939 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3940 return;
3943 info_level = SVAL(params,2);
3945 *pparams = (char *)SMB_REALLOC(*pparams,2);
3946 if (*pparams == NULL) {
3947 reply_nterror(req, NT_STATUS_NO_MEMORY);
3948 return;
3950 params = *pparams;
3951 SSVAL(params,0,0);
3952 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3953 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3954 if (*ppdata == NULL ) {
3955 reply_nterror(req, NT_STATUS_NO_MEMORY);
3956 return;
3958 pdata = *ppdata;
3960 switch (info_level) {
3961 case SMB_FILE_STANDARD_INFORMATION:
3962 memset(pdata,0,24);
3963 SOFF_T(pdata,0,4096LL);
3964 SIVAL(pdata,16,1);
3965 SIVAL(pdata,20,1);
3966 data_size = 24;
3967 break;
3969 default:
3970 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3971 return;
3974 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3975 max_data_bytes);
3977 return;
3980 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3981 TALLOC_CTX *mem_ctx,
3982 uint16_t info_level,
3983 files_struct *fsp,
3984 const struct smb_filename *smb_fname,
3985 bool delete_pending,
3986 struct timespec write_time_ts,
3987 bool ms_dfs_link,
3988 struct ea_list *ea_list,
3989 int lock_data_count,
3990 char *lock_data,
3991 uint16_t flags2,
3992 unsigned int max_data_bytes,
3993 char **ppdata,
3994 unsigned int *pdata_size)
3996 char *pdata = *ppdata;
3997 char *dstart, *dend;
3998 unsigned int data_size;
3999 struct timespec create_time_ts, mtime_ts, atime_ts;
4000 time_t create_time, mtime, atime;
4001 SMB_STRUCT_STAT sbuf;
4002 char *p;
4003 char *base_name;
4004 char *dos_fname;
4005 int mode;
4006 int nlink;
4007 NTSTATUS status;
4008 uint64_t file_size = 0;
4009 uint64_t pos = 0;
4010 uint64_t allocation_size = 0;
4011 uint64_t file_index = 0;
4012 uint32_t access_mask = 0;
4014 sbuf = smb_fname->st;
4016 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4017 return NT_STATUS_INVALID_LEVEL;
4020 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4021 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4022 info_level, max_data_bytes));
4024 if (ms_dfs_link) {
4025 mode = dos_mode_msdfs(conn, smb_fname);
4026 } else {
4027 mode = dos_mode(conn, smb_fname);
4029 if (!mode)
4030 mode = FILE_ATTRIBUTE_NORMAL;
4032 nlink = sbuf.st_ex_nlink;
4034 if (nlink && (mode&aDIR)) {
4035 nlink = 1;
4038 if ((nlink > 0) && delete_pending) {
4039 nlink -= 1;
4042 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4043 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4044 if (*ppdata == NULL) {
4045 return NT_STATUS_NO_MEMORY;
4047 pdata = *ppdata;
4048 dstart = pdata;
4049 dend = dstart + data_size - 1;
4051 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4052 update_stat_ex_mtime(&sbuf, write_time_ts);
4055 create_time_ts = sbuf.st_ex_btime;
4056 mtime_ts = sbuf.st_ex_mtime;
4057 atime_ts = sbuf.st_ex_atime;
4059 if (lp_dos_filetime_resolution(SNUM(conn))) {
4060 dos_filetime_timespec(&create_time_ts);
4061 dos_filetime_timespec(&mtime_ts);
4062 dos_filetime_timespec(&atime_ts);
4065 create_time = convert_timespec_to_time_t(create_time_ts);
4066 mtime = convert_timespec_to_time_t(mtime_ts);
4067 atime = convert_timespec_to_time_t(atime_ts);
4069 p = strrchr_m(smb_fname->base_name,'/');
4070 if (!p)
4071 base_name = smb_fname->base_name;
4072 else
4073 base_name = p+1;
4075 /* NT expects the name to be in an exact form of the *full*
4076 filename. See the trans2 torture test */
4077 if (ISDOT(base_name)) {
4078 dos_fname = talloc_strdup(mem_ctx, "\\");
4079 if (!dos_fname) {
4080 return NT_STATUS_NO_MEMORY;
4082 } else {
4083 dos_fname = talloc_asprintf(mem_ctx,
4084 "\\%s",
4085 smb_fname->base_name);
4086 if (!dos_fname) {
4087 return NT_STATUS_NO_MEMORY;
4089 if (is_ntfs_stream_smb_fname(smb_fname)) {
4090 dos_fname = talloc_asprintf(dos_fname, "%s",
4091 smb_fname->stream_name);
4092 if (!dos_fname) {
4093 return NT_STATUS_NO_MEMORY;
4097 string_replace(dos_fname, '/', '\\');
4100 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4102 if (!fsp) {
4103 /* Do we have this path open ? */
4104 files_struct *fsp1;
4105 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4106 fsp1 = file_find_di_first(fileid);
4107 if (fsp1 && fsp1->initial_allocation_size) {
4108 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4112 if (!(mode & aDIR)) {
4113 file_size = get_file_size_stat(&sbuf);
4116 if (fsp) {
4117 pos = fsp->fh->position_information;
4120 if (fsp) {
4121 access_mask = fsp->access_mask;
4122 } else {
4123 /* GENERIC_EXECUTE mapping from Windows */
4124 access_mask = 0x12019F;
4127 /* This should be an index number - looks like
4128 dev/ino to me :-)
4130 I think this causes us to fail the IFSKIT
4131 BasicFileInformationTest. -tpot */
4132 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4133 file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4135 switch (info_level) {
4136 case SMB_INFO_STANDARD:
4137 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4138 data_size = 22;
4139 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4140 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4141 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4142 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4143 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4144 SSVAL(pdata,l1_attrFile,mode);
4145 break;
4147 case SMB_INFO_QUERY_EA_SIZE:
4149 unsigned int ea_size =
4150 estimate_ea_size(conn, fsp,
4151 smb_fname->base_name);
4152 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4153 data_size = 26;
4154 srv_put_dos_date2(pdata,0,create_time);
4155 srv_put_dos_date2(pdata,4,atime);
4156 srv_put_dos_date2(pdata,8,mtime); /* write time */
4157 SIVAL(pdata,12,(uint32)file_size);
4158 SIVAL(pdata,16,(uint32)allocation_size);
4159 SSVAL(pdata,20,mode);
4160 SIVAL(pdata,22,ea_size);
4161 break;
4164 case SMB_INFO_IS_NAME_VALID:
4165 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4166 if (fsp) {
4167 /* os/2 needs this ? really ?*/
4168 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4170 /* This is only reached for qpathinfo */
4171 data_size = 0;
4172 break;
4174 case SMB_INFO_QUERY_EAS_FROM_LIST:
4176 size_t total_ea_len = 0;
4177 struct ea_list *ea_file_list = NULL;
4179 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4181 ea_file_list =
4182 get_ea_list_from_file(mem_ctx, conn, fsp,
4183 smb_fname->base_name,
4184 &total_ea_len);
4185 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4187 if (!ea_list || (total_ea_len > data_size)) {
4188 data_size = 4;
4189 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4190 break;
4193 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4194 break;
4197 case SMB_INFO_QUERY_ALL_EAS:
4199 /* We have data_size bytes to put EA's into. */
4200 size_t total_ea_len = 0;
4202 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4204 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4205 smb_fname->base_name,
4206 &total_ea_len);
4207 if (!ea_list || (total_ea_len > data_size)) {
4208 data_size = 4;
4209 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4210 break;
4213 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4214 break;
4217 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4219 /* We have data_size bytes to put EA's into. */
4220 size_t total_ea_len = 0;
4221 struct ea_list *ea_file_list = NULL;
4223 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4225 /*TODO: add filtering and index handling */
4227 ea_file_list =
4228 get_ea_list_from_file(mem_ctx, conn, fsp,
4229 smb_fname->base_name,
4230 &total_ea_len);
4231 if (!ea_file_list) {
4232 return NT_STATUS_NO_EAS_ON_FILE;
4235 status = fill_ea_chained_buffer(mem_ctx,
4236 pdata,
4237 data_size,
4238 &data_size,
4239 conn, ea_file_list);
4240 if (!NT_STATUS_IS_OK(status)) {
4241 return status;
4243 break;
4246 case SMB_FILE_BASIC_INFORMATION:
4247 case SMB_QUERY_FILE_BASIC_INFO:
4249 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4250 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4251 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4252 } else {
4253 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4254 data_size = 40;
4255 SIVAL(pdata,36,0);
4257 put_long_date_timespec(pdata,create_time_ts);
4258 put_long_date_timespec(pdata+8,atime_ts);
4259 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4260 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4261 SIVAL(pdata,32,mode);
4263 DEBUG(5,("SMB_QFBI - "));
4264 DEBUG(5,("create: %s ", ctime(&create_time)));
4265 DEBUG(5,("access: %s ", ctime(&atime)));
4266 DEBUG(5,("write: %s ", ctime(&mtime)));
4267 DEBUG(5,("change: %s ", ctime(&mtime)));
4268 DEBUG(5,("mode: %x\n", mode));
4269 break;
4271 case SMB_FILE_STANDARD_INFORMATION:
4272 case SMB_QUERY_FILE_STANDARD_INFO:
4274 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4275 data_size = 24;
4276 SOFF_T(pdata,0,allocation_size);
4277 SOFF_T(pdata,8,file_size);
4278 SIVAL(pdata,16,nlink);
4279 SCVAL(pdata,20,delete_pending?1:0);
4280 SCVAL(pdata,21,(mode&aDIR)?1:0);
4281 SSVAL(pdata,22,0); /* Padding. */
4282 break;
4284 case SMB_FILE_EA_INFORMATION:
4285 case SMB_QUERY_FILE_EA_INFO:
4287 unsigned int ea_size =
4288 estimate_ea_size(conn, fsp, smb_fname->base_name);
4289 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4290 data_size = 4;
4291 SIVAL(pdata,0,ea_size);
4292 break;
4295 /* Get the 8.3 name - used if NT SMB was negotiated. */
4296 case SMB_QUERY_FILE_ALT_NAME_INFO:
4297 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4299 int len;
4300 char mangled_name[13];
4301 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4302 if (!name_to_8_3(base_name,mangled_name,
4303 True,conn->params)) {
4304 return NT_STATUS_NO_MEMORY;
4306 len = srvstr_push(dstart, flags2,
4307 pdata+4, mangled_name,
4308 PTR_DIFF(dend, pdata+4),
4309 STR_UNICODE);
4310 data_size = 4 + len;
4311 SIVAL(pdata,0,len);
4312 break;
4315 case SMB_QUERY_FILE_NAME_INFO:
4317 int len;
4319 this must be *exactly* right for ACLs on mapped drives to work
4321 len = srvstr_push(dstart, flags2,
4322 pdata+4, dos_fname,
4323 PTR_DIFF(dend, pdata+4),
4324 STR_UNICODE);
4325 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4326 data_size = 4 + len;
4327 SIVAL(pdata,0,len);
4328 break;
4331 case SMB_FILE_ALLOCATION_INFORMATION:
4332 case SMB_QUERY_FILE_ALLOCATION_INFO:
4333 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4334 data_size = 8;
4335 SOFF_T(pdata,0,allocation_size);
4336 break;
4338 case SMB_FILE_END_OF_FILE_INFORMATION:
4339 case SMB_QUERY_FILE_END_OF_FILEINFO:
4340 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4341 data_size = 8;
4342 SOFF_T(pdata,0,file_size);
4343 break;
4345 case SMB_QUERY_FILE_ALL_INFO:
4346 case SMB_FILE_ALL_INFORMATION:
4348 int len;
4349 unsigned int ea_size =
4350 estimate_ea_size(conn, fsp, smb_fname->base_name);
4351 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4352 put_long_date_timespec(pdata,create_time_ts);
4353 put_long_date_timespec(pdata+8,atime_ts);
4354 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4355 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4356 SIVAL(pdata,32,mode);
4357 SIVAL(pdata,36,0); /* padding. */
4358 pdata += 40;
4359 SOFF_T(pdata,0,allocation_size);
4360 SOFF_T(pdata,8,file_size);
4361 SIVAL(pdata,16,nlink);
4362 SCVAL(pdata,20,delete_pending);
4363 SCVAL(pdata,21,(mode&aDIR)?1:0);
4364 SSVAL(pdata,22,0);
4365 pdata += 24;
4366 SIVAL(pdata,0,ea_size);
4367 pdata += 4; /* EA info */
4368 len = srvstr_push(dstart, flags2,
4369 pdata+4, dos_fname,
4370 PTR_DIFF(dend, pdata+4),
4371 STR_UNICODE);
4372 SIVAL(pdata,0,len);
4373 pdata += 4 + len;
4374 data_size = PTR_DIFF(pdata,(*ppdata));
4375 break;
4378 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4380 int len;
4381 unsigned int ea_size =
4382 estimate_ea_size(conn, fsp, smb_fname->base_name);
4383 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4384 put_long_date_timespec(pdata+0x00,create_time_ts);
4385 put_long_date_timespec(pdata+0x08,atime_ts);
4386 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4387 put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
4388 SIVAL(pdata, 0x20, mode);
4389 SIVAL(pdata, 0x24, 0); /* padding. */
4390 SBVAL(pdata, 0x28, allocation_size);
4391 SBVAL(pdata, 0x30, file_size);
4392 SIVAL(pdata, 0x38, nlink);
4393 SCVAL(pdata, 0x3C, delete_pending);
4394 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4395 SSVAL(pdata, 0x3E, 0); /* padding */
4396 SBVAL(pdata, 0x40, file_index);
4397 SIVAL(pdata, 0x48, ea_size);
4398 SIVAL(pdata, 0x4C, access_mask);
4399 SBVAL(pdata, 0x50, pos);
4400 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4401 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4403 pdata += 0x60;
4405 len = srvstr_push(dstart, flags2,
4406 pdata+4, dos_fname,
4407 PTR_DIFF(dend, pdata+4),
4408 STR_UNICODE);
4409 SIVAL(pdata,0,len);
4410 pdata += 4 + len;
4411 data_size = PTR_DIFF(pdata,(*ppdata));
4412 break;
4414 case SMB_FILE_INTERNAL_INFORMATION:
4416 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4417 SBVAL(pdata, 0, file_index);
4418 data_size = 8;
4419 break;
4421 case SMB_FILE_ACCESS_INFORMATION:
4422 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4423 SIVAL(pdata, 0, access_mask);
4424 data_size = 4;
4425 break;
4427 case SMB_FILE_NAME_INFORMATION:
4428 /* Pathname with leading '\'. */
4430 size_t byte_len;
4431 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4432 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4433 SIVAL(pdata,0,byte_len);
4434 data_size = 4 + byte_len;
4435 break;
4438 case SMB_FILE_DISPOSITION_INFORMATION:
4439 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4440 data_size = 1;
4441 SCVAL(pdata,0,delete_pending);
4442 break;
4444 case SMB_FILE_POSITION_INFORMATION:
4445 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4446 data_size = 8;
4447 SOFF_T(pdata,0,pos);
4448 break;
4450 case SMB_FILE_MODE_INFORMATION:
4451 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4452 SIVAL(pdata,0,mode);
4453 data_size = 4;
4454 break;
4456 case SMB_FILE_ALIGNMENT_INFORMATION:
4457 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4458 SIVAL(pdata,0,0); /* No alignment needed. */
4459 data_size = 4;
4460 break;
4463 * NT4 server just returns "invalid query" to this - if we try
4464 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4465 * want this. JRA.
4467 /* The first statement above is false - verified using Thursby
4468 * client against NT4 -- gcolley.
4470 case SMB_QUERY_FILE_STREAM_INFO:
4471 case SMB_FILE_STREAM_INFORMATION: {
4472 unsigned int num_streams;
4473 struct stream_struct *streams;
4475 DEBUG(10,("smbd_do_qfilepathinfo: "
4476 "SMB_FILE_STREAM_INFORMATION\n"));
4478 if (is_ntfs_stream_smb_fname(smb_fname)) {
4479 return NT_STATUS_INVALID_PARAMETER;
4482 status = SMB_VFS_STREAMINFO(
4483 conn, fsp, smb_fname->base_name, talloc_tos(),
4484 &num_streams, &streams);
4486 if (!NT_STATUS_IS_OK(status)) {
4487 DEBUG(10, ("could not get stream info: %s\n",
4488 nt_errstr(status)));
4489 return status;
4492 status = marshall_stream_info(num_streams, streams,
4493 pdata, max_data_bytes,
4494 &data_size);
4496 if (!NT_STATUS_IS_OK(status)) {
4497 DEBUG(10, ("marshall_stream_info failed: %s\n",
4498 nt_errstr(status)));
4499 return status;
4502 TALLOC_FREE(streams);
4504 break;
4506 case SMB_QUERY_COMPRESSION_INFO:
4507 case SMB_FILE_COMPRESSION_INFORMATION:
4508 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4509 SOFF_T(pdata,0,file_size);
4510 SIVAL(pdata,8,0); /* ??? */
4511 SIVAL(pdata,12,0); /* ??? */
4512 data_size = 16;
4513 break;
4515 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4516 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4517 put_long_date_timespec(pdata,create_time_ts);
4518 put_long_date_timespec(pdata+8,atime_ts);
4519 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4520 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4521 SOFF_T(pdata,32,allocation_size);
4522 SOFF_T(pdata,40,file_size);
4523 SIVAL(pdata,48,mode);
4524 SIVAL(pdata,52,0); /* ??? */
4525 data_size = 56;
4526 break;
4528 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4529 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4530 SIVAL(pdata,0,mode);
4531 SIVAL(pdata,4,0);
4532 data_size = 8;
4533 break;
4536 * CIFS UNIX Extensions.
4539 case SMB_QUERY_FILE_UNIX_BASIC:
4541 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4542 data_size = PTR_DIFF(pdata,(*ppdata));
4545 int i;
4546 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4548 for (i=0; i<100; i++)
4549 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4550 DEBUG(4,("\n"));
4553 break;
4555 case SMB_QUERY_FILE_UNIX_INFO2:
4557 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4558 data_size = PTR_DIFF(pdata,(*ppdata));
4561 int i;
4562 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4564 for (i=0; i<100; i++)
4565 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4566 DEBUG(4,("\n"));
4569 break;
4571 case SMB_QUERY_FILE_UNIX_LINK:
4573 int len;
4574 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4576 if (!buffer) {
4577 return NT_STATUS_NO_MEMORY;
4580 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4581 #ifdef S_ISLNK
4582 if(!S_ISLNK(sbuf.st_ex_mode)) {
4583 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4585 #else
4586 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4587 #endif
4588 len = SMB_VFS_READLINK(conn,
4589 smb_fname->base_name,
4590 buffer, PATH_MAX);
4591 if (len == -1) {
4592 return map_nt_error_from_unix(errno);
4594 buffer[len] = 0;
4595 len = srvstr_push(dstart, flags2,
4596 pdata, buffer,
4597 PTR_DIFF(dend, pdata),
4598 STR_TERMINATE);
4599 pdata += len;
4600 data_size = PTR_DIFF(pdata,(*ppdata));
4602 break;
4605 #if defined(HAVE_POSIX_ACLS)
4606 case SMB_QUERY_POSIX_ACL:
4608 SMB_ACL_T file_acl = NULL;
4609 SMB_ACL_T def_acl = NULL;
4610 uint16 num_file_acls = 0;
4611 uint16 num_def_acls = 0;
4613 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4614 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4615 } else {
4616 file_acl =
4617 SMB_VFS_SYS_ACL_GET_FILE(conn,
4618 smb_fname->base_name,
4619 SMB_ACL_TYPE_ACCESS);
4622 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4623 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4624 "not implemented on "
4625 "filesystem containing %s\n",
4626 smb_fname->base_name));
4627 return NT_STATUS_NOT_IMPLEMENTED;
4630 if (S_ISDIR(sbuf.st_ex_mode)) {
4631 if (fsp && fsp->is_directory) {
4632 def_acl =
4633 SMB_VFS_SYS_ACL_GET_FILE(
4634 conn,
4635 fsp->fsp_name->base_name,
4636 SMB_ACL_TYPE_DEFAULT);
4637 } else {
4638 def_acl =
4639 SMB_VFS_SYS_ACL_GET_FILE(
4640 conn,
4641 smb_fname->base_name,
4642 SMB_ACL_TYPE_DEFAULT);
4644 def_acl = free_empty_sys_acl(conn, def_acl);
4647 num_file_acls = count_acl_entries(conn, file_acl);
4648 num_def_acls = count_acl_entries(conn, def_acl);
4650 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4651 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4652 data_size,
4653 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4654 SMB_POSIX_ACL_HEADER_SIZE) ));
4655 if (file_acl) {
4656 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4658 if (def_acl) {
4659 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4661 return NT_STATUS_BUFFER_TOO_SMALL;
4664 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4665 SSVAL(pdata,2,num_file_acls);
4666 SSVAL(pdata,4,num_def_acls);
4667 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4668 if (file_acl) {
4669 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4671 if (def_acl) {
4672 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4674 return NT_STATUS_INTERNAL_ERROR;
4676 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4677 if (file_acl) {
4678 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4680 if (def_acl) {
4681 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4683 return NT_STATUS_INTERNAL_ERROR;
4686 if (file_acl) {
4687 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4689 if (def_acl) {
4690 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4692 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4693 break;
4695 #endif
4698 case SMB_QUERY_POSIX_LOCK:
4700 uint64_t count;
4701 uint64_t offset;
4702 uint32 lock_pid;
4703 enum brl_type lock_type;
4705 /* We need an open file with a real fd for this. */
4706 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4707 return NT_STATUS_INVALID_LEVEL;
4710 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4711 return NT_STATUS_INVALID_PARAMETER;
4714 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4715 case POSIX_LOCK_TYPE_READ:
4716 lock_type = READ_LOCK;
4717 break;
4718 case POSIX_LOCK_TYPE_WRITE:
4719 lock_type = WRITE_LOCK;
4720 break;
4721 case POSIX_LOCK_TYPE_UNLOCK:
4722 default:
4723 /* There's no point in asking for an unlock... */
4724 return NT_STATUS_INVALID_PARAMETER;
4727 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4728 #if defined(HAVE_LONGLONG)
4729 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4730 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4731 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4732 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4733 #else /* HAVE_LONGLONG */
4734 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4735 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4736 #endif /* HAVE_LONGLONG */
4738 status = query_lock(fsp,
4739 &lock_pid,
4740 &count,
4741 &offset,
4742 &lock_type,
4743 POSIX_LOCK);
4745 if (ERROR_WAS_LOCK_DENIED(status)) {
4746 /* Here we need to report who has it locked... */
4747 data_size = POSIX_LOCK_DATA_SIZE;
4749 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4750 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4751 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4752 #if defined(HAVE_LONGLONG)
4753 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4754 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4755 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4756 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4757 #else /* HAVE_LONGLONG */
4758 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4759 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4760 #endif /* HAVE_LONGLONG */
4762 } else if (NT_STATUS_IS_OK(status)) {
4763 /* For success we just return a copy of what we sent
4764 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4765 data_size = POSIX_LOCK_DATA_SIZE;
4766 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4767 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4768 } else {
4769 return status;
4771 break;
4774 default:
4775 return NT_STATUS_INVALID_LEVEL;
4778 *pdata_size = data_size;
4779 return NT_STATUS_OK;
4782 /****************************************************************************
4783 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4784 file name or file id).
4785 ****************************************************************************/
4787 static void call_trans2qfilepathinfo(connection_struct *conn,
4788 struct smb_request *req,
4789 unsigned int tran_call,
4790 char **pparams, int total_params,
4791 char **ppdata, int total_data,
4792 unsigned int max_data_bytes)
4794 char *params = *pparams;
4795 char *pdata = *ppdata;
4796 uint16 info_level;
4797 unsigned int data_size = 0;
4798 unsigned int param_size = 2;
4799 struct smb_filename *smb_fname = NULL;
4800 bool delete_pending = False;
4801 struct timespec write_time_ts;
4802 files_struct *fsp = NULL;
4803 struct file_id fileid;
4804 struct ea_list *ea_list = NULL;
4805 int lock_data_count = 0;
4806 char *lock_data = NULL;
4807 bool ms_dfs_link = false;
4808 NTSTATUS status = NT_STATUS_OK;
4810 if (!params) {
4811 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4812 return;
4815 ZERO_STRUCT(write_time_ts);
4817 if (tran_call == TRANSACT2_QFILEINFO) {
4818 if (total_params < 4) {
4819 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4820 return;
4823 if (IS_IPC(conn)) {
4824 call_trans2qpipeinfo(conn, req, tran_call,
4825 pparams, total_params,
4826 ppdata, total_data,
4827 max_data_bytes);
4828 return;
4831 fsp = file_fsp(req, SVAL(params,0));
4832 info_level = SVAL(params,2);
4834 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4836 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4837 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4838 return;
4841 /* Initial check for valid fsp ptr. */
4842 if (!check_fsp_open(conn, req, fsp)) {
4843 return;
4846 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
4847 &smb_fname);
4848 if (!NT_STATUS_IS_OK(status)) {
4849 reply_nterror(req, status);
4850 return;
4853 if(fsp->fake_file_handle) {
4855 * This is actually for the QUOTA_FAKE_FILE --metze
4858 /* We know this name is ok, it's already passed the checks. */
4860 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4862 * This is actually a QFILEINFO on a directory
4863 * handle (returned from an NT SMB). NT5.0 seems
4864 * to do this call. JRA.
4867 if (INFO_LEVEL_IS_UNIX(info_level)) {
4868 /* Always do lstat for UNIX calls. */
4869 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4870 DEBUG(3,("call_trans2qfilepathinfo: "
4871 "SMB_VFS_LSTAT of %s failed "
4872 "(%s)\n",
4873 smb_fname_str_dbg(smb_fname),
4874 strerror(errno)));
4875 reply_nterror(req,
4876 map_nt_error_from_unix(errno));
4877 return;
4879 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4880 DEBUG(3,("call_trans2qfilepathinfo: "
4881 "SMB_VFS_STAT of %s failed (%s)\n",
4882 smb_fname_str_dbg(smb_fname),
4883 strerror(errno)));
4884 reply_nterror(req,
4885 map_nt_error_from_unix(errno));
4886 return;
4889 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4890 get_file_infos(fileid, &delete_pending, &write_time_ts);
4891 } else {
4893 * Original code - this is an open file.
4895 if (!check_fsp(conn, req, fsp)) {
4896 return;
4899 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4900 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4901 fsp->fnum, strerror(errno)));
4902 reply_nterror(req,
4903 map_nt_error_from_unix(errno));
4904 return;
4906 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4907 get_file_infos(fileid, &delete_pending, &write_time_ts);
4910 } else {
4911 char *fname = NULL;
4913 /* qpathinfo */
4914 if (total_params < 7) {
4915 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4916 return;
4919 info_level = SVAL(params,0);
4921 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4923 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4924 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4925 return;
4928 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
4929 total_params - 6,
4930 STR_TERMINATE, &status);
4931 if (!NT_STATUS_IS_OK(status)) {
4932 reply_nterror(req, status);
4933 return;
4936 status = filename_convert(req,
4937 conn,
4938 req->flags2 & FLAGS2_DFS_PATHNAMES,
4939 fname,
4941 NULL,
4942 &smb_fname);
4943 if (!NT_STATUS_IS_OK(status)) {
4944 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4945 reply_botherror(req,
4946 NT_STATUS_PATH_NOT_COVERED,
4947 ERRSRV, ERRbadpath);
4948 return;
4950 reply_nterror(req, status);
4951 return;
4954 /* If this is a stream, check if there is a delete_pending. */
4955 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4956 && is_ntfs_stream_smb_fname(smb_fname)) {
4957 struct smb_filename *smb_fname_base = NULL;
4959 /* Create an smb_filename with stream_name == NULL. */
4960 status =
4961 create_synthetic_smb_fname(talloc_tos(),
4962 smb_fname->base_name,
4963 NULL, NULL,
4964 &smb_fname_base);
4965 if (!NT_STATUS_IS_OK(status)) {
4966 reply_nterror(req, status);
4967 return;
4970 if (INFO_LEVEL_IS_UNIX(info_level)) {
4971 /* Always do lstat for UNIX calls. */
4972 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4973 DEBUG(3,("call_trans2qfilepathinfo: "
4974 "SMB_VFS_LSTAT of %s failed "
4975 "(%s)\n",
4976 smb_fname_str_dbg(smb_fname_base),
4977 strerror(errno)));
4978 TALLOC_FREE(smb_fname_base);
4979 reply_nterror(req,
4980 map_nt_error_from_unix(errno));
4981 return;
4983 } else {
4984 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4985 DEBUG(3,("call_trans2qfilepathinfo: "
4986 "fileinfo of %s failed "
4987 "(%s)\n",
4988 smb_fname_str_dbg(smb_fname_base),
4989 strerror(errno)));
4990 TALLOC_FREE(smb_fname_base);
4991 reply_nterror(req,
4992 map_nt_error_from_unix(errno));
4993 return;
4997 fileid = vfs_file_id_from_sbuf(conn,
4998 &smb_fname_base->st);
4999 TALLOC_FREE(smb_fname_base);
5000 get_file_infos(fileid, &delete_pending, NULL);
5001 if (delete_pending) {
5002 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5003 return;
5007 if (INFO_LEVEL_IS_UNIX(info_level)) {
5008 /* Always do lstat for UNIX calls. */
5009 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5010 DEBUG(3,("call_trans2qfilepathinfo: "
5011 "SMB_VFS_LSTAT of %s failed (%s)\n",
5012 smb_fname_str_dbg(smb_fname),
5013 strerror(errno)));
5014 reply_nterror(req,
5015 map_nt_error_from_unix(errno));
5016 return;
5019 } else if (!VALID_STAT(smb_fname->st) &&
5020 SMB_VFS_STAT(conn, smb_fname) &&
5021 (info_level != SMB_INFO_IS_NAME_VALID)) {
5022 ms_dfs_link = check_msdfs_link(conn,
5023 smb_fname->base_name,
5024 &smb_fname->st);
5026 if (!ms_dfs_link) {
5027 DEBUG(3,("call_trans2qfilepathinfo: "
5028 "SMB_VFS_STAT of %s failed (%s)\n",
5029 smb_fname_str_dbg(smb_fname),
5030 strerror(errno)));
5031 reply_nterror(req,
5032 map_nt_error_from_unix(errno));
5033 return;
5037 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5038 get_file_infos(fileid, &delete_pending, &write_time_ts);
5039 if (delete_pending) {
5040 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5041 return;
5045 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5046 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5047 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5049 /* Pull out any data sent here before we realloc. */
5050 switch (info_level) {
5051 case SMB_INFO_QUERY_EAS_FROM_LIST:
5053 /* Pull any EA list from the data portion. */
5054 uint32 ea_size;
5056 if (total_data < 4) {
5057 reply_nterror(
5058 req, NT_STATUS_INVALID_PARAMETER);
5059 return;
5061 ea_size = IVAL(pdata,0);
5063 if (total_data > 0 && ea_size != total_data) {
5064 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5065 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5066 reply_nterror(
5067 req, NT_STATUS_INVALID_PARAMETER);
5068 return;
5071 if (!lp_ea_support(SNUM(conn))) {
5072 reply_doserror(req, ERRDOS,
5073 ERReasnotsupported);
5074 return;
5077 /* Pull out the list of names. */
5078 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5079 if (!ea_list) {
5080 reply_nterror(
5081 req, NT_STATUS_INVALID_PARAMETER);
5082 return;
5084 break;
5087 case SMB_QUERY_POSIX_LOCK:
5089 if (fsp == NULL || fsp->fh->fd == -1) {
5090 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5091 return;
5094 if (total_data != POSIX_LOCK_DATA_SIZE) {
5095 reply_nterror(
5096 req, NT_STATUS_INVALID_PARAMETER);
5097 return;
5100 /* Copy the lock range data. */
5101 lock_data = (char *)TALLOC_MEMDUP(
5102 req, pdata, total_data);
5103 if (!lock_data) {
5104 reply_nterror(req, NT_STATUS_NO_MEMORY);
5105 return;
5107 lock_data_count = total_data;
5109 default:
5110 break;
5113 *pparams = (char *)SMB_REALLOC(*pparams,2);
5114 if (*pparams == NULL) {
5115 reply_nterror(req, NT_STATUS_NO_MEMORY);
5116 return;
5118 params = *pparams;
5119 SSVAL(params,0,0);
5122 * draft-leach-cifs-v1-spec-02.txt
5123 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5124 * says:
5126 * The requested information is placed in the Data portion of the
5127 * transaction response. For the information levels greater than 0x100,
5128 * the transaction response has 1 parameter word which should be
5129 * ignored by the client.
5131 * However Windows only follows this rule for the IS_NAME_VALID call.
5133 switch (info_level) {
5134 case SMB_INFO_IS_NAME_VALID:
5135 param_size = 0;
5136 break;
5139 if ((info_level & 0xFF00) == 0xFF00) {
5141 * We use levels that start with 0xFF00
5142 * internally to represent SMB2 specific levels
5144 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5145 return;
5148 status = smbd_do_qfilepathinfo(conn, req, info_level,
5149 fsp, smb_fname,
5150 delete_pending, write_time_ts,
5151 ms_dfs_link, ea_list,
5152 lock_data_count, lock_data,
5153 req->flags2, max_data_bytes,
5154 ppdata, &data_size);
5155 if (!NT_STATUS_IS_OK(status)) {
5156 reply_nterror(req, status);
5157 return;
5160 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5161 max_data_bytes);
5163 return;
5166 /****************************************************************************
5167 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5168 code.
5169 ****************************************************************************/
5171 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5172 connection_struct *conn,
5173 const struct smb_filename *smb_fname_old,
5174 const struct smb_filename *smb_fname_new)
5176 NTSTATUS status = NT_STATUS_OK;
5178 /* source must already exist. */
5179 if (!VALID_STAT(smb_fname_old->st)) {
5180 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5183 /* Disallow if newname already exists. */
5184 if (VALID_STAT(smb_fname_new->st)) {
5185 return NT_STATUS_OBJECT_NAME_COLLISION;
5188 /* No links from a directory. */
5189 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5190 return NT_STATUS_FILE_IS_A_DIRECTORY;
5193 /* Setting a hardlink to/from a stream isn't currently supported. */
5194 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5195 is_ntfs_stream_smb_fname(smb_fname_new)) {
5196 return NT_STATUS_INVALID_PARAMETER;
5199 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5200 smb_fname_old->base_name, smb_fname_new->base_name));
5202 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5203 smb_fname_new->base_name) != 0) {
5204 status = map_nt_error_from_unix(errno);
5205 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5206 nt_errstr(status), smb_fname_old->base_name,
5207 smb_fname_new->base_name));
5209 return status;
5212 /****************************************************************************
5213 Deal with setting the time from any of the setfilepathinfo functions.
5214 ****************************************************************************/
5216 NTSTATUS smb_set_file_time(connection_struct *conn,
5217 files_struct *fsp,
5218 const struct smb_filename *smb_fname,
5219 struct smb_file_time *ft,
5220 bool setting_write_time)
5222 struct smb_filename *smb_fname_base = NULL;
5223 uint32 action =
5224 FILE_NOTIFY_CHANGE_LAST_ACCESS
5225 |FILE_NOTIFY_CHANGE_LAST_WRITE
5226 |FILE_NOTIFY_CHANGE_CREATION;
5227 NTSTATUS status;
5229 if (!VALID_STAT(smb_fname->st)) {
5230 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5233 /* get some defaults (no modifications) if any info is zero or -1. */
5234 if (null_timespec(ft->create_time)) {
5235 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5238 if (null_timespec(ft->atime)) {
5239 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5242 if (null_timespec(ft->mtime)) {
5243 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5246 if (!setting_write_time) {
5247 /* ft->mtime comes from change time, not write time. */
5248 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5251 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5252 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5253 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5254 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5255 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5256 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5257 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5258 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5260 if (setting_write_time) {
5262 * This was a Windows setfileinfo on an open file.
5263 * NT does this a lot. We also need to
5264 * set the time here, as it can be read by
5265 * FindFirst/FindNext and with the patch for bug #2045
5266 * in smbd/fileio.c it ensures that this timestamp is
5267 * kept sticky even after a write. We save the request
5268 * away and will set it on file close and after a write. JRA.
5271 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5272 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5274 if (fsp != NULL) {
5275 if (fsp->base_fsp) {
5276 set_sticky_write_time_fsp(fsp->base_fsp,
5277 ft->mtime);
5278 } else {
5279 set_sticky_write_time_fsp(fsp, ft->mtime);
5281 } else {
5282 set_sticky_write_time_path(
5283 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5284 ft->mtime);
5288 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5290 /* Always call ntimes on the base, even if a stream was passed in. */
5291 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5292 NULL, &smb_fname->st,
5293 &smb_fname_base);
5294 if (!NT_STATUS_IS_OK(status)) {
5295 return status;
5298 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5299 TALLOC_FREE(smb_fname_base);
5300 return map_nt_error_from_unix(errno);
5302 TALLOC_FREE(smb_fname_base);
5304 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5305 smb_fname->base_name);
5306 return NT_STATUS_OK;
5309 /****************************************************************************
5310 Deal with setting the dosmode from any of the setfilepathinfo functions.
5311 ****************************************************************************/
5313 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5314 const struct smb_filename *smb_fname,
5315 uint32 dosmode)
5317 struct smb_filename *smb_fname_base = NULL;
5318 NTSTATUS status;
5320 if (!VALID_STAT(smb_fname->st)) {
5321 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5324 /* Always operate on the base_name, even if a stream was passed in. */
5325 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5326 NULL, &smb_fname->st,
5327 &smb_fname_base);
5328 if (!NT_STATUS_IS_OK(status)) {
5329 return status;
5332 if (dosmode) {
5333 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5334 dosmode |= aDIR;
5335 } else {
5336 dosmode &= ~aDIR;
5340 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5342 /* check the mode isn't different, before changing it */
5343 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5344 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5345 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5346 (unsigned int)dosmode));
5348 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5349 false)) {
5350 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5351 "%s failed (%s)\n",
5352 smb_fname_str_dbg(smb_fname_base),
5353 strerror(errno)));
5354 status = map_nt_error_from_unix(errno);
5355 goto out;
5358 status = NT_STATUS_OK;
5359 out:
5360 TALLOC_FREE(smb_fname_base);
5361 return status;
5364 /****************************************************************************
5365 Deal with setting the size from any of the setfilepathinfo functions.
5366 ****************************************************************************/
5368 static NTSTATUS smb_set_file_size(connection_struct *conn,
5369 struct smb_request *req,
5370 files_struct *fsp,
5371 const struct smb_filename *smb_fname,
5372 const SMB_STRUCT_STAT *psbuf,
5373 SMB_OFF_T size)
5375 NTSTATUS status = NT_STATUS_OK;
5376 struct smb_filename *smb_fname_tmp = NULL;
5377 files_struct *new_fsp = NULL;
5379 if (!VALID_STAT(*psbuf)) {
5380 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5383 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5385 if (size == get_file_size_stat(psbuf)) {
5386 return NT_STATUS_OK;
5389 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5390 smb_fname_str_dbg(smb_fname), (double)size));
5392 if (fsp && fsp->fh->fd != -1) {
5393 /* Handle based call. */
5394 if (vfs_set_filelen(fsp, size) == -1) {
5395 return map_nt_error_from_unix(errno);
5397 trigger_write_time_update_immediate(fsp);
5398 return NT_STATUS_OK;
5401 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5402 if (!NT_STATUS_IS_OK(status)) {
5403 return status;
5406 smb_fname_tmp->st = *psbuf;
5408 status = SMB_VFS_CREATE_FILE(
5409 conn, /* conn */
5410 req, /* req */
5411 0, /* root_dir_fid */
5412 smb_fname_tmp, /* fname */
5413 FILE_WRITE_ATTRIBUTES, /* access_mask */
5414 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5415 FILE_SHARE_DELETE),
5416 FILE_OPEN, /* create_disposition*/
5417 0, /* create_options */
5418 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5419 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5420 0, /* allocation_size */
5421 NULL, /* sd */
5422 NULL, /* ea_list */
5423 &new_fsp, /* result */
5424 NULL); /* pinfo */
5426 TALLOC_FREE(smb_fname_tmp);
5428 if (!NT_STATUS_IS_OK(status)) {
5429 /* NB. We check for open_was_deferred in the caller. */
5430 return status;
5433 if (vfs_set_filelen(new_fsp, size) == -1) {
5434 status = map_nt_error_from_unix(errno);
5435 close_file(req, new_fsp,NORMAL_CLOSE);
5436 return status;
5439 trigger_write_time_update_immediate(new_fsp);
5440 close_file(req, new_fsp,NORMAL_CLOSE);
5441 return NT_STATUS_OK;
5444 /****************************************************************************
5445 Deal with SMB_INFO_SET_EA.
5446 ****************************************************************************/
5448 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5449 const char *pdata,
5450 int total_data,
5451 files_struct *fsp,
5452 const struct smb_filename *smb_fname)
5454 struct ea_list *ea_list = NULL;
5455 TALLOC_CTX *ctx = NULL;
5456 NTSTATUS status = NT_STATUS_OK;
5458 if (total_data < 10) {
5460 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5461 length. They seem to have no effect. Bug #3212. JRA */
5463 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5464 /* We're done. We only get EA info in this call. */
5465 return NT_STATUS_OK;
5468 return NT_STATUS_INVALID_PARAMETER;
5471 if (IVAL(pdata,0) > total_data) {
5472 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5473 IVAL(pdata,0), (unsigned int)total_data));
5474 return NT_STATUS_INVALID_PARAMETER;
5477 ctx = talloc_tos();
5478 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5479 if (!ea_list) {
5480 return NT_STATUS_INVALID_PARAMETER;
5482 status = set_ea(conn, fsp, smb_fname, ea_list);
5484 return status;
5487 /****************************************************************************
5488 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5489 ****************************************************************************/
5491 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5492 const char *pdata,
5493 int total_data,
5494 files_struct *fsp,
5495 const struct smb_filename *smb_fname)
5497 NTSTATUS status = NT_STATUS_OK;
5498 bool delete_on_close;
5499 uint32 dosmode = 0;
5501 if (total_data < 1) {
5502 return NT_STATUS_INVALID_PARAMETER;
5505 if (fsp == NULL) {
5506 return NT_STATUS_INVALID_HANDLE;
5509 delete_on_close = (CVAL(pdata,0) ? True : False);
5510 dosmode = dos_mode(conn, smb_fname);
5512 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5513 "delete_on_close = %u\n",
5514 smb_fname_str_dbg(smb_fname),
5515 (unsigned int)dosmode,
5516 (unsigned int)delete_on_close ));
5518 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5520 if (!NT_STATUS_IS_OK(status)) {
5521 return status;
5524 /* The set is across all open files on this dev/inode pair. */
5525 if (!set_delete_on_close(fsp, delete_on_close,
5526 &conn->server_info->utok)) {
5527 return NT_STATUS_ACCESS_DENIED;
5529 return NT_STATUS_OK;
5532 /****************************************************************************
5533 Deal with SMB_FILE_POSITION_INFORMATION.
5534 ****************************************************************************/
5536 static NTSTATUS smb_file_position_information(connection_struct *conn,
5537 const char *pdata,
5538 int total_data,
5539 files_struct *fsp)
5541 uint64_t position_information;
5543 if (total_data < 8) {
5544 return NT_STATUS_INVALID_PARAMETER;
5547 if (fsp == NULL) {
5548 /* Ignore on pathname based set. */
5549 return NT_STATUS_OK;
5552 position_information = (uint64_t)IVAL(pdata,0);
5553 #ifdef LARGE_SMB_OFF_T
5554 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5555 #else /* LARGE_SMB_OFF_T */
5556 if (IVAL(pdata,4) != 0) {
5557 /* more than 32 bits? */
5558 return NT_STATUS_INVALID_PARAMETER;
5560 #endif /* LARGE_SMB_OFF_T */
5562 DEBUG(10,("smb_file_position_information: Set file position "
5563 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5564 (double)position_information));
5565 fsp->fh->position_information = position_information;
5566 return NT_STATUS_OK;
5569 /****************************************************************************
5570 Deal with SMB_FILE_MODE_INFORMATION.
5571 ****************************************************************************/
5573 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5574 const char *pdata,
5575 int total_data)
5577 uint32 mode;
5579 if (total_data < 4) {
5580 return NT_STATUS_INVALID_PARAMETER;
5582 mode = IVAL(pdata,0);
5583 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5584 return NT_STATUS_INVALID_PARAMETER;
5586 return NT_STATUS_OK;
5589 /****************************************************************************
5590 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5591 ****************************************************************************/
5593 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5594 struct smb_request *req,
5595 const char *pdata,
5596 int total_data,
5597 const struct smb_filename *smb_fname)
5599 char *link_target = NULL;
5600 const char *newname = smb_fname->base_name;
5601 NTSTATUS status = NT_STATUS_OK;
5602 TALLOC_CTX *ctx = talloc_tos();
5604 /* Set a symbolic link. */
5605 /* Don't allow this if follow links is false. */
5607 if (total_data == 0) {
5608 return NT_STATUS_INVALID_PARAMETER;
5611 if (!lp_symlinks(SNUM(conn))) {
5612 return NT_STATUS_ACCESS_DENIED;
5615 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5616 total_data, STR_TERMINATE);
5618 if (!link_target) {
5619 return NT_STATUS_INVALID_PARAMETER;
5622 /* !widelinks forces the target path to be within the share. */
5623 /* This means we can interpret the target as a pathname. */
5624 if (!lp_widelinks(SNUM(conn))) {
5625 char *rel_name = NULL;
5626 char *last_dirp = NULL;
5628 if (*link_target == '/') {
5629 /* No absolute paths allowed. */
5630 return NT_STATUS_ACCESS_DENIED;
5632 rel_name = talloc_strdup(ctx,newname);
5633 if (!rel_name) {
5634 return NT_STATUS_NO_MEMORY;
5636 last_dirp = strrchr_m(rel_name, '/');
5637 if (last_dirp) {
5638 last_dirp[1] = '\0';
5639 } else {
5640 rel_name = talloc_strdup(ctx,"./");
5641 if (!rel_name) {
5642 return NT_STATUS_NO_MEMORY;
5645 rel_name = talloc_asprintf_append(rel_name,
5646 "%s",
5647 link_target);
5648 if (!rel_name) {
5649 return NT_STATUS_NO_MEMORY;
5652 status = check_name(conn, rel_name);
5653 if (!NT_STATUS_IS_OK(status)) {
5654 return status;
5658 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5659 newname, link_target ));
5661 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5662 return map_nt_error_from_unix(errno);
5665 return NT_STATUS_OK;
5668 /****************************************************************************
5669 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5670 ****************************************************************************/
5672 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5673 struct smb_request *req,
5674 const char *pdata, int total_data,
5675 const struct smb_filename *smb_fname_new)
5677 char *oldname = NULL;
5678 struct smb_filename *smb_fname_old = NULL;
5679 TALLOC_CTX *ctx = talloc_tos();
5680 NTSTATUS status = NT_STATUS_OK;
5682 /* Set a hard link. */
5683 if (total_data == 0) {
5684 return NT_STATUS_INVALID_PARAMETER;
5687 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5688 total_data, STR_TERMINATE, &status);
5689 if (!NT_STATUS_IS_OK(status)) {
5690 return status;
5693 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5694 smb_fname_str_dbg(smb_fname_new), oldname));
5696 status = filename_convert(ctx,
5697 conn,
5698 req->flags2 & FLAGS2_DFS_PATHNAMES,
5699 oldname,
5701 NULL,
5702 &smb_fname_old);
5703 if (!NT_STATUS_IS_OK(status)) {
5704 return status;
5707 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5710 /****************************************************************************
5711 Deal with SMB_FILE_RENAME_INFORMATION.
5712 ****************************************************************************/
5714 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5715 struct smb_request *req,
5716 const char *pdata,
5717 int total_data,
5718 files_struct *fsp,
5719 struct smb_filename *smb_fname_src)
5721 bool overwrite;
5722 uint32 root_fid;
5723 uint32 len;
5724 char *newname = NULL;
5725 struct smb_filename *smb_fname_dst = NULL;
5726 bool dest_has_wcard = False;
5727 NTSTATUS status = NT_STATUS_OK;
5728 char *p;
5729 TALLOC_CTX *ctx = talloc_tos();
5731 if (total_data < 13) {
5732 return NT_STATUS_INVALID_PARAMETER;
5735 overwrite = (CVAL(pdata,0) ? True : False);
5736 root_fid = IVAL(pdata,4);
5737 len = IVAL(pdata,8);
5739 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5740 return NT_STATUS_INVALID_PARAMETER;
5743 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5744 len, 0, &status,
5745 &dest_has_wcard);
5746 if (!NT_STATUS_IS_OK(status)) {
5747 return status;
5750 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5751 newname));
5753 status = resolve_dfspath_wcard(ctx, conn,
5754 req->flags2 & FLAGS2_DFS_PATHNAMES,
5755 newname,
5756 &newname,
5757 &dest_has_wcard);
5758 if (!NT_STATUS_IS_OK(status)) {
5759 return status;
5762 /* Check the new name has no '/' characters. */
5763 if (strchr_m(newname, '/')) {
5764 return NT_STATUS_NOT_SUPPORTED;
5767 if (fsp && fsp->base_fsp) {
5768 /* newname must be a stream name. */
5769 if (newname[0] != ':') {
5770 return NT_STATUS_NOT_SUPPORTED;
5773 /* Create an smb_fname to call rename_internals_fsp() with. */
5774 status = create_synthetic_smb_fname(talloc_tos(),
5775 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5776 &smb_fname_dst);
5777 if (!NT_STATUS_IS_OK(status)) {
5778 goto out;
5782 * Set the original last component, since
5783 * rename_internals_fsp() requires it.
5785 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5786 newname);
5787 if (smb_fname_dst->original_lcomp == NULL) {
5788 status = NT_STATUS_NO_MEMORY;
5789 goto out;
5792 } else {
5794 * Build up an smb_fname_dst based on the filename passed in.
5795 * We basically just strip off the last component, and put on
5796 * the newname instead.
5798 char *base_name = NULL;
5800 /* newname must *not* be a stream name. */
5801 if (newname[0] == ':') {
5802 return NT_STATUS_NOT_SUPPORTED;
5806 * Strip off the last component (filename) of the path passed
5807 * in.
5809 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5810 if (!base_name) {
5811 return NT_STATUS_NO_MEMORY;
5813 p = strrchr_m(base_name, '/');
5814 if (p) {
5815 p[1] = '\0';
5816 } else {
5817 base_name = talloc_strdup(ctx, "./");
5818 if (!base_name) {
5819 return NT_STATUS_NO_MEMORY;
5822 /* Append the new name. */
5823 base_name = talloc_asprintf_append(base_name,
5824 "%s",
5825 newname);
5826 if (!base_name) {
5827 return NT_STATUS_NO_MEMORY;
5830 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
5831 (UCF_SAVE_LCOMP |
5832 (dest_has_wcard ?
5833 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
5834 0)));
5836 /* If an error we expect this to be
5837 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5839 if (!NT_STATUS_IS_OK(status)) {
5840 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5841 status)) {
5842 goto out;
5844 /* Create an smb_fname to call rename_internals_fsp() */
5845 status = create_synthetic_smb_fname(ctx,
5846 base_name, NULL,
5847 NULL,
5848 &smb_fname_dst);
5849 if (!NT_STATUS_IS_OK(status)) {
5850 goto out;
5855 if (fsp) {
5856 DEBUG(10,("smb_file_rename_information: "
5857 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5858 fsp->fnum, fsp_str_dbg(fsp),
5859 smb_fname_str_dbg(smb_fname_dst)));
5860 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
5861 overwrite);
5862 } else {
5863 DEBUG(10,("smb_file_rename_information: "
5864 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5865 smb_fname_str_dbg(smb_fname_src),
5866 smb_fname_str_dbg(smb_fname_dst)));
5867 status = rename_internals(ctx, conn, req, smb_fname_src,
5868 smb_fname_dst, 0, overwrite, false,
5869 dest_has_wcard,
5870 FILE_WRITE_ATTRIBUTES);
5872 out:
5873 TALLOC_FREE(smb_fname_dst);
5874 return status;
5877 /****************************************************************************
5878 Deal with SMB_SET_POSIX_ACL.
5879 ****************************************************************************/
5881 #if defined(HAVE_POSIX_ACLS)
5882 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5883 const char *pdata,
5884 int total_data,
5885 files_struct *fsp,
5886 const struct smb_filename *smb_fname)
5888 uint16 posix_acl_version;
5889 uint16 num_file_acls;
5890 uint16 num_def_acls;
5891 bool valid_file_acls = True;
5892 bool valid_def_acls = True;
5894 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5895 return NT_STATUS_INVALID_PARAMETER;
5897 posix_acl_version = SVAL(pdata,0);
5898 num_file_acls = SVAL(pdata,2);
5899 num_def_acls = SVAL(pdata,4);
5901 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5902 valid_file_acls = False;
5903 num_file_acls = 0;
5906 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5907 valid_def_acls = False;
5908 num_def_acls = 0;
5911 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5912 return NT_STATUS_INVALID_PARAMETER;
5915 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5916 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5917 return NT_STATUS_INVALID_PARAMETER;
5920 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5921 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
5922 (unsigned int)num_file_acls,
5923 (unsigned int)num_def_acls));
5925 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
5926 smb_fname->base_name, num_file_acls,
5927 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5928 return map_nt_error_from_unix(errno);
5931 if (valid_def_acls && !set_unix_posix_default_acl(conn,
5932 smb_fname->base_name, &smb_fname->st, num_def_acls,
5933 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5934 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5935 return map_nt_error_from_unix(errno);
5937 return NT_STATUS_OK;
5939 #endif
5941 /****************************************************************************
5942 Deal with SMB_SET_POSIX_LOCK.
5943 ****************************************************************************/
5945 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5946 struct smb_request *req,
5947 const char *pdata,
5948 int total_data,
5949 files_struct *fsp)
5951 uint64_t count;
5952 uint64_t offset;
5953 uint32 lock_pid;
5954 bool blocking_lock = False;
5955 enum brl_type lock_type;
5957 NTSTATUS status = NT_STATUS_OK;
5959 if (fsp == NULL || fsp->fh->fd == -1) {
5960 return NT_STATUS_INVALID_HANDLE;
5963 if (total_data != POSIX_LOCK_DATA_SIZE) {
5964 return NT_STATUS_INVALID_PARAMETER;
5967 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5968 case POSIX_LOCK_TYPE_READ:
5969 lock_type = READ_LOCK;
5970 break;
5971 case POSIX_LOCK_TYPE_WRITE:
5972 /* Return the right POSIX-mappable error code for files opened read-only. */
5973 if (!fsp->can_write) {
5974 return NT_STATUS_INVALID_HANDLE;
5976 lock_type = WRITE_LOCK;
5977 break;
5978 case POSIX_LOCK_TYPE_UNLOCK:
5979 lock_type = UNLOCK_LOCK;
5980 break;
5981 default:
5982 return NT_STATUS_INVALID_PARAMETER;
5985 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5986 blocking_lock = False;
5987 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5988 blocking_lock = True;
5989 } else {
5990 return NT_STATUS_INVALID_PARAMETER;
5993 if (!lp_blocking_locks(SNUM(conn))) {
5994 blocking_lock = False;
5997 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5998 #if defined(HAVE_LONGLONG)
5999 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6000 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6001 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6002 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6003 #else /* HAVE_LONGLONG */
6004 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6005 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6006 #endif /* HAVE_LONGLONG */
6008 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6009 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6010 fsp_str_dbg(fsp),
6011 (unsigned int)lock_type,
6012 (unsigned int)lock_pid,
6013 (double)count,
6014 (double)offset ));
6016 if (lock_type == UNLOCK_LOCK) {
6017 status = do_unlock(smbd_messaging_context(),
6018 fsp,
6019 lock_pid,
6020 count,
6021 offset,
6022 POSIX_LOCK);
6023 } else {
6024 uint32 block_smbpid;
6026 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6027 fsp,
6028 lock_pid,
6029 count,
6030 offset,
6031 lock_type,
6032 POSIX_LOCK,
6033 blocking_lock,
6034 &status,
6035 &block_smbpid,
6036 NULL);
6038 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6040 * A blocking lock was requested. Package up
6041 * this smb into a queued request and push it
6042 * onto the blocking lock queue.
6044 if(push_blocking_lock_request(br_lck,
6045 req,
6046 fsp,
6047 -1, /* infinite timeout. */
6049 lock_pid,
6050 lock_type,
6051 POSIX_LOCK,
6052 offset,
6053 count,
6054 block_smbpid)) {
6055 TALLOC_FREE(br_lck);
6056 return status;
6059 TALLOC_FREE(br_lck);
6062 return status;
6065 /****************************************************************************
6066 Deal with SMB_SET_FILE_BASIC_INFO.
6067 ****************************************************************************/
6069 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6070 const char *pdata,
6071 int total_data,
6072 files_struct *fsp,
6073 const struct smb_filename *smb_fname)
6075 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6076 struct smb_file_time ft;
6077 uint32 dosmode = 0;
6078 NTSTATUS status = NT_STATUS_OK;
6080 ZERO_STRUCT(ft);
6082 if (total_data < 36) {
6083 return NT_STATUS_INVALID_PARAMETER;
6086 /* Set the attributes */
6087 dosmode = IVAL(pdata,32);
6088 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6089 if (!NT_STATUS_IS_OK(status)) {
6090 return status;
6093 /* create time */
6094 ft.create_time = interpret_long_date(pdata);
6096 /* access time */
6097 ft.atime = interpret_long_date(pdata+8);
6099 /* write time. */
6100 ft.mtime = interpret_long_date(pdata+16);
6102 /* change time. */
6103 ft.ctime = interpret_long_date(pdata+24);
6105 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6106 smb_fname_str_dbg(smb_fname)));
6108 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6109 true);
6112 /****************************************************************************
6113 Deal with SMB_INFO_STANDARD.
6114 ****************************************************************************/
6116 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6117 const char *pdata,
6118 int total_data,
6119 files_struct *fsp,
6120 const struct smb_filename *smb_fname)
6122 struct smb_file_time ft;
6124 ZERO_STRUCT(ft);
6126 if (total_data < 12) {
6127 return NT_STATUS_INVALID_PARAMETER;
6130 /* create time */
6131 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6132 /* access time */
6133 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6134 /* write time */
6135 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6137 DEBUG(10,("smb_set_info_standard: file %s\n",
6138 smb_fname_str_dbg(smb_fname)));
6140 return smb_set_file_time(conn,
6141 fsp,
6142 smb_fname,
6143 &ft,
6144 true);
6147 /****************************************************************************
6148 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6149 ****************************************************************************/
6151 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6152 struct smb_request *req,
6153 const char *pdata,
6154 int total_data,
6155 files_struct *fsp,
6156 struct smb_filename *smb_fname)
6158 uint64_t allocation_size = 0;
6159 NTSTATUS status = NT_STATUS_OK;
6160 files_struct *new_fsp = NULL;
6162 if (!VALID_STAT(smb_fname->st)) {
6163 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6166 if (total_data < 8) {
6167 return NT_STATUS_INVALID_PARAMETER;
6170 allocation_size = (uint64_t)IVAL(pdata,0);
6171 #ifdef LARGE_SMB_OFF_T
6172 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6173 #else /* LARGE_SMB_OFF_T */
6174 if (IVAL(pdata,4) != 0) {
6175 /* more than 32 bits? */
6176 return NT_STATUS_INVALID_PARAMETER;
6178 #endif /* LARGE_SMB_OFF_T */
6180 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6181 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6182 (double)allocation_size));
6184 if (allocation_size) {
6185 allocation_size = smb_roundup(conn, allocation_size);
6188 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6189 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6190 (double)allocation_size));
6192 if (fsp && fsp->fh->fd != -1) {
6193 /* Open file handle. */
6194 /* Only change if needed. */
6195 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6196 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6197 return map_nt_error_from_unix(errno);
6200 /* But always update the time. */
6202 * This is equivalent to a write. Ensure it's seen immediately
6203 * if there are no pending writes.
6205 trigger_write_time_update_immediate(fsp);
6206 return NT_STATUS_OK;
6209 /* Pathname or stat or directory file. */
6210 status = SMB_VFS_CREATE_FILE(
6211 conn, /* conn */
6212 req, /* req */
6213 0, /* root_dir_fid */
6214 smb_fname, /* fname */
6215 FILE_WRITE_DATA, /* access_mask */
6216 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6217 FILE_SHARE_DELETE),
6218 FILE_OPEN, /* create_disposition*/
6219 0, /* create_options */
6220 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6221 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6222 0, /* allocation_size */
6223 NULL, /* sd */
6224 NULL, /* ea_list */
6225 &new_fsp, /* result */
6226 NULL); /* pinfo */
6228 if (!NT_STATUS_IS_OK(status)) {
6229 /* NB. We check for open_was_deferred in the caller. */
6230 return status;
6233 /* Only change if needed. */
6234 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6235 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6236 status = map_nt_error_from_unix(errno);
6237 close_file(req, new_fsp, NORMAL_CLOSE);
6238 return status;
6242 /* Changing the allocation size should set the last mod time. */
6244 * This is equivalent to a write. Ensure it's seen immediately
6245 * if there are no pending writes.
6247 trigger_write_time_update_immediate(new_fsp);
6249 close_file(req, new_fsp, NORMAL_CLOSE);
6250 return NT_STATUS_OK;
6253 /****************************************************************************
6254 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6255 ****************************************************************************/
6257 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6258 struct smb_request *req,
6259 const char *pdata,
6260 int total_data,
6261 files_struct *fsp,
6262 const struct smb_filename *smb_fname)
6264 SMB_OFF_T size;
6266 if (total_data < 8) {
6267 return NT_STATUS_INVALID_PARAMETER;
6270 size = IVAL(pdata,0);
6271 #ifdef LARGE_SMB_OFF_T
6272 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6273 #else /* LARGE_SMB_OFF_T */
6274 if (IVAL(pdata,4) != 0) {
6275 /* more than 32 bits? */
6276 return NT_STATUS_INVALID_PARAMETER;
6278 #endif /* LARGE_SMB_OFF_T */
6279 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6280 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6281 (double)size));
6283 return smb_set_file_size(conn, req,
6284 fsp,
6285 smb_fname,
6286 &smb_fname->st,
6287 size);
6290 /****************************************************************************
6291 Allow a UNIX info mknod.
6292 ****************************************************************************/
6294 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6295 const char *pdata,
6296 int total_data,
6297 const struct smb_filename *smb_fname)
6299 uint32 file_type = IVAL(pdata,56);
6300 #if defined(HAVE_MAKEDEV)
6301 uint32 dev_major = IVAL(pdata,60);
6302 uint32 dev_minor = IVAL(pdata,68);
6303 #endif
6304 SMB_DEV_T dev = (SMB_DEV_T)0;
6305 uint32 raw_unixmode = IVAL(pdata,84);
6306 NTSTATUS status;
6307 mode_t unixmode;
6309 if (total_data < 100) {
6310 return NT_STATUS_INVALID_PARAMETER;
6313 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6314 PERM_NEW_FILE, &unixmode);
6315 if (!NT_STATUS_IS_OK(status)) {
6316 return status;
6319 #if defined(HAVE_MAKEDEV)
6320 dev = makedev(dev_major, dev_minor);
6321 #endif
6323 switch (file_type) {
6324 #if defined(S_IFIFO)
6325 case UNIX_TYPE_FIFO:
6326 unixmode |= S_IFIFO;
6327 break;
6328 #endif
6329 #if defined(S_IFSOCK)
6330 case UNIX_TYPE_SOCKET:
6331 unixmode |= S_IFSOCK;
6332 break;
6333 #endif
6334 #if defined(S_IFCHR)
6335 case UNIX_TYPE_CHARDEV:
6336 unixmode |= S_IFCHR;
6337 break;
6338 #endif
6339 #if defined(S_IFBLK)
6340 case UNIX_TYPE_BLKDEV:
6341 unixmode |= S_IFBLK;
6342 break;
6343 #endif
6344 default:
6345 return NT_STATUS_INVALID_PARAMETER;
6348 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6349 "%.0f mode 0%o for file %s\n", (double)dev,
6350 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6352 /* Ok - do the mknod. */
6353 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6354 return map_nt_error_from_unix(errno);
6357 /* If any of the other "set" calls fail we
6358 * don't want to end up with a half-constructed mknod.
6361 if (lp_inherit_perms(SNUM(conn))) {
6362 char *parent;
6363 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6364 &parent, NULL)) {
6365 return NT_STATUS_NO_MEMORY;
6367 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6368 unixmode);
6369 TALLOC_FREE(parent);
6372 return NT_STATUS_OK;
6375 /****************************************************************************
6376 Deal with SMB_SET_FILE_UNIX_BASIC.
6377 ****************************************************************************/
6379 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6380 struct smb_request *req,
6381 const char *pdata,
6382 int total_data,
6383 files_struct *fsp,
6384 const struct smb_filename *smb_fname)
6386 struct smb_file_time ft;
6387 uint32 raw_unixmode;
6388 mode_t unixmode;
6389 SMB_OFF_T size = 0;
6390 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6391 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6392 NTSTATUS status = NT_STATUS_OK;
6393 bool delete_on_fail = False;
6394 enum perm_type ptype;
6395 files_struct *all_fsps = NULL;
6396 bool modify_mtime = true;
6397 struct file_id id;
6398 SMB_STRUCT_STAT sbuf;
6400 ZERO_STRUCT(ft);
6402 if (total_data < 100) {
6403 return NT_STATUS_INVALID_PARAMETER;
6406 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6407 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6408 size=IVAL(pdata,0); /* first 8 Bytes are size */
6409 #ifdef LARGE_SMB_OFF_T
6410 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6411 #else /* LARGE_SMB_OFF_T */
6412 if (IVAL(pdata,4) != 0) {
6413 /* more than 32 bits? */
6414 return NT_STATUS_INVALID_PARAMETER;
6416 #endif /* LARGE_SMB_OFF_T */
6419 ft.atime = interpret_long_date(pdata+24); /* access_time */
6420 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6421 set_owner = (uid_t)IVAL(pdata,40);
6422 set_grp = (gid_t)IVAL(pdata,48);
6423 raw_unixmode = IVAL(pdata,84);
6425 if (VALID_STAT(smb_fname->st)) {
6426 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6427 ptype = PERM_EXISTING_DIR;
6428 } else {
6429 ptype = PERM_EXISTING_FILE;
6431 } else {
6432 ptype = PERM_NEW_FILE;
6435 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6436 ptype, &unixmode);
6437 if (!NT_STATUS_IS_OK(status)) {
6438 return status;
6441 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6442 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6443 smb_fname_str_dbg(smb_fname), (double)size,
6444 (unsigned int)set_owner, (unsigned int)set_grp,
6445 (int)raw_unixmode));
6447 sbuf = smb_fname->st;
6449 if (!VALID_STAT(sbuf)) {
6450 struct smb_filename *smb_fname_tmp = NULL;
6452 * The only valid use of this is to create character and block
6453 * devices, and named pipes. This is deprecated (IMHO) and
6454 * a new info level should be used for mknod. JRA.
6457 status = smb_unix_mknod(conn,
6458 pdata,
6459 total_data,
6460 smb_fname);
6461 if (!NT_STATUS_IS_OK(status)) {
6462 return status;
6465 status = copy_smb_filename(talloc_tos(), smb_fname,
6466 &smb_fname_tmp);
6467 if (!NT_STATUS_IS_OK(status)) {
6468 return status;
6471 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6472 status = map_nt_error_from_unix(errno);
6473 TALLOC_FREE(smb_fname_tmp);
6474 SMB_VFS_UNLINK(conn, smb_fname);
6475 return status;
6478 sbuf = smb_fname_tmp->st;
6479 TALLOC_FREE(smb_fname_tmp);
6481 /* Ensure we don't try and change anything else. */
6482 raw_unixmode = SMB_MODE_NO_CHANGE;
6483 size = get_file_size_stat(&sbuf);
6484 ft.atime = sbuf.st_ex_atime;
6485 ft.mtime = sbuf.st_ex_mtime;
6487 * We continue here as we might want to change the
6488 * owner uid/gid.
6490 delete_on_fail = True;
6493 #if 1
6494 /* Horrible backwards compatibility hack as an old server bug
6495 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6496 * */
6498 if (!size) {
6499 size = get_file_size_stat(&sbuf);
6501 #endif
6504 * Deal with the UNIX specific mode set.
6507 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6508 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6509 "setting mode 0%o for file %s\n",
6510 (unsigned int)unixmode,
6511 smb_fname_str_dbg(smb_fname)));
6512 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6513 return map_nt_error_from_unix(errno);
6518 * Deal with the UNIX specific uid set.
6521 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6522 (sbuf.st_ex_uid != set_owner)) {
6523 int ret;
6525 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6526 "changing owner %u for path %s\n",
6527 (unsigned int)set_owner,
6528 smb_fname_str_dbg(smb_fname)));
6530 if (S_ISLNK(sbuf.st_ex_mode)) {
6531 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6532 set_owner, (gid_t)-1);
6533 } else {
6534 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6535 set_owner, (gid_t)-1);
6538 if (ret != 0) {
6539 status = map_nt_error_from_unix(errno);
6540 if (delete_on_fail) {
6541 SMB_VFS_UNLINK(conn, smb_fname);
6543 return status;
6548 * Deal with the UNIX specific gid set.
6551 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6552 (sbuf.st_ex_gid != set_grp)) {
6553 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6554 "changing group %u for file %s\n",
6555 (unsigned int)set_owner,
6556 smb_fname_str_dbg(smb_fname)));
6557 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6558 set_grp) != 0) {
6559 status = map_nt_error_from_unix(errno);
6560 if (delete_on_fail) {
6561 SMB_VFS_UNLINK(conn, smb_fname);
6563 return status;
6567 /* Deal with any size changes. */
6569 status = smb_set_file_size(conn, req,
6570 fsp,
6571 smb_fname,
6572 &sbuf,
6573 size);
6574 if (!NT_STATUS_IS_OK(status)) {
6575 return status;
6578 /* Deal with any time changes. */
6579 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6580 /* No change, don't cancel anything. */
6581 return status;
6584 id = vfs_file_id_from_sbuf(conn, &sbuf);
6585 for(all_fsps = file_find_di_first(id); all_fsps;
6586 all_fsps = file_find_di_next(all_fsps)) {
6588 * We're setting the time explicitly for UNIX.
6589 * Cancel any pending changes over all handles.
6591 all_fsps->update_write_time_on_close = false;
6592 TALLOC_FREE(all_fsps->update_write_time_event);
6596 * Override the "setting_write_time"
6597 * parameter here as it almost does what
6598 * we need. Just remember if we modified
6599 * mtime and send the notify ourselves.
6601 if (null_timespec(ft.mtime)) {
6602 modify_mtime = false;
6605 status = smb_set_file_time(conn,
6606 fsp,
6607 smb_fname,
6608 &ft,
6609 false);
6610 if (modify_mtime) {
6611 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6612 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6614 return status;
6617 /****************************************************************************
6618 Deal with SMB_SET_FILE_UNIX_INFO2.
6619 ****************************************************************************/
6621 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6622 struct smb_request *req,
6623 const char *pdata,
6624 int total_data,
6625 files_struct *fsp,
6626 const struct smb_filename *smb_fname)
6628 NTSTATUS status;
6629 uint32 smb_fflags;
6630 uint32 smb_fmask;
6632 if (total_data < 116) {
6633 return NT_STATUS_INVALID_PARAMETER;
6636 /* Start by setting all the fields that are common between UNIX_BASIC
6637 * and UNIX_INFO2.
6639 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6640 fsp, smb_fname);
6641 if (!NT_STATUS_IS_OK(status)) {
6642 return status;
6645 smb_fflags = IVAL(pdata, 108);
6646 smb_fmask = IVAL(pdata, 112);
6648 /* NB: We should only attempt to alter the file flags if the client
6649 * sends a non-zero mask.
6651 if (smb_fmask != 0) {
6652 int stat_fflags = 0;
6654 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6655 smb_fmask, &stat_fflags)) {
6656 /* Client asked to alter a flag we don't understand. */
6657 return NT_STATUS_INVALID_PARAMETER;
6660 if (fsp && fsp->fh->fd != -1) {
6661 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6662 return NT_STATUS_NOT_SUPPORTED;
6663 } else {
6664 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6665 stat_fflags) != 0) {
6666 return map_nt_error_from_unix(errno);
6671 /* XXX: need to add support for changing the create_time here. You
6672 * can do this for paths on Darwin with setattrlist(2). The right way
6673 * to hook this up is probably by extending the VFS utimes interface.
6676 return NT_STATUS_OK;
6679 /****************************************************************************
6680 Create a directory with POSIX semantics.
6681 ****************************************************************************/
6683 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6684 struct smb_request *req,
6685 char **ppdata,
6686 int total_data,
6687 struct smb_filename *smb_fname,
6688 int *pdata_return_size)
6690 NTSTATUS status = NT_STATUS_OK;
6691 uint32 raw_unixmode = 0;
6692 uint32 mod_unixmode = 0;
6693 mode_t unixmode = (mode_t)0;
6694 files_struct *fsp = NULL;
6695 uint16 info_level_return = 0;
6696 int info;
6697 char *pdata = *ppdata;
6699 if (total_data < 18) {
6700 return NT_STATUS_INVALID_PARAMETER;
6703 raw_unixmode = IVAL(pdata,8);
6704 /* Next 4 bytes are not yet defined. */
6706 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6707 PERM_NEW_DIR, &unixmode);
6708 if (!NT_STATUS_IS_OK(status)) {
6709 return status;
6712 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6714 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6715 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6717 status = SMB_VFS_CREATE_FILE(
6718 conn, /* conn */
6719 req, /* req */
6720 0, /* root_dir_fid */
6721 smb_fname, /* fname */
6722 FILE_READ_ATTRIBUTES, /* access_mask */
6723 FILE_SHARE_NONE, /* share_access */
6724 FILE_CREATE, /* create_disposition*/
6725 FILE_DIRECTORY_FILE, /* create_options */
6726 mod_unixmode, /* file_attributes */
6727 0, /* oplock_request */
6728 0, /* allocation_size */
6729 NULL, /* sd */
6730 NULL, /* ea_list */
6731 &fsp, /* result */
6732 &info); /* pinfo */
6734 if (NT_STATUS_IS_OK(status)) {
6735 close_file(req, fsp, NORMAL_CLOSE);
6738 info_level_return = SVAL(pdata,16);
6740 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6741 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6742 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6743 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6744 } else {
6745 *pdata_return_size = 12;
6748 /* Realloc the data size */
6749 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6750 if (*ppdata == NULL) {
6751 *pdata_return_size = 0;
6752 return NT_STATUS_NO_MEMORY;
6754 pdata = *ppdata;
6756 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6757 SSVAL(pdata,2,0); /* No fnum. */
6758 SIVAL(pdata,4,info); /* Was directory created. */
6760 switch (info_level_return) {
6761 case SMB_QUERY_FILE_UNIX_BASIC:
6762 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6763 SSVAL(pdata,10,0); /* Padding. */
6764 store_file_unix_basic(conn, pdata + 12, fsp,
6765 &smb_fname->st);
6766 break;
6767 case SMB_QUERY_FILE_UNIX_INFO2:
6768 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6769 SSVAL(pdata,10,0); /* Padding. */
6770 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6771 &smb_fname->st);
6772 break;
6773 default:
6774 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6775 SSVAL(pdata,10,0); /* Padding. */
6776 break;
6779 return status;
6782 /****************************************************************************
6783 Open/Create a file with POSIX semantics.
6784 ****************************************************************************/
6786 static NTSTATUS smb_posix_open(connection_struct *conn,
6787 struct smb_request *req,
6788 char **ppdata,
6789 int total_data,
6790 struct smb_filename *smb_fname,
6791 int *pdata_return_size)
6793 bool extended_oplock_granted = False;
6794 char *pdata = *ppdata;
6795 uint32 flags = 0;
6796 uint32 wire_open_mode = 0;
6797 uint32 raw_unixmode = 0;
6798 uint32 mod_unixmode = 0;
6799 uint32 create_disp = 0;
6800 uint32 access_mask = 0;
6801 uint32 create_options = 0;
6802 NTSTATUS status = NT_STATUS_OK;
6803 mode_t unixmode = (mode_t)0;
6804 files_struct *fsp = NULL;
6805 int oplock_request = 0;
6806 int info = 0;
6807 uint16 info_level_return = 0;
6809 if (total_data < 18) {
6810 return NT_STATUS_INVALID_PARAMETER;
6813 flags = IVAL(pdata,0);
6814 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6815 if (oplock_request) {
6816 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6819 wire_open_mode = IVAL(pdata,4);
6821 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6822 return smb_posix_mkdir(conn, req,
6823 ppdata,
6824 total_data,
6825 smb_fname,
6826 pdata_return_size);
6829 switch (wire_open_mode & SMB_ACCMODE) {
6830 case SMB_O_RDONLY:
6831 access_mask = FILE_READ_DATA;
6832 break;
6833 case SMB_O_WRONLY:
6834 access_mask = FILE_WRITE_DATA;
6835 break;
6836 case SMB_O_RDWR:
6837 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6838 break;
6839 default:
6840 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6841 (unsigned int)wire_open_mode ));
6842 return NT_STATUS_INVALID_PARAMETER;
6845 wire_open_mode &= ~SMB_ACCMODE;
6847 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6848 create_disp = FILE_CREATE;
6849 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6850 create_disp = FILE_OVERWRITE_IF;
6851 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6852 create_disp = FILE_OPEN_IF;
6853 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6854 create_disp = FILE_OPEN;
6855 } else {
6856 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6857 (unsigned int)wire_open_mode ));
6858 return NT_STATUS_INVALID_PARAMETER;
6861 raw_unixmode = IVAL(pdata,8);
6862 /* Next 4 bytes are not yet defined. */
6864 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6865 (VALID_STAT(smb_fname->st) ?
6866 PERM_EXISTING_FILE : PERM_NEW_FILE),
6867 &unixmode);
6869 if (!NT_STATUS_IS_OK(status)) {
6870 return status;
6873 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6875 if (wire_open_mode & SMB_O_SYNC) {
6876 create_options |= FILE_WRITE_THROUGH;
6878 if (wire_open_mode & SMB_O_APPEND) {
6879 access_mask |= FILE_APPEND_DATA;
6881 if (wire_open_mode & SMB_O_DIRECT) {
6882 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6885 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6886 smb_fname_str_dbg(smb_fname),
6887 (unsigned int)wire_open_mode,
6888 (unsigned int)unixmode ));
6890 status = SMB_VFS_CREATE_FILE(
6891 conn, /* conn */
6892 req, /* req */
6893 0, /* root_dir_fid */
6894 smb_fname, /* fname */
6895 access_mask, /* access_mask */
6896 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6897 FILE_SHARE_DELETE),
6898 create_disp, /* create_disposition*/
6899 FILE_NON_DIRECTORY_FILE, /* create_options */
6900 mod_unixmode, /* file_attributes */
6901 oplock_request, /* oplock_request */
6902 0, /* allocation_size */
6903 NULL, /* sd */
6904 NULL, /* ea_list */
6905 &fsp, /* result */
6906 &info); /* pinfo */
6908 if (!NT_STATUS_IS_OK(status)) {
6909 return status;
6912 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6913 extended_oplock_granted = True;
6916 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6917 extended_oplock_granted = True;
6920 info_level_return = SVAL(pdata,16);
6922 /* Allocate the correct return size. */
6924 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6925 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6926 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6927 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6928 } else {
6929 *pdata_return_size = 12;
6932 /* Realloc the data size */
6933 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6934 if (*ppdata == NULL) {
6935 close_file(req, fsp, ERROR_CLOSE);
6936 *pdata_return_size = 0;
6937 return NT_STATUS_NO_MEMORY;
6939 pdata = *ppdata;
6941 if (extended_oplock_granted) {
6942 if (flags & REQUEST_BATCH_OPLOCK) {
6943 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6944 } else {
6945 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6947 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6948 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6949 } else {
6950 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6953 SSVAL(pdata,2,fsp->fnum);
6954 SIVAL(pdata,4,info); /* Was file created etc. */
6956 switch (info_level_return) {
6957 case SMB_QUERY_FILE_UNIX_BASIC:
6958 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6959 SSVAL(pdata,10,0); /* padding. */
6960 store_file_unix_basic(conn, pdata + 12, fsp,
6961 &smb_fname->st);
6962 break;
6963 case SMB_QUERY_FILE_UNIX_INFO2:
6964 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6965 SSVAL(pdata,10,0); /* padding. */
6966 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6967 &smb_fname->st);
6968 break;
6969 default:
6970 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6971 SSVAL(pdata,10,0); /* padding. */
6972 break;
6974 return NT_STATUS_OK;
6977 /****************************************************************************
6978 Delete a file with POSIX semantics.
6979 ****************************************************************************/
6981 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6982 struct smb_request *req,
6983 const char *pdata,
6984 int total_data,
6985 struct smb_filename *smb_fname)
6987 NTSTATUS status = NT_STATUS_OK;
6988 files_struct *fsp = NULL;
6989 uint16 flags = 0;
6990 char del = 1;
6991 int info = 0;
6992 int create_options = 0;
6993 int i;
6994 struct share_mode_lock *lck = NULL;
6996 if (total_data < 2) {
6997 return NT_STATUS_INVALID_PARAMETER;
7000 flags = SVAL(pdata,0);
7002 if (!VALID_STAT(smb_fname->st)) {
7003 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7006 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7007 !VALID_STAT_OF_DIR(smb_fname->st)) {
7008 return NT_STATUS_NOT_A_DIRECTORY;
7011 DEBUG(10,("smb_posix_unlink: %s %s\n",
7012 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7013 smb_fname_str_dbg(smb_fname)));
7015 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7016 create_options |= FILE_DIRECTORY_FILE;
7019 status = SMB_VFS_CREATE_FILE(
7020 conn, /* conn */
7021 req, /* req */
7022 0, /* root_dir_fid */
7023 smb_fname, /* fname */
7024 DELETE_ACCESS, /* access_mask */
7025 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7026 FILE_SHARE_DELETE),
7027 FILE_OPEN, /* create_disposition*/
7028 create_options, /* create_options */
7029 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7030 0, /* oplock_request */
7031 0, /* allocation_size */
7032 NULL, /* sd */
7033 NULL, /* ea_list */
7034 &fsp, /* result */
7035 &info); /* pinfo */
7037 if (!NT_STATUS_IS_OK(status)) {
7038 return status;
7042 * Don't lie to client. If we can't really delete due to
7043 * non-POSIX opens return SHARING_VIOLATION.
7046 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7047 NULL);
7048 if (lck == NULL) {
7049 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7050 "lock for file %s\n", fsp_str_dbg(fsp)));
7051 close_file(req, fsp, NORMAL_CLOSE);
7052 return NT_STATUS_INVALID_PARAMETER;
7056 * See if others still have the file open. If this is the case, then
7057 * don't delete. If all opens are POSIX delete we can set the delete
7058 * on close disposition.
7060 for (i=0; i<lck->num_share_modes; i++) {
7061 struct share_mode_entry *e = &lck->share_modes[i];
7062 if (is_valid_share_mode_entry(e)) {
7063 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7064 continue;
7066 /* Fail with sharing violation. */
7067 close_file(req, fsp, NORMAL_CLOSE);
7068 TALLOC_FREE(lck);
7069 return NT_STATUS_SHARING_VIOLATION;
7074 * Set the delete on close.
7076 status = smb_set_file_disposition_info(conn,
7077 &del,
7079 fsp,
7080 smb_fname);
7082 if (!NT_STATUS_IS_OK(status)) {
7083 close_file(req, fsp, NORMAL_CLOSE);
7084 TALLOC_FREE(lck);
7085 return status;
7087 TALLOC_FREE(lck);
7088 return close_file(req, fsp, NORMAL_CLOSE);
7091 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7092 struct smb_request *req,
7093 TALLOC_CTX *mem_ctx,
7094 uint16_t info_level,
7095 files_struct *fsp,
7096 struct smb_filename *smb_fname,
7097 char **ppdata, int total_data,
7098 int *ret_data_size)
7100 char *pdata = *ppdata;
7101 NTSTATUS status = NT_STATUS_OK;
7102 int data_return_size = 0;
7104 *ret_data_size = 0;
7106 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7107 return NT_STATUS_INVALID_LEVEL;
7110 if (!CAN_WRITE(conn)) {
7111 /* Allow POSIX opens. The open path will deny
7112 * any non-readonly opens. */
7113 if (info_level != SMB_POSIX_PATH_OPEN) {
7114 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7118 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7119 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7120 fsp ? fsp->fnum : -1, info_level, total_data));
7122 switch (info_level) {
7124 case SMB_INFO_STANDARD:
7126 status = smb_set_info_standard(conn,
7127 pdata,
7128 total_data,
7129 fsp,
7130 smb_fname);
7131 break;
7134 case SMB_INFO_SET_EA:
7136 status = smb_info_set_ea(conn,
7137 pdata,
7138 total_data,
7139 fsp,
7140 smb_fname);
7141 break;
7144 case SMB_SET_FILE_BASIC_INFO:
7145 case SMB_FILE_BASIC_INFORMATION:
7147 status = smb_set_file_basic_info(conn,
7148 pdata,
7149 total_data,
7150 fsp,
7151 smb_fname);
7152 break;
7155 case SMB_FILE_ALLOCATION_INFORMATION:
7156 case SMB_SET_FILE_ALLOCATION_INFO:
7158 status = smb_set_file_allocation_info(conn, req,
7159 pdata,
7160 total_data,
7161 fsp,
7162 smb_fname);
7163 break;
7166 case SMB_FILE_END_OF_FILE_INFORMATION:
7167 case SMB_SET_FILE_END_OF_FILE_INFO:
7169 status = smb_set_file_end_of_file_info(conn, req,
7170 pdata,
7171 total_data,
7172 fsp,
7173 smb_fname);
7174 break;
7177 case SMB_FILE_DISPOSITION_INFORMATION:
7178 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7180 #if 0
7181 /* JRA - We used to just ignore this on a path ?
7182 * Shouldn't this be invalid level on a pathname
7183 * based call ?
7185 if (tran_call != TRANSACT2_SETFILEINFO) {
7186 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7188 #endif
7189 status = smb_set_file_disposition_info(conn,
7190 pdata,
7191 total_data,
7192 fsp,
7193 smb_fname);
7194 break;
7197 case SMB_FILE_POSITION_INFORMATION:
7199 status = smb_file_position_information(conn,
7200 pdata,
7201 total_data,
7202 fsp);
7203 break;
7206 /* From tridge Samba4 :
7207 * MODE_INFORMATION in setfileinfo (I have no
7208 * idea what "mode information" on a file is - it takes a value of 0,
7209 * 2, 4 or 6. What could it be?).
7212 case SMB_FILE_MODE_INFORMATION:
7214 status = smb_file_mode_information(conn,
7215 pdata,
7216 total_data);
7217 break;
7221 * CIFS UNIX extensions.
7224 case SMB_SET_FILE_UNIX_BASIC:
7226 status = smb_set_file_unix_basic(conn, req,
7227 pdata,
7228 total_data,
7229 fsp,
7230 smb_fname);
7231 break;
7234 case SMB_SET_FILE_UNIX_INFO2:
7236 status = smb_set_file_unix_info2(conn, req,
7237 pdata,
7238 total_data,
7239 fsp,
7240 smb_fname);
7241 break;
7244 case SMB_SET_FILE_UNIX_LINK:
7246 if (fsp) {
7247 /* We must have a pathname for this. */
7248 return NT_STATUS_INVALID_LEVEL;
7250 status = smb_set_file_unix_link(conn, req, pdata,
7251 total_data, smb_fname);
7252 break;
7255 case SMB_SET_FILE_UNIX_HLINK:
7257 if (fsp) {
7258 /* We must have a pathname for this. */
7259 return NT_STATUS_INVALID_LEVEL;
7261 status = smb_set_file_unix_hlink(conn, req,
7262 pdata, total_data,
7263 smb_fname);
7264 break;
7267 case SMB_FILE_RENAME_INFORMATION:
7269 status = smb_file_rename_information(conn, req,
7270 pdata, total_data,
7271 fsp, smb_fname);
7272 break;
7275 #if defined(HAVE_POSIX_ACLS)
7276 case SMB_SET_POSIX_ACL:
7278 status = smb_set_posix_acl(conn,
7279 pdata,
7280 total_data,
7281 fsp,
7282 smb_fname);
7283 break;
7285 #endif
7287 case SMB_SET_POSIX_LOCK:
7289 if (!fsp) {
7290 return NT_STATUS_INVALID_LEVEL;
7292 status = smb_set_posix_lock(conn, req,
7293 pdata, total_data, fsp);
7294 break;
7297 case SMB_POSIX_PATH_OPEN:
7299 if (fsp) {
7300 /* We must have a pathname for this. */
7301 return NT_STATUS_INVALID_LEVEL;
7304 status = smb_posix_open(conn, req,
7305 ppdata,
7306 total_data,
7307 smb_fname,
7308 &data_return_size);
7309 break;
7312 case SMB_POSIX_PATH_UNLINK:
7314 if (fsp) {
7315 /* We must have a pathname for this. */
7316 return NT_STATUS_INVALID_LEVEL;
7319 status = smb_posix_unlink(conn, req,
7320 pdata,
7321 total_data,
7322 smb_fname);
7323 break;
7326 default:
7327 return NT_STATUS_INVALID_LEVEL;
7330 if (!NT_STATUS_IS_OK(status)) {
7331 return status;
7334 *ret_data_size = data_return_size;
7335 return NT_STATUS_OK;
7338 /****************************************************************************
7339 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7340 ****************************************************************************/
7342 static void call_trans2setfilepathinfo(connection_struct *conn,
7343 struct smb_request *req,
7344 unsigned int tran_call,
7345 char **pparams, int total_params,
7346 char **ppdata, int total_data,
7347 unsigned int max_data_bytes)
7349 char *params = *pparams;
7350 char *pdata = *ppdata;
7351 uint16 info_level;
7352 struct smb_filename *smb_fname = NULL;
7353 files_struct *fsp = NULL;
7354 NTSTATUS status = NT_STATUS_OK;
7355 int data_return_size = 0;
7357 if (!params) {
7358 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7359 return;
7362 if (tran_call == TRANSACT2_SETFILEINFO) {
7363 if (total_params < 4) {
7364 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7365 return;
7368 fsp = file_fsp(req, SVAL(params,0));
7369 /* Basic check for non-null fsp. */
7370 if (!check_fsp_open(conn, req, fsp)) {
7371 return;
7373 info_level = SVAL(params,2);
7375 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7376 &smb_fname);
7377 if (!NT_STATUS_IS_OK(status)) {
7378 reply_nterror(req, status);
7379 return;
7382 if(fsp->is_directory || fsp->fh->fd == -1) {
7384 * This is actually a SETFILEINFO on a directory
7385 * handle (returned from an NT SMB). NT5.0 seems
7386 * to do this call. JRA.
7388 if (INFO_LEVEL_IS_UNIX(info_level)) {
7389 /* Always do lstat for UNIX calls. */
7390 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7391 DEBUG(3,("call_trans2setfilepathinfo: "
7392 "SMB_VFS_LSTAT of %s failed "
7393 "(%s)\n",
7394 smb_fname_str_dbg(smb_fname),
7395 strerror(errno)));
7396 reply_nterror(req, map_nt_error_from_unix(errno));
7397 return;
7399 } else {
7400 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7401 DEBUG(3,("call_trans2setfilepathinfo: "
7402 "fileinfo of %s failed (%s)\n",
7403 smb_fname_str_dbg(smb_fname),
7404 strerror(errno)));
7405 reply_nterror(req, map_nt_error_from_unix(errno));
7406 return;
7409 } else if (fsp->print_file) {
7411 * Doing a DELETE_ON_CLOSE should cancel a print job.
7413 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7414 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7416 DEBUG(3,("call_trans2setfilepathinfo: "
7417 "Cancelling print job (%s)\n",
7418 fsp_str_dbg(fsp)));
7420 SSVAL(params,0,0);
7421 send_trans2_replies(conn, req, params, 2,
7422 *ppdata, 0,
7423 max_data_bytes);
7424 return;
7425 } else {
7426 reply_doserror(req, ERRDOS, ERRbadpath);
7427 return;
7429 } else {
7431 * Original code - this is an open file.
7433 if (!check_fsp(conn, req, fsp)) {
7434 return;
7437 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7438 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7439 "of fnum %d failed (%s)\n", fsp->fnum,
7440 strerror(errno)));
7441 reply_nterror(req, map_nt_error_from_unix(errno));
7442 return;
7445 } else {
7446 char *fname = NULL;
7448 /* set path info */
7449 if (total_params < 7) {
7450 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7451 return;
7454 info_level = SVAL(params,0);
7455 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7456 total_params - 6, STR_TERMINATE,
7457 &status);
7458 if (!NT_STATUS_IS_OK(status)) {
7459 reply_nterror(req, status);
7460 return;
7463 status = filename_convert(req, conn,
7464 req->flags2 & FLAGS2_DFS_PATHNAMES,
7465 fname,
7467 NULL,
7468 &smb_fname);
7469 if (!NT_STATUS_IS_OK(status)) {
7470 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7471 reply_botherror(req,
7472 NT_STATUS_PATH_NOT_COVERED,
7473 ERRSRV, ERRbadpath);
7474 return;
7476 reply_nterror(req, status);
7477 return;
7480 if (INFO_LEVEL_IS_UNIX(info_level)) {
7482 * For CIFS UNIX extensions the target name may not exist.
7485 /* Always do lstat for UNIX calls. */
7486 SMB_VFS_LSTAT(conn, smb_fname);
7488 } else if (!VALID_STAT(smb_fname->st) &&
7489 SMB_VFS_STAT(conn, smb_fname)) {
7490 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7491 "%s failed (%s)\n",
7492 smb_fname_str_dbg(smb_fname),
7493 strerror(errno)));
7494 reply_nterror(req, map_nt_error_from_unix(errno));
7495 return;
7499 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7500 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7501 fsp ? fsp->fnum : -1, info_level,total_data));
7503 /* Realloc the parameter size */
7504 *pparams = (char *)SMB_REALLOC(*pparams,2);
7505 if (*pparams == NULL) {
7506 reply_nterror(req, NT_STATUS_NO_MEMORY);
7507 return;
7509 params = *pparams;
7511 SSVAL(params,0,0);
7513 status = smbd_do_setfilepathinfo(conn, req, req,
7514 info_level,
7515 fsp,
7516 smb_fname,
7517 ppdata, total_data,
7518 &data_return_size);
7519 if (!NT_STATUS_IS_OK(status)) {
7520 if (open_was_deferred(req->mid)) {
7521 /* We have re-scheduled this call. */
7522 return;
7524 if (blocking_lock_was_deferred(req->mid)) {
7525 /* We have re-scheduled this call. */
7526 return;
7528 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7529 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7530 ERRSRV, ERRbadpath);
7531 return;
7533 if (info_level == SMB_POSIX_PATH_OPEN) {
7534 reply_openerror(req, status);
7535 return;
7538 reply_nterror(req, status);
7539 return;
7542 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7543 max_data_bytes);
7545 return;
7548 /****************************************************************************
7549 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7550 ****************************************************************************/
7552 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7553 char **pparams, int total_params,
7554 char **ppdata, int total_data,
7555 unsigned int max_data_bytes)
7557 struct smb_filename *smb_dname = NULL;
7558 char *params = *pparams;
7559 char *pdata = *ppdata;
7560 char *directory = NULL;
7561 NTSTATUS status = NT_STATUS_OK;
7562 struct ea_list *ea_list = NULL;
7563 TALLOC_CTX *ctx = talloc_tos();
7565 if (!CAN_WRITE(conn)) {
7566 reply_doserror(req, ERRSRV, ERRaccess);
7567 return;
7570 if (total_params < 5) {
7571 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7572 return;
7575 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7576 total_params - 4, STR_TERMINATE,
7577 &status);
7578 if (!NT_STATUS_IS_OK(status)) {
7579 reply_nterror(req, status);
7580 return;
7583 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7585 status = filename_convert(ctx,
7586 conn,
7587 req->flags2 & FLAGS2_DFS_PATHNAMES,
7588 directory,
7590 NULL,
7591 &smb_dname);
7593 if (!NT_STATUS_IS_OK(status)) {
7594 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7595 reply_botherror(req,
7596 NT_STATUS_PATH_NOT_COVERED,
7597 ERRSRV, ERRbadpath);
7598 return;
7600 reply_nterror(req, status);
7601 return;
7604 /* Any data in this call is an EA list. */
7605 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7606 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7607 goto out;
7611 * OS/2 workplace shell seems to send SET_EA requests of "null"
7612 * length (4 bytes containing IVAL 4).
7613 * They seem to have no effect. Bug #3212. JRA.
7616 if (total_data != 4) {
7617 if (total_data < 10) {
7618 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7619 goto out;
7622 if (IVAL(pdata,0) > total_data) {
7623 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7624 IVAL(pdata,0), (unsigned int)total_data));
7625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7626 goto out;
7629 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7630 total_data - 4);
7631 if (!ea_list) {
7632 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7633 goto out;
7636 /* If total_data == 4 Windows doesn't care what values
7637 * are placed in that field, it just ignores them.
7638 * The System i QNTC IBM SMB client puts bad values here,
7639 * so ignore them. */
7641 status = create_directory(conn, req, smb_dname);
7643 if (!NT_STATUS_IS_OK(status)) {
7644 reply_nterror(req, status);
7645 goto out;
7648 /* Try and set any given EA. */
7649 if (ea_list) {
7650 status = set_ea(conn, NULL, smb_dname, ea_list);
7651 if (!NT_STATUS_IS_OK(status)) {
7652 reply_nterror(req, status);
7653 goto out;
7657 /* Realloc the parameter and data sizes */
7658 *pparams = (char *)SMB_REALLOC(*pparams,2);
7659 if(*pparams == NULL) {
7660 reply_nterror(req, NT_STATUS_NO_MEMORY);
7661 goto out;
7663 params = *pparams;
7665 SSVAL(params,0,0);
7667 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7669 out:
7670 TALLOC_FREE(smb_dname);
7671 return;
7674 /****************************************************************************
7675 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7676 We don't actually do this - we just send a null response.
7677 ****************************************************************************/
7679 static void call_trans2findnotifyfirst(connection_struct *conn,
7680 struct smb_request *req,
7681 char **pparams, int total_params,
7682 char **ppdata, int total_data,
7683 unsigned int max_data_bytes)
7685 char *params = *pparams;
7686 uint16 info_level;
7688 if (total_params < 6) {
7689 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7690 return;
7693 info_level = SVAL(params,4);
7694 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7696 switch (info_level) {
7697 case 1:
7698 case 2:
7699 break;
7700 default:
7701 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7702 return;
7705 /* Realloc the parameter and data sizes */
7706 *pparams = (char *)SMB_REALLOC(*pparams,6);
7707 if (*pparams == NULL) {
7708 reply_nterror(req, NT_STATUS_NO_MEMORY);
7709 return;
7711 params = *pparams;
7713 SSVAL(params,0,fnf_handle);
7714 SSVAL(params,2,0); /* No changes */
7715 SSVAL(params,4,0); /* No EA errors */
7717 fnf_handle++;
7719 if(fnf_handle == 0)
7720 fnf_handle = 257;
7722 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7724 return;
7727 /****************************************************************************
7728 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7729 changes). Currently this does nothing.
7730 ****************************************************************************/
7732 static void call_trans2findnotifynext(connection_struct *conn,
7733 struct smb_request *req,
7734 char **pparams, int total_params,
7735 char **ppdata, int total_data,
7736 unsigned int max_data_bytes)
7738 char *params = *pparams;
7740 DEBUG(3,("call_trans2findnotifynext\n"));
7742 /* Realloc the parameter and data sizes */
7743 *pparams = (char *)SMB_REALLOC(*pparams,4);
7744 if (*pparams == NULL) {
7745 reply_nterror(req, NT_STATUS_NO_MEMORY);
7746 return;
7748 params = *pparams;
7750 SSVAL(params,0,0); /* No changes */
7751 SSVAL(params,2,0); /* No EA errors */
7753 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7755 return;
7758 /****************************************************************************
7759 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7760 ****************************************************************************/
7762 static void call_trans2getdfsreferral(connection_struct *conn,
7763 struct smb_request *req,
7764 char **pparams, int total_params,
7765 char **ppdata, int total_data,
7766 unsigned int max_data_bytes)
7768 char *params = *pparams;
7769 char *pathname = NULL;
7770 int reply_size = 0;
7771 int max_referral_level;
7772 NTSTATUS status = NT_STATUS_OK;
7773 TALLOC_CTX *ctx = talloc_tos();
7775 DEBUG(10,("call_trans2getdfsreferral\n"));
7777 if (total_params < 3) {
7778 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7779 return;
7782 max_referral_level = SVAL(params,0);
7784 if(!lp_host_msdfs()) {
7785 reply_doserror(req, ERRDOS, ERRbadfunc);
7786 return;
7789 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7790 total_params - 2, STR_TERMINATE);
7791 if (!pathname) {
7792 reply_nterror(req, NT_STATUS_NOT_FOUND);
7793 return;
7795 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7796 ppdata,&status)) < 0) {
7797 reply_nterror(req, status);
7798 return;
7801 SSVAL(req->inbuf, smb_flg2,
7802 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7803 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7805 return;
7808 #define LMCAT_SPL 0x53
7809 #define LMFUNC_GETJOBID 0x60
7811 /****************************************************************************
7812 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7813 ****************************************************************************/
7815 static void call_trans2ioctl(connection_struct *conn,
7816 struct smb_request *req,
7817 char **pparams, int total_params,
7818 char **ppdata, int total_data,
7819 unsigned int max_data_bytes)
7821 char *pdata = *ppdata;
7822 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7824 /* check for an invalid fid before proceeding */
7826 if (!fsp) {
7827 reply_doserror(req, ERRDOS, ERRbadfid);
7828 return;
7831 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7832 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7833 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7834 if (*ppdata == NULL) {
7835 reply_nterror(req, NT_STATUS_NO_MEMORY);
7836 return;
7838 pdata = *ppdata;
7840 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7841 CAN ACCEPT THIS IN UNICODE. JRA. */
7843 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7844 srvstr_push(pdata, req->flags2, pdata + 2,
7845 global_myname(), 15,
7846 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7847 srvstr_push(pdata, req->flags2, pdata+18,
7848 lp_servicename(SNUM(conn)), 13,
7849 STR_ASCII|STR_TERMINATE); /* Service name */
7850 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7851 max_data_bytes);
7852 return;
7855 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7856 reply_doserror(req, ERRSRV, ERRerror);
7859 /****************************************************************************
7860 Reply to a SMBfindclose (stop trans2 directory search).
7861 ****************************************************************************/
7863 void reply_findclose(struct smb_request *req)
7865 int dptr_num;
7866 struct smbd_server_connection *sconn = smbd_server_conn;
7868 START_PROFILE(SMBfindclose);
7870 if (req->wct < 1) {
7871 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7872 END_PROFILE(SMBfindclose);
7873 return;
7876 dptr_num = SVALS(req->vwv+0, 0);
7878 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7880 dptr_close(sconn, &dptr_num);
7882 reply_outbuf(req, 0, 0);
7884 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7886 END_PROFILE(SMBfindclose);
7887 return;
7890 /****************************************************************************
7891 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7892 ****************************************************************************/
7894 void reply_findnclose(struct smb_request *req)
7896 int dptr_num;
7898 START_PROFILE(SMBfindnclose);
7900 if (req->wct < 1) {
7901 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7902 END_PROFILE(SMBfindnclose);
7903 return;
7906 dptr_num = SVAL(req->vwv+0, 0);
7908 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7910 /* We never give out valid handles for a
7911 findnotifyfirst - so any dptr_num is ok here.
7912 Just ignore it. */
7914 reply_outbuf(req, 0, 0);
7916 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7918 END_PROFILE(SMBfindnclose);
7919 return;
7922 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7923 struct trans_state *state)
7925 if (Protocol >= PROTOCOL_NT1) {
7926 req->flags2 |= 0x40; /* IS_LONG_NAME */
7927 SSVAL(req->inbuf,smb_flg2,req->flags2);
7930 if (conn->encrypt_level == Required && !req->encrypted) {
7931 if (state->call != TRANSACT2_QFSINFO &&
7932 state->call != TRANSACT2_SETFSINFO) {
7933 DEBUG(0,("handle_trans2: encryption required "
7934 "with call 0x%x\n",
7935 (unsigned int)state->call));
7936 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7937 return;
7941 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7943 /* Now we must call the relevant TRANS2 function */
7944 switch(state->call) {
7945 case TRANSACT2_OPEN:
7947 START_PROFILE(Trans2_open);
7948 call_trans2open(conn, req,
7949 &state->param, state->total_param,
7950 &state->data, state->total_data,
7951 state->max_data_return);
7952 END_PROFILE(Trans2_open);
7953 break;
7956 case TRANSACT2_FINDFIRST:
7958 START_PROFILE(Trans2_findfirst);
7959 call_trans2findfirst(conn, req,
7960 &state->param, state->total_param,
7961 &state->data, state->total_data,
7962 state->max_data_return);
7963 END_PROFILE(Trans2_findfirst);
7964 break;
7967 case TRANSACT2_FINDNEXT:
7969 START_PROFILE(Trans2_findnext);
7970 call_trans2findnext(conn, req,
7971 &state->param, state->total_param,
7972 &state->data, state->total_data,
7973 state->max_data_return);
7974 END_PROFILE(Trans2_findnext);
7975 break;
7978 case TRANSACT2_QFSINFO:
7980 START_PROFILE(Trans2_qfsinfo);
7981 call_trans2qfsinfo(conn, req,
7982 &state->param, state->total_param,
7983 &state->data, state->total_data,
7984 state->max_data_return);
7985 END_PROFILE(Trans2_qfsinfo);
7986 break;
7989 case TRANSACT2_SETFSINFO:
7991 START_PROFILE(Trans2_setfsinfo);
7992 call_trans2setfsinfo(conn, req,
7993 &state->param, state->total_param,
7994 &state->data, state->total_data,
7995 state->max_data_return);
7996 END_PROFILE(Trans2_setfsinfo);
7997 break;
8000 case TRANSACT2_QPATHINFO:
8001 case TRANSACT2_QFILEINFO:
8003 START_PROFILE(Trans2_qpathinfo);
8004 call_trans2qfilepathinfo(conn, req, state->call,
8005 &state->param, state->total_param,
8006 &state->data, state->total_data,
8007 state->max_data_return);
8008 END_PROFILE(Trans2_qpathinfo);
8009 break;
8012 case TRANSACT2_SETPATHINFO:
8013 case TRANSACT2_SETFILEINFO:
8015 START_PROFILE(Trans2_setpathinfo);
8016 call_trans2setfilepathinfo(conn, req, state->call,
8017 &state->param, state->total_param,
8018 &state->data, state->total_data,
8019 state->max_data_return);
8020 END_PROFILE(Trans2_setpathinfo);
8021 break;
8024 case TRANSACT2_FINDNOTIFYFIRST:
8026 START_PROFILE(Trans2_findnotifyfirst);
8027 call_trans2findnotifyfirst(conn, req,
8028 &state->param, state->total_param,
8029 &state->data, state->total_data,
8030 state->max_data_return);
8031 END_PROFILE(Trans2_findnotifyfirst);
8032 break;
8035 case TRANSACT2_FINDNOTIFYNEXT:
8037 START_PROFILE(Trans2_findnotifynext);
8038 call_trans2findnotifynext(conn, req,
8039 &state->param, state->total_param,
8040 &state->data, state->total_data,
8041 state->max_data_return);
8042 END_PROFILE(Trans2_findnotifynext);
8043 break;
8046 case TRANSACT2_MKDIR:
8048 START_PROFILE(Trans2_mkdir);
8049 call_trans2mkdir(conn, req,
8050 &state->param, state->total_param,
8051 &state->data, state->total_data,
8052 state->max_data_return);
8053 END_PROFILE(Trans2_mkdir);
8054 break;
8057 case TRANSACT2_GET_DFS_REFERRAL:
8059 START_PROFILE(Trans2_get_dfs_referral);
8060 call_trans2getdfsreferral(conn, req,
8061 &state->param, state->total_param,
8062 &state->data, state->total_data,
8063 state->max_data_return);
8064 END_PROFILE(Trans2_get_dfs_referral);
8065 break;
8068 case TRANSACT2_IOCTL:
8070 START_PROFILE(Trans2_ioctl);
8071 call_trans2ioctl(conn, req,
8072 &state->param, state->total_param,
8073 &state->data, state->total_data,
8074 state->max_data_return);
8075 END_PROFILE(Trans2_ioctl);
8076 break;
8079 default:
8080 /* Error in request */
8081 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8082 reply_doserror(req, ERRSRV,ERRerror);
8086 /****************************************************************************
8087 Reply to a SMBtrans2.
8088 ****************************************************************************/
8090 void reply_trans2(struct smb_request *req)
8092 connection_struct *conn = req->conn;
8093 unsigned int dsoff;
8094 unsigned int dscnt;
8095 unsigned int psoff;
8096 unsigned int pscnt;
8097 unsigned int tran_call;
8098 struct trans_state *state;
8099 NTSTATUS result;
8101 START_PROFILE(SMBtrans2);
8103 if (req->wct < 14) {
8104 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8105 END_PROFILE(SMBtrans2);
8106 return;
8109 dsoff = SVAL(req->vwv+12, 0);
8110 dscnt = SVAL(req->vwv+11, 0);
8111 psoff = SVAL(req->vwv+10, 0);
8112 pscnt = SVAL(req->vwv+9, 0);
8113 tran_call = SVAL(req->vwv+14, 0);
8115 result = allow_new_trans(conn->pending_trans, req->mid);
8116 if (!NT_STATUS_IS_OK(result)) {
8117 DEBUG(2, ("Got invalid trans2 request: %s\n",
8118 nt_errstr(result)));
8119 reply_nterror(req, result);
8120 END_PROFILE(SMBtrans2);
8121 return;
8124 if (IS_IPC(conn)) {
8125 switch (tran_call) {
8126 /* List the allowed trans2 calls on IPC$ */
8127 case TRANSACT2_OPEN:
8128 case TRANSACT2_GET_DFS_REFERRAL:
8129 case TRANSACT2_QFILEINFO:
8130 case TRANSACT2_QFSINFO:
8131 case TRANSACT2_SETFSINFO:
8132 break;
8133 default:
8134 reply_doserror(req, ERRSRV, ERRaccess);
8135 END_PROFILE(SMBtrans2);
8136 return;
8140 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8141 DEBUG(0, ("talloc failed\n"));
8142 reply_nterror(req, NT_STATUS_NO_MEMORY);
8143 END_PROFILE(SMBtrans2);
8144 return;
8147 state->cmd = SMBtrans2;
8149 state->mid = req->mid;
8150 state->vuid = req->vuid;
8151 state->setup_count = SVAL(req->vwv+13, 0);
8152 state->setup = NULL;
8153 state->total_param = SVAL(req->vwv+0, 0);
8154 state->param = NULL;
8155 state->total_data = SVAL(req->vwv+1, 0);
8156 state->data = NULL;
8157 state->max_param_return = SVAL(req->vwv+2, 0);
8158 state->max_data_return = SVAL(req->vwv+3, 0);
8159 state->max_setup_return = SVAL(req->vwv+4, 0);
8160 state->close_on_completion = BITSETW(req->vwv+5, 0);
8161 state->one_way = BITSETW(req->vwv+5, 1);
8163 state->call = tran_call;
8165 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8166 is so as a sanity check */
8167 if (state->setup_count != 1) {
8169 * Need to have rc=0 for ioctl to get job id for OS/2.
8170 * Network printing will fail if function is not successful.
8171 * Similar function in reply.c will be used if protocol
8172 * is LANMAN1.0 instead of LM1.2X002.
8173 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8174 * outbuf doesn't have to be set(only job id is used).
8176 if ( (state->setup_count == 4)
8177 && (tran_call == TRANSACT2_IOCTL)
8178 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8179 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8180 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8181 } else {
8182 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8183 DEBUG(2,("Transaction is %d\n",tran_call));
8184 TALLOC_FREE(state);
8185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8186 END_PROFILE(SMBtrans2);
8187 return;
8191 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8192 goto bad_param;
8194 if (state->total_data) {
8196 if (trans_oob(state->total_data, 0, dscnt)
8197 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8198 goto bad_param;
8201 /* Can't use talloc here, the core routines do realloc on the
8202 * params and data. */
8203 state->data = (char *)SMB_MALLOC(state->total_data);
8204 if (state->data == NULL) {
8205 DEBUG(0,("reply_trans2: data malloc fail for %u "
8206 "bytes !\n", (unsigned int)state->total_data));
8207 TALLOC_FREE(state);
8208 reply_nterror(req, NT_STATUS_NO_MEMORY);
8209 END_PROFILE(SMBtrans2);
8210 return;
8213 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8216 if (state->total_param) {
8218 if (trans_oob(state->total_param, 0, pscnt)
8219 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8220 goto bad_param;
8223 /* Can't use talloc here, the core routines do realloc on the
8224 * params and data. */
8225 state->param = (char *)SMB_MALLOC(state->total_param);
8226 if (state->param == NULL) {
8227 DEBUG(0,("reply_trans: param malloc fail for %u "
8228 "bytes !\n", (unsigned int)state->total_param));
8229 SAFE_FREE(state->data);
8230 TALLOC_FREE(state);
8231 reply_nterror(req, NT_STATUS_NO_MEMORY);
8232 END_PROFILE(SMBtrans2);
8233 return;
8236 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8239 state->received_data = dscnt;
8240 state->received_param = pscnt;
8242 if ((state->received_param == state->total_param) &&
8243 (state->received_data == state->total_data)) {
8245 handle_trans2(conn, req, state);
8247 SAFE_FREE(state->data);
8248 SAFE_FREE(state->param);
8249 TALLOC_FREE(state);
8250 END_PROFILE(SMBtrans2);
8251 return;
8254 DLIST_ADD(conn->pending_trans, state);
8256 /* We need to send an interim response then receive the rest
8257 of the parameter/data bytes */
8258 reply_outbuf(req, 0, 0);
8259 show_msg((char *)req->outbuf);
8260 END_PROFILE(SMBtrans2);
8261 return;
8263 bad_param:
8265 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8266 SAFE_FREE(state->data);
8267 SAFE_FREE(state->param);
8268 TALLOC_FREE(state);
8269 END_PROFILE(SMBtrans2);
8270 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8274 /****************************************************************************
8275 Reply to a SMBtranss2
8276 ****************************************************************************/
8278 void reply_transs2(struct smb_request *req)
8280 connection_struct *conn = req->conn;
8281 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8282 struct trans_state *state;
8284 START_PROFILE(SMBtranss2);
8286 show_msg((char *)req->inbuf);
8288 if (req->wct < 8) {
8289 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8290 END_PROFILE(SMBtranss2);
8291 return;
8294 for (state = conn->pending_trans; state != NULL;
8295 state = state->next) {
8296 if (state->mid == req->mid) {
8297 break;
8301 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8302 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8303 END_PROFILE(SMBtranss2);
8304 return;
8307 /* Revise state->total_param and state->total_data in case they have
8308 changed downwards */
8310 if (SVAL(req->vwv+0, 0) < state->total_param)
8311 state->total_param = SVAL(req->vwv+0, 0);
8312 if (SVAL(req->vwv+1, 0) < state->total_data)
8313 state->total_data = SVAL(req->vwv+1, 0);
8315 pcnt = SVAL(req->vwv+2, 0);
8316 poff = SVAL(req->vwv+3, 0);
8317 pdisp = SVAL(req->vwv+4, 0);
8319 dcnt = SVAL(req->vwv+5, 0);
8320 doff = SVAL(req->vwv+6, 0);
8321 ddisp = SVAL(req->vwv+7, 0);
8323 state->received_param += pcnt;
8324 state->received_data += dcnt;
8326 if ((state->received_data > state->total_data) ||
8327 (state->received_param > state->total_param))
8328 goto bad_param;
8330 if (pcnt) {
8331 if (trans_oob(state->total_param, pdisp, pcnt)
8332 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8333 goto bad_param;
8335 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8338 if (dcnt) {
8339 if (trans_oob(state->total_data, ddisp, dcnt)
8340 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8341 goto bad_param;
8343 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8346 if ((state->received_param < state->total_param) ||
8347 (state->received_data < state->total_data)) {
8348 END_PROFILE(SMBtranss2);
8349 return;
8352 handle_trans2(conn, req, state);
8354 DLIST_REMOVE(conn->pending_trans, state);
8355 SAFE_FREE(state->data);
8356 SAFE_FREE(state->param);
8357 TALLOC_FREE(state);
8359 END_PROFILE(SMBtranss2);
8360 return;
8362 bad_param:
8364 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8365 DLIST_REMOVE(conn->pending_trans, state);
8366 SAFE_FREE(state->data);
8367 SAFE_FREE(state->param);
8368 TALLOC_FREE(state);
8369 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8370 END_PROFILE(SMBtranss2);
8371 return;