Refactor the use of create_time and change time to go
[Samba.git] / source3 / smbd / trans2.c
blob93b217558dc13cceb3e1d505b5a2e36bb3f2483a
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, cdate_ts, create_date_ts;
1472 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1473 time_t c_date = (time_t)0;
1474 char *nameptr;
1475 char *last_entry_ptr;
1476 bool was_8_3;
1477 uint32_t nt_extmode; /* Used for NT connections instead of mode */
1479 *out_of_space = false;
1481 ZERO_STRUCT(mdate_ts);
1482 ZERO_STRUCT(adate_ts);
1483 ZERO_STRUCT(create_date_ts);
1484 ZERO_STRUCT(cdate_ts);
1486 if (!(mode & aDIR)) {
1487 file_size = get_file_size_stat(&smb_fname->st);
1489 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1491 mdate_ts = smb_fname->st.st_ex_mtime;
1492 adate_ts = smb_fname->st.st_ex_atime;
1493 create_date_ts = get_create_timespec(NULL, smb_fname);
1494 cdate_ts = get_change_timespec(NULL, smb_fname);
1496 if (lp_dos_filetime_resolution(SNUM(conn))) {
1497 dos_filetime_timespec(&create_date_ts);
1498 dos_filetime_timespec(&mdate_ts);
1499 dos_filetime_timespec(&adate_ts);
1500 dos_filetime_timespec(&cdate_ts);
1503 create_date = convert_timespec_to_time_t(create_date_ts);
1504 mdate = convert_timespec_to_time_t(mdate_ts);
1505 adate = convert_timespec_to_time_t(adate_ts);
1506 c_date = convert_timespec_to_time_t(cdate_ts);
1508 p = pdata;
1509 last_entry_ptr = p;
1511 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1513 switch (info_level) {
1514 case SMB_FIND_INFO_STANDARD:
1515 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1516 if(requires_resume_key) {
1517 SIVAL(p,0,reskey);
1518 p += 4;
1520 srv_put_dos_date2(p,0,create_date);
1521 srv_put_dos_date2(p,4,adate);
1522 srv_put_dos_date2(p,8,mdate);
1523 SIVAL(p,12,(uint32)file_size);
1524 SIVAL(p,16,(uint32)allocation_size);
1525 SSVAL(p,20,mode);
1526 p += 23;
1527 nameptr = p;
1528 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1529 p += ucs2_align(base_data, p, 0);
1531 len = srvstr_push(base_data, flags2, p,
1532 fname, PTR_DIFF(end_data, p),
1533 STR_TERMINATE);
1534 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1535 if (len > 2) {
1536 SCVAL(nameptr, -1, len - 2);
1537 } else {
1538 SCVAL(nameptr, -1, 0);
1540 } else {
1541 if (len > 1) {
1542 SCVAL(nameptr, -1, len - 1);
1543 } else {
1544 SCVAL(nameptr, -1, 0);
1547 p += len;
1548 break;
1550 case SMB_FIND_EA_SIZE:
1551 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1552 if (requires_resume_key) {
1553 SIVAL(p,0,reskey);
1554 p += 4;
1556 srv_put_dos_date2(p,0,create_date);
1557 srv_put_dos_date2(p,4,adate);
1558 srv_put_dos_date2(p,8,mdate);
1559 SIVAL(p,12,(uint32)file_size);
1560 SIVAL(p,16,(uint32)allocation_size);
1561 SSVAL(p,20,mode);
1563 unsigned int ea_size = estimate_ea_size(conn, NULL,
1564 smb_fname->base_name);
1565 SIVAL(p,22,ea_size); /* Extended attributes */
1567 p += 27;
1568 nameptr = p - 1;
1569 len = srvstr_push(base_data, flags2,
1570 p, fname, PTR_DIFF(end_data, p),
1571 STR_TERMINATE | STR_NOALIGN);
1572 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1573 if (len > 2) {
1574 len -= 2;
1575 } else {
1576 len = 0;
1578 } else {
1579 if (len > 1) {
1580 len -= 1;
1581 } else {
1582 len = 0;
1585 SCVAL(nameptr,0,len);
1586 p += len;
1587 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1588 break;
1590 case SMB_FIND_EA_LIST:
1592 struct ea_list *file_list = NULL;
1593 size_t ea_len = 0;
1595 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1596 if (!name_list) {
1597 return false;
1599 if (requires_resume_key) {
1600 SIVAL(p,0,reskey);
1601 p += 4;
1603 srv_put_dos_date2(p,0,create_date);
1604 srv_put_dos_date2(p,4,adate);
1605 srv_put_dos_date2(p,8,mdate);
1606 SIVAL(p,12,(uint32)file_size);
1607 SIVAL(p,16,(uint32)allocation_size);
1608 SSVAL(p,20,mode);
1609 p += 22; /* p now points to the EA area. */
1611 file_list = get_ea_list_from_file(ctx, conn, NULL,
1612 smb_fname->base_name,
1613 &ea_len);
1614 name_list = ea_list_union(name_list, file_list, &ea_len);
1616 /* We need to determine if this entry will fit in the space available. */
1617 /* Max string size is 255 bytes. */
1618 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1619 *out_of_space = true;
1620 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1621 return False; /* Not finished - just out of space */
1624 /* Push the ea_data followed by the name. */
1625 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1626 nameptr = p;
1627 len = srvstr_push(base_data, flags2,
1628 p + 1, fname, PTR_DIFF(end_data, p+1),
1629 STR_TERMINATE | STR_NOALIGN);
1630 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1631 if (len > 2) {
1632 len -= 2;
1633 } else {
1634 len = 0;
1636 } else {
1637 if (len > 1) {
1638 len -= 1;
1639 } else {
1640 len = 0;
1643 SCVAL(nameptr,0,len);
1644 p += len + 1;
1645 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1646 break;
1649 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1650 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1651 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1652 p += 4;
1653 SIVAL(p,0,reskey); p += 4;
1654 put_long_date_timespec(p,create_date_ts); p += 8;
1655 put_long_date_timespec(p,adate_ts); p += 8;
1656 put_long_date_timespec(p,mdate_ts); p += 8;
1657 put_long_date_timespec(p,cdate_ts); p += 8;
1658 SOFF_T(p,0,file_size); p += 8;
1659 SOFF_T(p,0,allocation_size); p += 8;
1660 SIVAL(p,0,nt_extmode); p += 4;
1661 q = p; p += 4; /* q is placeholder for name length. */
1663 unsigned int ea_size = estimate_ea_size(conn, NULL,
1664 smb_fname->base_name);
1665 SIVAL(p,0,ea_size); /* Extended attributes */
1666 p += 4;
1668 /* Clear the short name buffer. This is
1669 * IMPORTANT as not doing so will trigger
1670 * a Win2k client bug. JRA.
1672 if (!was_8_3 && check_mangled_names) {
1673 char mangled_name[13]; /* mangled 8.3 name. */
1674 if (!name_to_8_3(fname,mangled_name,True,
1675 conn->params)) {
1676 /* Error - mangle failed ! */
1677 memset(mangled_name,'\0',12);
1679 mangled_name[12] = 0;
1680 len = srvstr_push(base_data, flags2,
1681 p+2, mangled_name, 24,
1682 STR_UPPER|STR_UNICODE);
1683 if (len < 24) {
1684 memset(p + 2 + len,'\0',24 - len);
1686 SSVAL(p, 0, len);
1687 } else {
1688 memset(p,'\0',26);
1690 p += 2 + 24;
1691 len = srvstr_push(base_data, flags2, p,
1692 fname, PTR_DIFF(end_data, p),
1693 STR_TERMINATE_ASCII);
1694 SIVAL(q,0,len);
1695 p += len;
1696 SIVAL(p,0,0); /* Ensure any padding is null. */
1697 len = PTR_DIFF(p, pdata);
1698 len = (len + 3) & ~3;
1699 SIVAL(pdata,0,len);
1700 p = pdata + len;
1701 break;
1703 case SMB_FIND_FILE_DIRECTORY_INFO:
1704 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1705 p += 4;
1706 SIVAL(p,0,reskey); p += 4;
1707 put_long_date_timespec(p,create_date_ts); p += 8;
1708 put_long_date_timespec(p,adate_ts); p += 8;
1709 put_long_date_timespec(p,mdate_ts); p += 8;
1710 put_long_date_timespec(p,cdate_ts); p += 8;
1711 SOFF_T(p,0,file_size); p += 8;
1712 SOFF_T(p,0,allocation_size); p += 8;
1713 SIVAL(p,0,nt_extmode); p += 4;
1714 len = srvstr_push(base_data, flags2,
1715 p + 4, fname, PTR_DIFF(end_data, p+4),
1716 STR_TERMINATE_ASCII);
1717 SIVAL(p,0,len);
1718 p += 4 + len;
1719 SIVAL(p,0,0); /* Ensure any padding is null. */
1720 len = PTR_DIFF(p, pdata);
1721 len = (len + 3) & ~3;
1722 SIVAL(pdata,0,len);
1723 p = pdata + len;
1724 break;
1726 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1727 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1728 p += 4;
1729 SIVAL(p,0,reskey); p += 4;
1730 put_long_date_timespec(p,create_date_ts); p += 8;
1731 put_long_date_timespec(p,adate_ts); p += 8;
1732 put_long_date_timespec(p,mdate_ts); p += 8;
1733 put_long_date_timespec(p,cdate_ts); p += 8;
1734 SOFF_T(p,0,file_size); p += 8;
1735 SOFF_T(p,0,allocation_size); p += 8;
1736 SIVAL(p,0,nt_extmode); p += 4;
1737 q = p; p += 4; /* q is placeholder for name length. */
1739 unsigned int ea_size = estimate_ea_size(conn, NULL,
1740 smb_fname->base_name);
1741 SIVAL(p,0,ea_size); /* Extended attributes */
1742 p +=4;
1744 len = srvstr_push(base_data, flags2, p,
1745 fname, PTR_DIFF(end_data, p),
1746 STR_TERMINATE_ASCII);
1747 SIVAL(q, 0, len);
1748 p += len;
1750 SIVAL(p,0,0); /* Ensure any padding is null. */
1751 len = PTR_DIFF(p, pdata);
1752 len = (len + 3) & ~3;
1753 SIVAL(pdata,0,len);
1754 p = pdata + len;
1755 break;
1757 case SMB_FIND_FILE_NAMES_INFO:
1758 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1759 p += 4;
1760 SIVAL(p,0,reskey); p += 4;
1761 p += 4;
1762 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1763 acl on a dir (tridge) */
1764 len = srvstr_push(base_data, flags2, p,
1765 fname, PTR_DIFF(end_data, p),
1766 STR_TERMINATE_ASCII);
1767 SIVAL(p, -4, len);
1768 p += len;
1769 SIVAL(p,0,0); /* Ensure any padding is null. */
1770 len = PTR_DIFF(p, pdata);
1771 len = (len + 3) & ~3;
1772 SIVAL(pdata,0,len);
1773 p = pdata + len;
1774 break;
1776 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1777 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1778 p += 4;
1779 SIVAL(p,0,reskey); p += 4;
1780 put_long_date_timespec(p,create_date_ts); p += 8;
1781 put_long_date_timespec(p,adate_ts); p += 8;
1782 put_long_date_timespec(p,mdate_ts); p += 8;
1783 put_long_date_timespec(p,cdate_ts); p += 8;
1784 SOFF_T(p,0,file_size); p += 8;
1785 SOFF_T(p,0,allocation_size); p += 8;
1786 SIVAL(p,0,nt_extmode); p += 4;
1787 q = p; p += 4; /* q is placeholder for name length. */
1789 unsigned int ea_size = estimate_ea_size(conn, NULL,
1790 smb_fname->base_name);
1791 SIVAL(p,0,ea_size); /* Extended attributes */
1792 p +=4;
1794 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1795 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1796 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1797 len = srvstr_push(base_data, flags2, p,
1798 fname, PTR_DIFF(end_data, p),
1799 STR_TERMINATE_ASCII);
1800 SIVAL(q, 0, len);
1801 p += len;
1802 SIVAL(p,0,0); /* Ensure any padding is null. */
1803 len = PTR_DIFF(p, pdata);
1804 len = (len + 3) & ~3;
1805 SIVAL(pdata,0,len);
1806 p = pdata + len;
1807 break;
1809 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1810 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1811 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1812 p += 4;
1813 SIVAL(p,0,reskey); p += 4;
1814 put_long_date_timespec(p,create_date_ts); p += 8;
1815 put_long_date_timespec(p,adate_ts); p += 8;
1816 put_long_date_timespec(p,mdate_ts); p += 8;
1817 put_long_date_timespec(p,cdate_ts); p += 8;
1818 SOFF_T(p,0,file_size); p += 8;
1819 SOFF_T(p,0,allocation_size); p += 8;
1820 SIVAL(p,0,nt_extmode); p += 4;
1821 q = p; p += 4; /* q is placeholder for name length */
1823 unsigned int ea_size = estimate_ea_size(conn, NULL,
1824 smb_fname->base_name);
1825 SIVAL(p,0,ea_size); /* Extended attributes */
1826 p +=4;
1828 /* Clear the short name buffer. This is
1829 * IMPORTANT as not doing so will trigger
1830 * a Win2k client bug. JRA.
1832 if (!was_8_3 && check_mangled_names) {
1833 char mangled_name[13]; /* mangled 8.3 name. */
1834 if (!name_to_8_3(fname,mangled_name,True,
1835 conn->params)) {
1836 /* Error - mangle failed ! */
1837 memset(mangled_name,'\0',12);
1839 mangled_name[12] = 0;
1840 len = srvstr_push(base_data, flags2,
1841 p+2, mangled_name, 24,
1842 STR_UPPER|STR_UNICODE);
1843 SSVAL(p, 0, len);
1844 if (len < 24) {
1845 memset(p + 2 + len,'\0',24 - len);
1847 SSVAL(p, 0, len);
1848 } else {
1849 memset(p,'\0',26);
1851 p += 26;
1852 SSVAL(p,0,0); p += 2; /* Reserved ? */
1853 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1854 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1855 len = srvstr_push(base_data, flags2, p,
1856 fname, PTR_DIFF(end_data, p),
1857 STR_TERMINATE_ASCII);
1858 SIVAL(q,0,len);
1859 p += len;
1860 SIVAL(p,0,0); /* Ensure any padding is null. */
1861 len = PTR_DIFF(p, pdata);
1862 len = (len + 3) & ~3;
1863 SIVAL(pdata,0,len);
1864 p = pdata + len;
1865 break;
1867 /* CIFS UNIX Extension. */
1869 case SMB_FIND_FILE_UNIX:
1870 case SMB_FIND_FILE_UNIX_INFO2:
1871 p+= 4;
1872 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1874 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1876 if (info_level == SMB_FIND_FILE_UNIX) {
1877 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1878 p = store_file_unix_basic(conn, p,
1879 NULL, &smb_fname->st);
1880 len = srvstr_push(base_data, flags2, p,
1881 fname, PTR_DIFF(end_data, p),
1882 STR_TERMINATE);
1883 } else {
1884 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1885 p = store_file_unix_basic_info2(conn, p,
1886 NULL, &smb_fname->st);
1887 nameptr = p;
1888 p += 4;
1889 len = srvstr_push(base_data, flags2, p, fname,
1890 PTR_DIFF(end_data, p), 0);
1891 SIVAL(nameptr, 0, len);
1894 p += len;
1895 SIVAL(p,0,0); /* Ensure any padding is null. */
1897 len = PTR_DIFF(p, pdata);
1898 len = (len + 3) & ~3;
1899 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1900 p = pdata + len;
1901 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1903 break;
1905 default:
1906 return false;
1909 if (PTR_DIFF(p,pdata) > space_remaining) {
1910 *out_of_space = true;
1911 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1912 return false; /* Not finished - just out of space */
1915 /* Setup the last entry pointer, as an offset from base_data */
1916 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1917 /* Advance the data pointer to the next slot */
1918 *ppdata = p;
1920 return true;
1923 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1924 connection_struct *conn,
1925 struct dptr_struct *dirptr,
1926 uint16 flags2,
1927 const char *path_mask,
1928 uint32 dirtype,
1929 int info_level,
1930 int requires_resume_key,
1931 bool dont_descend,
1932 bool ask_sharemode,
1933 char **ppdata,
1934 char *base_data,
1935 char *end_data,
1936 int space_remaining,
1937 bool *out_of_space,
1938 bool *got_exact_match,
1939 int *_last_entry_off,
1940 struct ea_list *name_list)
1942 const char *p;
1943 const char *mask = NULL;
1944 long prev_dirpos = 0;
1945 uint32_t mode = 0;
1946 char *fname = NULL;
1947 struct smb_filename *smb_fname = NULL;
1948 struct smbd_dirptr_lanman2_state state;
1949 bool ok;
1950 uint64_t last_entry_off = 0;
1952 ZERO_STRUCT(state);
1953 state.conn = conn;
1954 state.info_level = info_level;
1955 state.check_mangled_names = lp_manglednames(conn->params);
1956 state.has_wild = dptr_has_wild(dirptr);
1957 state.got_exact_match = false;
1959 *out_of_space = false;
1960 *got_exact_match = false;
1962 p = strrchr_m(path_mask,'/');
1963 if(p != NULL) {
1964 if(p[1] == '\0') {
1965 mask = "*.*";
1966 } else {
1967 mask = p+1;
1969 } else {
1970 mask = path_mask;
1973 ok = smbd_dirptr_get_entry(ctx,
1974 dirptr,
1975 mask,
1976 dirtype,
1977 dont_descend,
1978 ask_sharemode,
1979 smbd_dirptr_lanman2_match_fn,
1980 smbd_dirptr_lanman2_mode_fn,
1981 &state,
1982 &fname,
1983 &smb_fname,
1984 &mode,
1985 &prev_dirpos);
1986 if (!ok) {
1987 return false;
1990 *got_exact_match = state.got_exact_match;
1992 ok = smbd_marshall_dir_entry(ctx,
1993 conn,
1994 flags2,
1995 info_level,
1996 name_list,
1997 state.check_mangled_names,
1998 requires_resume_key,
1999 mode,
2000 fname,
2001 smb_fname,
2002 space_remaining,
2003 base_data,
2004 ppdata,
2005 end_data,
2006 out_of_space,
2007 &last_entry_off);
2008 TALLOC_FREE(fname);
2009 TALLOC_FREE(smb_fname);
2010 if (*out_of_space) {
2011 dptr_SeekDir(dirptr, prev_dirpos);
2012 return false;
2014 if (!ok) {
2015 return false;
2018 *_last_entry_off = last_entry_off;
2019 return true;
2022 /****************************************************************************
2023 Reply to a TRANS2_FINDFIRST.
2024 ****************************************************************************/
2026 static void call_trans2findfirst(connection_struct *conn,
2027 struct smb_request *req,
2028 char **pparams, int total_params,
2029 char **ppdata, int total_data,
2030 unsigned int max_data_bytes)
2032 /* We must be careful here that we don't return more than the
2033 allowed number of data bytes. If this means returning fewer than
2034 maxentries then so be it. We assume that the redirector has
2035 enough room for the fixed number of parameter bytes it has
2036 requested. */
2037 struct smb_filename *smb_dname = NULL;
2038 char *params = *pparams;
2039 char *pdata = *ppdata;
2040 char *data_end;
2041 uint32 dirtype;
2042 int maxentries;
2043 uint16 findfirst_flags;
2044 bool close_after_first;
2045 bool close_if_end;
2046 bool requires_resume_key;
2047 int info_level;
2048 char *directory = NULL;
2049 char *mask = NULL;
2050 char *p;
2051 int last_entry_off=0;
2052 int dptr_num = -1;
2053 int numentries = 0;
2054 int i;
2055 bool finished = False;
2056 bool dont_descend = False;
2057 bool out_of_space = False;
2058 int space_remaining;
2059 bool mask_contains_wcard = False;
2060 struct ea_list *ea_list = NULL;
2061 NTSTATUS ntstatus = NT_STATUS_OK;
2062 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2063 TALLOC_CTX *ctx = talloc_tos();
2064 struct dptr_struct *dirptr = NULL;
2065 struct smbd_server_connection *sconn = smbd_server_conn;
2067 if (total_params < 13) {
2068 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2069 goto out;
2072 dirtype = SVAL(params,0);
2073 maxentries = SVAL(params,2);
2074 findfirst_flags = SVAL(params,4);
2075 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2076 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2077 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2078 info_level = SVAL(params,6);
2080 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2081 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2082 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2083 info_level, max_data_bytes));
2085 if (!maxentries) {
2086 /* W2K3 seems to treat zero as 1. */
2087 maxentries = 1;
2090 switch (info_level) {
2091 case SMB_FIND_INFO_STANDARD:
2092 case SMB_FIND_EA_SIZE:
2093 case SMB_FIND_EA_LIST:
2094 case SMB_FIND_FILE_DIRECTORY_INFO:
2095 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2096 case SMB_FIND_FILE_NAMES_INFO:
2097 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2098 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2099 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2100 break;
2101 case SMB_FIND_FILE_UNIX:
2102 case SMB_FIND_FILE_UNIX_INFO2:
2103 /* Always use filesystem for UNIX mtime query. */
2104 ask_sharemode = false;
2105 if (!lp_unix_extensions()) {
2106 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2107 goto out;
2109 break;
2110 default:
2111 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2112 goto out;
2115 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2116 params+12, total_params - 12,
2117 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2118 if (!NT_STATUS_IS_OK(ntstatus)) {
2119 reply_nterror(req, ntstatus);
2120 goto out;
2123 ntstatus = filename_convert(ctx, conn,
2124 req->flags2 & FLAGS2_DFS_PATHNAMES,
2125 directory,
2126 (UCF_SAVE_LCOMP |
2127 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2128 &mask_contains_wcard,
2129 &smb_dname);
2130 if (!NT_STATUS_IS_OK(ntstatus)) {
2131 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2132 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2133 ERRSRV, ERRbadpath);
2134 goto out;
2136 reply_nterror(req, ntstatus);
2137 goto out;
2140 mask = smb_dname->original_lcomp;
2142 directory = smb_dname->base_name;
2144 p = strrchr_m(directory,'/');
2145 if(p == NULL) {
2146 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2147 if((directory[0] == '.') && (directory[1] == '\0')) {
2148 mask = talloc_strdup(ctx,"*");
2149 if (!mask) {
2150 reply_nterror(req, NT_STATUS_NO_MEMORY);
2151 goto out;
2153 mask_contains_wcard = True;
2155 directory = talloc_strdup(talloc_tos(), "./");
2156 if (!directory) {
2157 reply_nterror(req, NT_STATUS_NO_MEMORY);
2158 goto out;
2160 } else {
2161 *p = 0;
2164 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2166 if (info_level == SMB_FIND_EA_LIST) {
2167 uint32 ea_size;
2169 if (total_data < 4) {
2170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2171 goto out;
2174 ea_size = IVAL(pdata,0);
2175 if (ea_size != total_data) {
2176 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2177 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2179 goto out;
2182 if (!lp_ea_support(SNUM(conn))) {
2183 reply_doserror(req, ERRDOS, ERReasnotsupported);
2184 goto out;
2187 /* Pull out the list of names. */
2188 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2189 if (!ea_list) {
2190 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2191 goto out;
2195 *ppdata = (char *)SMB_REALLOC(
2196 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2197 if(*ppdata == NULL ) {
2198 reply_nterror(req, NT_STATUS_NO_MEMORY);
2199 goto out;
2201 pdata = *ppdata;
2202 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2204 /* Realloc the params space */
2205 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2206 if (*pparams == NULL) {
2207 reply_nterror(req, NT_STATUS_NO_MEMORY);
2208 goto out;
2210 params = *pparams;
2212 /* Save the wildcard match and attribs we are using on this directory -
2213 needed as lanman2 assumes these are being saved between calls */
2215 ntstatus = dptr_create(conn,
2216 directory,
2217 False,
2218 True,
2219 req->smbpid,
2220 mask,
2221 mask_contains_wcard,
2222 dirtype,
2223 &dirptr);
2225 if (!NT_STATUS_IS_OK(ntstatus)) {
2226 reply_nterror(req, ntstatus);
2227 goto out;
2230 dptr_num = dptr_dnum(dirptr);
2231 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2233 /* Initialize per TRANS2_FIND_FIRST operation data */
2234 dptr_init_search_op(dirptr);
2236 /* We don't need to check for VOL here as this is returned by
2237 a different TRANS2 call. */
2239 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2240 directory,lp_dontdescend(SNUM(conn))));
2241 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2242 dont_descend = True;
2244 p = pdata;
2245 space_remaining = max_data_bytes;
2246 out_of_space = False;
2248 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2249 bool got_exact_match = False;
2251 /* this is a heuristic to avoid seeking the dirptr except when
2252 absolutely necessary. It allows for a filename of about 40 chars */
2253 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2254 out_of_space = True;
2255 finished = False;
2256 } else {
2257 finished = !get_lanman2_dir_entry(ctx,
2258 conn,
2259 dirptr,
2260 req->flags2,
2261 mask,dirtype,info_level,
2262 requires_resume_key,dont_descend,
2263 ask_sharemode,
2264 &p,pdata,data_end,
2265 space_remaining, &out_of_space,
2266 &got_exact_match,
2267 &last_entry_off, ea_list);
2270 if (finished && out_of_space)
2271 finished = False;
2273 if (!finished && !out_of_space)
2274 numentries++;
2277 * As an optimisation if we know we aren't looking
2278 * for a wildcard name (ie. the name matches the wildcard exactly)
2279 * then we can finish on any (first) match.
2280 * This speeds up large directory searches. JRA.
2283 if(got_exact_match)
2284 finished = True;
2286 /* Ensure space_remaining never goes -ve. */
2287 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2288 space_remaining = 0;
2289 out_of_space = true;
2290 } else {
2291 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2295 /* Check if we can close the dirptr */
2296 if(close_after_first || (finished && close_if_end)) {
2297 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2298 dptr_close(sconn, &dptr_num);
2302 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2303 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2304 * the protocol level is less than NT1. Tested with smbclient. JRA.
2305 * This should fix the OS/2 client bug #2335.
2308 if(numentries == 0) {
2309 dptr_close(sconn, &dptr_num);
2310 if (Protocol < PROTOCOL_NT1) {
2311 reply_doserror(req, ERRDOS, ERRnofiles);
2312 goto out;
2313 } else {
2314 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2315 ERRDOS, ERRbadfile);
2316 goto out;
2320 /* At this point pdata points to numentries directory entries. */
2322 /* Set up the return parameter block */
2323 SSVAL(params,0,dptr_num);
2324 SSVAL(params,2,numentries);
2325 SSVAL(params,4,finished);
2326 SSVAL(params,6,0); /* Never an EA error */
2327 SSVAL(params,8,last_entry_off);
2329 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2330 max_data_bytes);
2332 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2333 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2334 if (!directory) {
2335 reply_nterror(req, NT_STATUS_NO_MEMORY);
2339 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2340 smb_fn_name(req->cmd),
2341 mask, directory, dirtype, numentries ) );
2344 * Force a name mangle here to ensure that the
2345 * mask as an 8.3 name is top of the mangled cache.
2346 * The reasons for this are subtle. Don't remove
2347 * this code unless you know what you are doing
2348 * (see PR#13758). JRA.
2351 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2352 char mangled_name[13];
2353 name_to_8_3(mask, mangled_name, True, conn->params);
2355 out:
2356 TALLOC_FREE(smb_dname);
2357 return;
2360 /****************************************************************************
2361 Reply to a TRANS2_FINDNEXT.
2362 ****************************************************************************/
2364 static void call_trans2findnext(connection_struct *conn,
2365 struct smb_request *req,
2366 char **pparams, int total_params,
2367 char **ppdata, int total_data,
2368 unsigned int max_data_bytes)
2370 /* We must be careful here that we don't return more than the
2371 allowed number of data bytes. If this means returning fewer than
2372 maxentries then so be it. We assume that the redirector has
2373 enough room for the fixed number of parameter bytes it has
2374 requested. */
2375 char *params = *pparams;
2376 char *pdata = *ppdata;
2377 char *data_end;
2378 int dptr_num;
2379 int maxentries;
2380 uint16 info_level;
2381 uint32 resume_key;
2382 uint16 findnext_flags;
2383 bool close_after_request;
2384 bool close_if_end;
2385 bool requires_resume_key;
2386 bool continue_bit;
2387 bool mask_contains_wcard = False;
2388 char *resume_name = NULL;
2389 const char *mask = NULL;
2390 const char *directory = NULL;
2391 char *p = NULL;
2392 uint16 dirtype;
2393 int numentries = 0;
2394 int i, last_entry_off=0;
2395 bool finished = False;
2396 bool dont_descend = False;
2397 bool out_of_space = False;
2398 int space_remaining;
2399 struct ea_list *ea_list = NULL;
2400 NTSTATUS ntstatus = NT_STATUS_OK;
2401 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2402 TALLOC_CTX *ctx = talloc_tos();
2403 struct dptr_struct *dirptr;
2404 struct smbd_server_connection *sconn = smbd_server_conn;
2406 if (total_params < 13) {
2407 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2408 return;
2411 dptr_num = SVAL(params,0);
2412 maxentries = SVAL(params,2);
2413 info_level = SVAL(params,4);
2414 resume_key = IVAL(params,6);
2415 findnext_flags = SVAL(params,10);
2416 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2417 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2418 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2419 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2421 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2422 params+12,
2423 total_params - 12, STR_TERMINATE, &ntstatus,
2424 &mask_contains_wcard);
2425 if (!NT_STATUS_IS_OK(ntstatus)) {
2426 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2427 complain (it thinks we're asking for the directory above the shared
2428 path or an invalid name). Catch this as the resume name is only compared, never used in
2429 a file access. JRA. */
2430 srvstr_pull_talloc(ctx, params, req->flags2,
2431 &resume_name, params+12,
2432 total_params - 12,
2433 STR_TERMINATE);
2435 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2436 reply_nterror(req, ntstatus);
2437 return;
2441 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2442 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2443 resume_key = %d resume name = %s continue=%d level = %d\n",
2444 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2445 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2447 if (!maxentries) {
2448 /* W2K3 seems to treat zero as 1. */
2449 maxentries = 1;
2452 switch (info_level) {
2453 case SMB_FIND_INFO_STANDARD:
2454 case SMB_FIND_EA_SIZE:
2455 case SMB_FIND_EA_LIST:
2456 case SMB_FIND_FILE_DIRECTORY_INFO:
2457 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2458 case SMB_FIND_FILE_NAMES_INFO:
2459 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2460 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2461 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2462 break;
2463 case SMB_FIND_FILE_UNIX:
2464 case SMB_FIND_FILE_UNIX_INFO2:
2465 /* Always use filesystem for UNIX mtime query. */
2466 ask_sharemode = false;
2467 if (!lp_unix_extensions()) {
2468 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2469 return;
2471 break;
2472 default:
2473 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2474 return;
2477 if (info_level == SMB_FIND_EA_LIST) {
2478 uint32 ea_size;
2480 if (total_data < 4) {
2481 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2482 return;
2485 ea_size = IVAL(pdata,0);
2486 if (ea_size != total_data) {
2487 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2488 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2489 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2490 return;
2493 if (!lp_ea_support(SNUM(conn))) {
2494 reply_doserror(req, ERRDOS, ERReasnotsupported);
2495 return;
2498 /* Pull out the list of names. */
2499 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2500 if (!ea_list) {
2501 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2502 return;
2506 *ppdata = (char *)SMB_REALLOC(
2507 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2508 if(*ppdata == NULL) {
2509 reply_nterror(req, NT_STATUS_NO_MEMORY);
2510 return;
2513 pdata = *ppdata;
2514 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2516 /* Realloc the params space */
2517 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2518 if(*pparams == NULL ) {
2519 reply_nterror(req, NT_STATUS_NO_MEMORY);
2520 return;
2523 params = *pparams;
2525 /* Check that the dptr is valid */
2526 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2527 reply_doserror(req, ERRDOS, ERRnofiles);
2528 return;
2531 directory = dptr_path(sconn, dptr_num);
2533 /* Get the wildcard mask from the dptr */
2534 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2535 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2536 reply_doserror(req, ERRDOS, ERRnofiles);
2537 return;
2540 mask = p;
2542 /* Get the attr mask from the dptr */
2543 dirtype = dptr_attr(sconn, dptr_num);
2545 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2546 dptr_num, mask, dirtype,
2547 (long)dirptr,
2548 dptr_TellDir(dirptr)));
2550 /* Initialize per TRANS2_FIND_NEXT operation data */
2551 dptr_init_search_op(dirptr);
2553 /* We don't need to check for VOL here as this is returned by
2554 a different TRANS2 call. */
2556 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2557 directory,lp_dontdescend(SNUM(conn))));
2558 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2559 dont_descend = True;
2561 p = pdata;
2562 space_remaining = max_data_bytes;
2563 out_of_space = False;
2566 * Seek to the correct position. We no longer use the resume key but
2567 * depend on the last file name instead.
2570 if(*resume_name && !continue_bit) {
2571 SMB_STRUCT_STAT st;
2573 long current_pos = 0;
2575 * Remember, name_to_8_3 is called by
2576 * get_lanman2_dir_entry(), so the resume name
2577 * could be mangled. Ensure we check the unmangled name.
2580 if (mangle_is_mangled(resume_name, conn->params)) {
2581 char *new_resume_name = NULL;
2582 mangle_lookup_name_from_8_3(ctx,
2583 resume_name,
2584 &new_resume_name,
2585 conn->params);
2586 if (new_resume_name) {
2587 resume_name = new_resume_name;
2592 * Fix for NT redirector problem triggered by resume key indexes
2593 * changing between directory scans. We now return a resume key of 0
2594 * and instead look for the filename to continue from (also given
2595 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2596 * findfirst/findnext (as is usual) then the directory pointer
2597 * should already be at the correct place.
2600 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
2601 } /* end if resume_name && !continue_bit */
2603 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2604 bool got_exact_match = False;
2606 /* this is a heuristic to avoid seeking the dirptr except when
2607 absolutely necessary. It allows for a filename of about 40 chars */
2608 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2609 out_of_space = True;
2610 finished = False;
2611 } else {
2612 finished = !get_lanman2_dir_entry(ctx,
2613 conn,
2614 dirptr,
2615 req->flags2,
2616 mask,dirtype,info_level,
2617 requires_resume_key,dont_descend,
2618 ask_sharemode,
2619 &p,pdata,data_end,
2620 space_remaining, &out_of_space,
2621 &got_exact_match,
2622 &last_entry_off, ea_list);
2625 if (finished && out_of_space)
2626 finished = False;
2628 if (!finished && !out_of_space)
2629 numentries++;
2632 * As an optimisation if we know we aren't looking
2633 * for a wildcard name (ie. the name matches the wildcard exactly)
2634 * then we can finish on any (first) match.
2635 * This speeds up large directory searches. JRA.
2638 if(got_exact_match)
2639 finished = True;
2641 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2644 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2645 smb_fn_name(req->cmd),
2646 mask, directory, dirtype, numentries ) );
2648 /* Check if we can close the dirptr */
2649 if(close_after_request || (finished && close_if_end)) {
2650 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2651 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2654 /* Set up the return parameter block */
2655 SSVAL(params,0,numentries);
2656 SSVAL(params,2,finished);
2657 SSVAL(params,4,0); /* Never an EA error */
2658 SSVAL(params,6,last_entry_off);
2660 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2661 max_data_bytes);
2663 return;
2666 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2668 E_md4hash(lp_servicename(SNUM(conn)),objid);
2669 return objid;
2672 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2674 SMB_ASSERT(extended_info != NULL);
2676 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2677 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2678 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2679 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2680 #ifdef SAMBA_VERSION_REVISION
2681 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2682 #endif
2683 extended_info->samba_subversion = 0;
2684 #ifdef SAMBA_VERSION_RC_RELEASE
2685 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2686 #else
2687 #ifdef SAMBA_VERSION_PRE_RELEASE
2688 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2689 #endif
2690 #endif
2691 #ifdef SAMBA_VERSION_VENDOR_PATCH
2692 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2693 #endif
2694 extended_info->samba_gitcommitdate = 0;
2695 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2696 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2697 #endif
2699 memset(extended_info->samba_version_string, 0,
2700 sizeof(extended_info->samba_version_string));
2702 snprintf (extended_info->samba_version_string,
2703 sizeof(extended_info->samba_version_string),
2704 "%s", samba_version_string());
2707 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2708 TALLOC_CTX *mem_ctx,
2709 uint16_t info_level,
2710 uint16_t flags2,
2711 unsigned int max_data_bytes,
2712 char **ppdata,
2713 int *ret_data_len)
2715 char *pdata, *end_data;
2716 int data_len = 0, len;
2717 const char *vname = volume_label(SNUM(conn));
2718 int snum = SNUM(conn);
2719 char *fstype = lp_fstype(SNUM(conn));
2720 uint32 additional_flags = 0;
2721 struct smb_filename *smb_fname_dot = NULL;
2722 SMB_STRUCT_STAT st;
2723 NTSTATUS status;
2725 if (IS_IPC(conn)) {
2726 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2727 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2728 "info level (0x%x) on IPC$.\n",
2729 (unsigned int)info_level));
2730 return NT_STATUS_ACCESS_DENIED;
2734 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2736 status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL,
2737 &smb_fname_dot);
2738 if (!NT_STATUS_IS_OK(status)) {
2739 return status;
2742 if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) {
2743 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2744 TALLOC_FREE(smb_fname_dot);
2745 return map_nt_error_from_unix(errno);
2748 st = smb_fname_dot->st;
2749 TALLOC_FREE(smb_fname_dot);
2751 *ppdata = (char *)SMB_REALLOC(
2752 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2753 if (*ppdata == NULL) {
2754 return NT_STATUS_NO_MEMORY;
2757 pdata = *ppdata;
2758 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2759 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2761 switch (info_level) {
2762 case SMB_INFO_ALLOCATION:
2764 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2765 data_len = 18;
2766 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2767 return map_nt_error_from_unix(errno);
2770 block_size = lp_block_size(snum);
2771 if (bsize < block_size) {
2772 uint64_t factor = block_size/bsize;
2773 bsize = block_size;
2774 dsize /= factor;
2775 dfree /= factor;
2777 if (bsize > block_size) {
2778 uint64_t factor = bsize/block_size;
2779 bsize = block_size;
2780 dsize *= factor;
2781 dfree *= factor;
2783 bytes_per_sector = 512;
2784 sectors_per_unit = bsize/bytes_per_sector;
2786 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2787 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2788 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2790 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2791 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2792 SIVAL(pdata,l1_cUnit,dsize);
2793 SIVAL(pdata,l1_cUnitAvail,dfree);
2794 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2795 break;
2798 case SMB_INFO_VOLUME:
2799 /* Return volume name */
2801 * Add volume serial number - hash of a combination of
2802 * the called hostname and the service name.
2804 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2806 * Win2k3 and previous mess this up by sending a name length
2807 * one byte short. I believe only older clients (OS/2 Win9x) use
2808 * this call so try fixing this by adding a terminating null to
2809 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2811 len = srvstr_push(
2812 pdata, flags2,
2813 pdata+l2_vol_szVolLabel, vname,
2814 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2815 STR_NOALIGN|STR_TERMINATE);
2816 SCVAL(pdata,l2_vol_cch,len);
2817 data_len = l2_vol_szVolLabel + len;
2818 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2819 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2820 len, vname));
2821 break;
2823 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2824 case SMB_FS_ATTRIBUTE_INFORMATION:
2826 additional_flags = 0;
2827 #if defined(HAVE_SYS_QUOTAS)
2828 additional_flags |= FILE_VOLUME_QUOTAS;
2829 #endif
2831 if(lp_nt_acl_support(SNUM(conn))) {
2832 additional_flags |= FILE_PERSISTENT_ACLS;
2835 /* Capabilities are filled in at connection time through STATVFS call */
2836 additional_flags |= conn->fs_capabilities;
2838 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2839 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2840 additional_flags); /* FS ATTRIBUTES */
2842 SIVAL(pdata,4,255); /* Max filename component length */
2843 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2844 and will think we can't do long filenames */
2845 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2846 PTR_DIFF(end_data, pdata+12),
2847 STR_UNICODE);
2848 SIVAL(pdata,8,len);
2849 data_len = 12 + len;
2850 break;
2852 case SMB_QUERY_FS_LABEL_INFO:
2853 case SMB_FS_LABEL_INFORMATION:
2854 len = srvstr_push(pdata, flags2, pdata+4, vname,
2855 PTR_DIFF(end_data, pdata+4), 0);
2856 data_len = 4 + len;
2857 SIVAL(pdata,0,len);
2858 break;
2860 case SMB_QUERY_FS_VOLUME_INFO:
2861 case SMB_FS_VOLUME_INFORMATION:
2864 * Add volume serial number - hash of a combination of
2865 * the called hostname and the service name.
2867 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2868 (str_checksum(get_local_machine_name())<<16));
2870 /* Max label len is 32 characters. */
2871 len = srvstr_push(pdata, flags2, pdata+18, vname,
2872 PTR_DIFF(end_data, pdata+18),
2873 STR_UNICODE);
2874 SIVAL(pdata,12,len);
2875 data_len = 18+len;
2877 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2878 (int)strlen(vname),vname, lp_servicename(snum)));
2879 break;
2881 case SMB_QUERY_FS_SIZE_INFO:
2882 case SMB_FS_SIZE_INFORMATION:
2884 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2885 data_len = 24;
2886 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2887 return map_nt_error_from_unix(errno);
2889 block_size = lp_block_size(snum);
2890 if (bsize < block_size) {
2891 uint64_t factor = block_size/bsize;
2892 bsize = block_size;
2893 dsize /= factor;
2894 dfree /= factor;
2896 if (bsize > block_size) {
2897 uint64_t factor = bsize/block_size;
2898 bsize = block_size;
2899 dsize *= factor;
2900 dfree *= factor;
2902 bytes_per_sector = 512;
2903 sectors_per_unit = bsize/bytes_per_sector;
2904 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2905 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2906 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2907 SBIG_UINT(pdata,0,dsize);
2908 SBIG_UINT(pdata,8,dfree);
2909 SIVAL(pdata,16,sectors_per_unit);
2910 SIVAL(pdata,20,bytes_per_sector);
2911 break;
2914 case SMB_FS_FULL_SIZE_INFORMATION:
2916 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2917 data_len = 32;
2918 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2919 return map_nt_error_from_unix(errno);
2921 block_size = lp_block_size(snum);
2922 if (bsize < block_size) {
2923 uint64_t factor = block_size/bsize;
2924 bsize = block_size;
2925 dsize /= factor;
2926 dfree /= factor;
2928 if (bsize > block_size) {
2929 uint64_t factor = bsize/block_size;
2930 bsize = block_size;
2931 dsize *= factor;
2932 dfree *= factor;
2934 bytes_per_sector = 512;
2935 sectors_per_unit = bsize/bytes_per_sector;
2936 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2937 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2938 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2939 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2940 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2941 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2942 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2943 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2944 break;
2947 case SMB_QUERY_FS_DEVICE_INFO:
2948 case SMB_FS_DEVICE_INFORMATION:
2949 data_len = 8;
2950 SIVAL(pdata,0,0); /* dev type */
2951 SIVAL(pdata,4,0); /* characteristics */
2952 break;
2954 #ifdef HAVE_SYS_QUOTAS
2955 case SMB_FS_QUOTA_INFORMATION:
2957 * what we have to send --metze:
2959 * Unknown1: 24 NULL bytes
2960 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2961 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2962 * Quota Flags: 2 byte :
2963 * Unknown3: 6 NULL bytes
2965 * 48 bytes total
2967 * details for Quota Flags:
2969 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2970 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2971 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2972 * 0x0001 Enable Quotas: enable quota for this fs
2976 /* we need to fake up a fsp here,
2977 * because its not send in this call
2979 files_struct fsp;
2980 SMB_NTQUOTA_STRUCT quotas;
2982 ZERO_STRUCT(fsp);
2983 ZERO_STRUCT(quotas);
2985 fsp.conn = conn;
2986 fsp.fnum = -1;
2988 /* access check */
2989 if (conn->server_info->utok.uid != sec_initial_uid()) {
2990 DEBUG(0,("set_user_quota: access_denied "
2991 "service [%s] user [%s]\n",
2992 lp_servicename(SNUM(conn)),
2993 conn->server_info->unix_name));
2994 return NT_STATUS_ACCESS_DENIED;
2997 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2998 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2999 return map_nt_error_from_unix(errno);
3002 data_len = 48;
3004 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3005 lp_servicename(SNUM(conn))));
3007 /* Unknown1 24 NULL bytes*/
3008 SBIG_UINT(pdata,0,(uint64_t)0);
3009 SBIG_UINT(pdata,8,(uint64_t)0);
3010 SBIG_UINT(pdata,16,(uint64_t)0);
3012 /* Default Soft Quota 8 bytes */
3013 SBIG_UINT(pdata,24,quotas.softlim);
3015 /* Default Hard Quota 8 bytes */
3016 SBIG_UINT(pdata,32,quotas.hardlim);
3018 /* Quota flag 2 bytes */
3019 SSVAL(pdata,40,quotas.qflags);
3021 /* Unknown3 6 NULL bytes */
3022 SSVAL(pdata,42,0);
3023 SIVAL(pdata,44,0);
3025 break;
3027 #endif /* HAVE_SYS_QUOTAS */
3028 case SMB_FS_OBJECTID_INFORMATION:
3030 unsigned char objid[16];
3031 struct smb_extended_info extended_info;
3032 memcpy(pdata,create_volume_objectid(conn, objid),16);
3033 samba_extended_info_version (&extended_info);
3034 SIVAL(pdata,16,extended_info.samba_magic);
3035 SIVAL(pdata,20,extended_info.samba_version);
3036 SIVAL(pdata,24,extended_info.samba_subversion);
3037 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3038 memcpy(pdata+36,extended_info.samba_version_string,28);
3039 data_len = 64;
3040 break;
3044 * Query the version and capabilities of the CIFS UNIX extensions
3045 * in use.
3048 case SMB_QUERY_CIFS_UNIX_INFO:
3050 bool large_write = lp_min_receive_file_size() &&
3051 !srv_is_signing_active(smbd_server_conn);
3052 bool large_read = !srv_is_signing_active(smbd_server_conn);
3053 int encrypt_caps = 0;
3055 if (!lp_unix_extensions()) {
3056 return NT_STATUS_INVALID_LEVEL;
3059 switch (conn->encrypt_level) {
3060 case 0:
3061 encrypt_caps = 0;
3062 break;
3063 case 1:
3064 case Auto:
3065 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3066 break;
3067 case Required:
3068 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3069 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3070 large_write = false;
3071 large_read = false;
3072 break;
3075 data_len = 12;
3076 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3077 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3079 /* We have POSIX ACLs, pathname, encryption,
3080 * large read/write, and locking capability. */
3082 SBIG_UINT(pdata,4,((uint64_t)(
3083 CIFS_UNIX_POSIX_ACLS_CAP|
3084 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3085 CIFS_UNIX_FCNTL_LOCKS_CAP|
3086 CIFS_UNIX_EXTATTR_CAP|
3087 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3088 encrypt_caps|
3089 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3090 (large_write ?
3091 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3092 break;
3095 case SMB_QUERY_POSIX_FS_INFO:
3097 int rc;
3098 vfs_statvfs_struct svfs;
3100 if (!lp_unix_extensions()) {
3101 return NT_STATUS_INVALID_LEVEL;
3104 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3106 if (!rc) {
3107 data_len = 56;
3108 SIVAL(pdata,0,svfs.OptimalTransferSize);
3109 SIVAL(pdata,4,svfs.BlockSize);
3110 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3111 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3112 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3113 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3114 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3115 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3116 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3117 #ifdef EOPNOTSUPP
3118 } else if (rc == EOPNOTSUPP) {
3119 return NT_STATUS_INVALID_LEVEL;
3120 #endif /* EOPNOTSUPP */
3121 } else {
3122 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3123 return NT_STATUS_DOS(ERRSRV, ERRerror);
3125 break;
3128 case SMB_QUERY_POSIX_WHOAMI:
3130 uint32_t flags = 0;
3131 uint32_t sid_bytes;
3132 int i;
3134 if (!lp_unix_extensions()) {
3135 return NT_STATUS_INVALID_LEVEL;
3138 if (max_data_bytes < 40) {
3139 return NT_STATUS_BUFFER_TOO_SMALL;
3142 /* We ARE guest if global_sid_Builtin_Guests is
3143 * in our list of SIDs.
3145 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3146 conn->server_info->ptok)) {
3147 flags |= SMB_WHOAMI_GUEST;
3150 /* We are NOT guest if global_sid_Authenticated_Users
3151 * is in our list of SIDs.
3153 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3154 conn->server_info->ptok)) {
3155 flags &= ~SMB_WHOAMI_GUEST;
3158 /* NOTE: 8 bytes for UID/GID, irrespective of native
3159 * platform size. This matches
3160 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3162 data_len = 4 /* flags */
3163 + 4 /* flag mask */
3164 + 8 /* uid */
3165 + 8 /* gid */
3166 + 4 /* ngroups */
3167 + 4 /* num_sids */
3168 + 4 /* SID bytes */
3169 + 4 /* pad/reserved */
3170 + (conn->server_info->utok.ngroups * 8)
3171 /* groups list */
3172 + (conn->server_info->ptok->num_sids *
3173 SID_MAX_SIZE)
3174 /* SID list */;
3176 SIVAL(pdata, 0, flags);
3177 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3178 SBIG_UINT(pdata, 8,
3179 (uint64_t)conn->server_info->utok.uid);
3180 SBIG_UINT(pdata, 16,
3181 (uint64_t)conn->server_info->utok.gid);
3184 if (data_len >= max_data_bytes) {
3185 /* Potential overflow, skip the GIDs and SIDs. */
3187 SIVAL(pdata, 24, 0); /* num_groups */
3188 SIVAL(pdata, 28, 0); /* num_sids */
3189 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3190 SIVAL(pdata, 36, 0); /* reserved */
3192 data_len = 40;
3193 break;
3196 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3197 SIVAL(pdata, 28, conn->server_info->num_sids);
3199 /* We walk the SID list twice, but this call is fairly
3200 * infrequent, and I don't expect that it's performance
3201 * sensitive -- jpeach
3203 for (i = 0, sid_bytes = 0;
3204 i < conn->server_info->ptok->num_sids; ++i) {
3205 sid_bytes += ndr_size_dom_sid(
3206 &conn->server_info->ptok->user_sids[i],
3207 NULL,
3211 /* SID list byte count */
3212 SIVAL(pdata, 32, sid_bytes);
3214 /* 4 bytes pad/reserved - must be zero */
3215 SIVAL(pdata, 36, 0);
3216 data_len = 40;
3218 /* GID list */
3219 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3220 SBIG_UINT(pdata, data_len,
3221 (uint64_t)conn->server_info->utok.groups[i]);
3222 data_len += 8;
3225 /* SID list */
3226 for (i = 0;
3227 i < conn->server_info->ptok->num_sids; ++i) {
3228 int sid_len = ndr_size_dom_sid(
3229 &conn->server_info->ptok->user_sids[i],
3230 NULL,
3233 sid_linearize(pdata + data_len, sid_len,
3234 &conn->server_info->ptok->user_sids[i]);
3235 data_len += sid_len;
3238 break;
3241 case SMB_MAC_QUERY_FS_INFO:
3243 * Thursby MAC extension... ONLY on NTFS filesystems
3244 * once we do streams then we don't need this
3246 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3247 data_len = 88;
3248 SIVAL(pdata,84,0x100); /* Don't support mac... */
3249 break;
3251 /* drop through */
3252 default:
3253 return NT_STATUS_INVALID_LEVEL;
3256 *ret_data_len = data_len;
3257 return NT_STATUS_OK;
3260 /****************************************************************************
3261 Reply to a TRANS2_QFSINFO (query filesystem info).
3262 ****************************************************************************/
3264 static void call_trans2qfsinfo(connection_struct *conn,
3265 struct smb_request *req,
3266 char **pparams, int total_params,
3267 char **ppdata, int total_data,
3268 unsigned int max_data_bytes)
3270 char *params = *pparams;
3271 uint16_t info_level;
3272 int data_len = 0;
3273 NTSTATUS status;
3275 if (total_params < 2) {
3276 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3277 return;
3280 info_level = SVAL(params,0);
3282 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3283 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3284 DEBUG(0,("call_trans2qfsinfo: encryption required "
3285 "and info level 0x%x sent.\n",
3286 (unsigned int)info_level));
3287 exit_server_cleanly("encryption required "
3288 "on connection");
3289 return;
3293 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3295 status = smbd_do_qfsinfo(conn, req,
3296 info_level,
3297 req->flags2,
3298 max_data_bytes,
3299 ppdata, &data_len);
3300 if (!NT_STATUS_IS_OK(status)) {
3301 reply_nterror(req, status);
3302 return;
3305 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3306 max_data_bytes);
3308 DEBUG( 4, ( "%s info_level = %d\n",
3309 smb_fn_name(req->cmd), info_level) );
3311 return;
3314 /****************************************************************************
3315 Reply to a TRANS2_SETFSINFO (set filesystem info).
3316 ****************************************************************************/
3318 static void call_trans2setfsinfo(connection_struct *conn,
3319 struct smb_request *req,
3320 char **pparams, int total_params,
3321 char **ppdata, int total_data,
3322 unsigned int max_data_bytes)
3324 char *pdata = *ppdata;
3325 char *params = *pparams;
3326 uint16 info_level;
3328 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3330 /* */
3331 if (total_params < 4) {
3332 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3333 total_params));
3334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3335 return;
3338 info_level = SVAL(params,2);
3340 if (IS_IPC(conn)) {
3341 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3342 info_level != SMB_SET_CIFS_UNIX_INFO) {
3343 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3344 "info level (0x%x) on IPC$.\n",
3345 (unsigned int)info_level));
3346 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3347 return;
3351 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3352 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3353 DEBUG(0,("call_trans2setfsinfo: encryption required "
3354 "and info level 0x%x sent.\n",
3355 (unsigned int)info_level));
3356 exit_server_cleanly("encryption required "
3357 "on connection");
3358 return;
3362 switch(info_level) {
3363 case SMB_SET_CIFS_UNIX_INFO:
3365 uint16 client_unix_major;
3366 uint16 client_unix_minor;
3367 uint32 client_unix_cap_low;
3368 uint32 client_unix_cap_high;
3370 if (!lp_unix_extensions()) {
3371 reply_nterror(req,
3372 NT_STATUS_INVALID_LEVEL);
3373 return;
3376 /* There should be 12 bytes of capabilities set. */
3377 if (total_data < 8) {
3378 reply_nterror(
3379 req,
3380 NT_STATUS_INVALID_PARAMETER);
3381 return;
3383 client_unix_major = SVAL(pdata,0);
3384 client_unix_minor = SVAL(pdata,2);
3385 client_unix_cap_low = IVAL(pdata,4);
3386 client_unix_cap_high = IVAL(pdata,8);
3387 /* Just print these values for now. */
3388 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3389 cap_low = 0x%x, cap_high = 0x%x\n",
3390 (unsigned int)client_unix_major,
3391 (unsigned int)client_unix_minor,
3392 (unsigned int)client_unix_cap_low,
3393 (unsigned int)client_unix_cap_high ));
3395 /* Here is where we must switch to posix pathname processing... */
3396 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3397 lp_set_posix_pathnames();
3398 mangle_change_to_posix();
3401 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3402 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3403 /* Client that knows how to do posix locks,
3404 * but not posix open/mkdir operations. Set a
3405 * default type for read/write checks. */
3407 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3410 break;
3413 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3415 NTSTATUS status;
3416 size_t param_len = 0;
3417 size_t data_len = total_data;
3419 if (!lp_unix_extensions()) {
3420 reply_nterror(
3421 req,
3422 NT_STATUS_INVALID_LEVEL);
3423 return;
3426 if (lp_smb_encrypt(SNUM(conn)) == false) {
3427 reply_nterror(
3428 req,
3429 NT_STATUS_NOT_SUPPORTED);
3430 return;
3433 DEBUG( 4,("call_trans2setfsinfo: "
3434 "request transport encryption.\n"));
3436 status = srv_request_encryption_setup(conn,
3437 (unsigned char **)ppdata,
3438 &data_len,
3439 (unsigned char **)pparams,
3440 &param_len);
3442 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3443 !NT_STATUS_IS_OK(status)) {
3444 reply_nterror(req, status);
3445 return;
3448 send_trans2_replies(conn, req,
3449 *pparams,
3450 param_len,
3451 *ppdata,
3452 data_len,
3453 max_data_bytes);
3455 if (NT_STATUS_IS_OK(status)) {
3456 /* Server-side transport
3457 * encryption is now *on*. */
3458 status = srv_encryption_start(conn);
3459 if (!NT_STATUS_IS_OK(status)) {
3460 exit_server_cleanly(
3461 "Failure in setting "
3462 "up encrypted transport");
3465 return;
3468 case SMB_FS_QUOTA_INFORMATION:
3470 files_struct *fsp = NULL;
3471 SMB_NTQUOTA_STRUCT quotas;
3473 ZERO_STRUCT(quotas);
3475 /* access check */
3476 if ((conn->server_info->utok.uid != sec_initial_uid())
3477 ||!CAN_WRITE(conn)) {
3478 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3479 lp_servicename(SNUM(conn)),
3480 conn->server_info->unix_name));
3481 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3482 return;
3485 /* note: normaly there're 48 bytes,
3486 * but we didn't use the last 6 bytes for now
3487 * --metze
3489 fsp = file_fsp(req, SVAL(params,0));
3491 if (!check_fsp_ntquota_handle(conn, req,
3492 fsp)) {
3493 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3494 reply_nterror(
3495 req, NT_STATUS_INVALID_HANDLE);
3496 return;
3499 if (total_data < 42) {
3500 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3501 total_data));
3502 reply_nterror(
3503 req,
3504 NT_STATUS_INVALID_PARAMETER);
3505 return;
3508 /* unknown_1 24 NULL bytes in pdata*/
3510 /* the soft quotas 8 bytes (uint64_t)*/
3511 quotas.softlim = (uint64_t)IVAL(pdata,24);
3512 #ifdef LARGE_SMB_OFF_T
3513 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3514 #else /* LARGE_SMB_OFF_T */
3515 if ((IVAL(pdata,28) != 0)&&
3516 ((quotas.softlim != 0xFFFFFFFF)||
3517 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3518 /* more than 32 bits? */
3519 reply_nterror(
3520 req,
3521 NT_STATUS_INVALID_PARAMETER);
3522 return;
3524 #endif /* LARGE_SMB_OFF_T */
3526 /* the hard quotas 8 bytes (uint64_t)*/
3527 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3528 #ifdef LARGE_SMB_OFF_T
3529 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3530 #else /* LARGE_SMB_OFF_T */
3531 if ((IVAL(pdata,36) != 0)&&
3532 ((quotas.hardlim != 0xFFFFFFFF)||
3533 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3534 /* more than 32 bits? */
3535 reply_nterror(
3536 req,
3537 NT_STATUS_INVALID_PARAMETER);
3538 return;
3540 #endif /* LARGE_SMB_OFF_T */
3542 /* quota_flags 2 bytes **/
3543 quotas.qflags = SVAL(pdata,40);
3545 /* unknown_2 6 NULL bytes follow*/
3547 /* now set the quotas */
3548 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3549 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3550 reply_nterror(req, map_nt_error_from_unix(errno));
3551 return;
3554 break;
3556 default:
3557 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3558 info_level));
3559 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3560 return;
3561 break;
3565 * sending this reply works fine,
3566 * but I'm not sure it's the same
3567 * like windows do...
3568 * --metze
3570 reply_outbuf(req, 10, 0);
3573 #if defined(HAVE_POSIX_ACLS)
3574 /****************************************************************************
3575 Utility function to count the number of entries in a POSIX acl.
3576 ****************************************************************************/
3578 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3580 unsigned int ace_count = 0;
3581 int entry_id = SMB_ACL_FIRST_ENTRY;
3582 SMB_ACL_ENTRY_T entry;
3584 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3585 /* get_next... */
3586 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3587 entry_id = SMB_ACL_NEXT_ENTRY;
3589 ace_count++;
3591 return ace_count;
3594 /****************************************************************************
3595 Utility function to marshall a POSIX acl into wire format.
3596 ****************************************************************************/
3598 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3600 int entry_id = SMB_ACL_FIRST_ENTRY;
3601 SMB_ACL_ENTRY_T entry;
3603 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3604 SMB_ACL_TAG_T tagtype;
3605 SMB_ACL_PERMSET_T permset;
3606 unsigned char perms = 0;
3607 unsigned int own_grp;
3609 /* get_next... */
3610 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3611 entry_id = SMB_ACL_NEXT_ENTRY;
3614 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3615 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3616 return False;
3619 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3620 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3621 return False;
3624 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3625 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3626 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3628 SCVAL(pdata,1,perms);
3630 switch (tagtype) {
3631 case SMB_ACL_USER_OBJ:
3632 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3633 own_grp = (unsigned int)pst->st_ex_uid;
3634 SIVAL(pdata,2,own_grp);
3635 SIVAL(pdata,6,0);
3636 break;
3637 case SMB_ACL_USER:
3639 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3640 if (!puid) {
3641 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3642 return False;
3644 own_grp = (unsigned int)*puid;
3645 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3646 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3647 SIVAL(pdata,2,own_grp);
3648 SIVAL(pdata,6,0);
3649 break;
3651 case SMB_ACL_GROUP_OBJ:
3652 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3653 own_grp = (unsigned int)pst->st_ex_gid;
3654 SIVAL(pdata,2,own_grp);
3655 SIVAL(pdata,6,0);
3656 break;
3657 case SMB_ACL_GROUP:
3659 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3660 if (!pgid) {
3661 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3662 return False;
3664 own_grp = (unsigned int)*pgid;
3665 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3666 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3667 SIVAL(pdata,2,own_grp);
3668 SIVAL(pdata,6,0);
3669 break;
3671 case SMB_ACL_MASK:
3672 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3673 SIVAL(pdata,2,0xFFFFFFFF);
3674 SIVAL(pdata,6,0xFFFFFFFF);
3675 break;
3676 case SMB_ACL_OTHER:
3677 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3678 SIVAL(pdata,2,0xFFFFFFFF);
3679 SIVAL(pdata,6,0xFFFFFFFF);
3680 break;
3681 default:
3682 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3683 return False;
3685 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3688 return True;
3690 #endif
3692 /****************************************************************************
3693 Store the FILE_UNIX_BASIC info.
3694 ****************************************************************************/
3696 static char *store_file_unix_basic(connection_struct *conn,
3697 char *pdata,
3698 files_struct *fsp,
3699 const SMB_STRUCT_STAT *psbuf)
3701 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3702 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3704 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3705 pdata += 8;
3707 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3708 pdata += 8;
3710 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3711 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3712 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3713 pdata += 24;
3715 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3716 SIVAL(pdata,4,0);
3717 pdata += 8;
3719 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3720 SIVAL(pdata,4,0);
3721 pdata += 8;
3723 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3724 pdata += 4;
3726 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3727 SIVAL(pdata,4,0);
3728 pdata += 8;
3730 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3731 SIVAL(pdata,4,0);
3732 pdata += 8;
3734 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3735 pdata += 8;
3737 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3738 SIVAL(pdata,4,0);
3739 pdata += 8;
3741 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3742 SIVAL(pdata,4,0);
3743 pdata += 8;
3745 return pdata;
3748 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3749 * the chflags(2) (or equivalent) flags.
3751 * XXX: this really should be behind the VFS interface. To do this, we would
3752 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3753 * Each VFS module could then implement its own mapping as appropriate for the
3754 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3756 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3757 info2_flags_map[] =
3759 #ifdef UF_NODUMP
3760 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3761 #endif
3763 #ifdef UF_IMMUTABLE
3764 { UF_IMMUTABLE, EXT_IMMUTABLE },
3765 #endif
3767 #ifdef UF_APPEND
3768 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3769 #endif
3771 #ifdef UF_HIDDEN
3772 { UF_HIDDEN, EXT_HIDDEN },
3773 #endif
3775 /* Do not remove. We need to guarantee that this array has at least one
3776 * entry to build on HP-UX.
3778 { 0, 0 }
3782 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3783 uint32 *smb_fflags, uint32 *smb_fmask)
3785 int i;
3787 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3788 *smb_fmask |= info2_flags_map[i].smb_fflag;
3789 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3790 *smb_fflags |= info2_flags_map[i].smb_fflag;
3795 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3796 const uint32 smb_fflags,
3797 const uint32 smb_fmask,
3798 int *stat_fflags)
3800 uint32 max_fmask = 0;
3801 int i;
3803 *stat_fflags = psbuf->st_ex_flags;
3805 /* For each flags requested in smb_fmask, check the state of the
3806 * corresponding flag in smb_fflags and set or clear the matching
3807 * stat flag.
3810 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3811 max_fmask |= info2_flags_map[i].smb_fflag;
3812 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3813 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3814 *stat_fflags |= info2_flags_map[i].stat_fflag;
3815 } else {
3816 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3821 /* If smb_fmask is asking to set any bits that are not supported by
3822 * our flag mappings, we should fail.
3824 if ((smb_fmask & max_fmask) != smb_fmask) {
3825 return False;
3828 return True;
3832 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3833 * of file flags and birth (create) time.
3835 static char *store_file_unix_basic_info2(connection_struct *conn,
3836 char *pdata,
3837 files_struct *fsp,
3838 const SMB_STRUCT_STAT *psbuf)
3840 uint32 file_flags = 0;
3841 uint32 flags_mask = 0;
3843 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3845 /* Create (birth) time 64 bit */
3846 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3847 pdata += 8;
3849 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3850 SIVAL(pdata, 0, file_flags); /* flags */
3851 SIVAL(pdata, 4, flags_mask); /* mask */
3852 pdata += 8;
3854 return pdata;
3857 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3858 const struct stream_struct *streams,
3859 char *data,
3860 unsigned int max_data_bytes,
3861 unsigned int *data_size)
3863 unsigned int i;
3864 unsigned int ofs = 0;
3866 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3867 unsigned int next_offset;
3868 size_t namelen;
3869 smb_ucs2_t *namebuf;
3871 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3872 streams[i].name, &namelen) ||
3873 namelen <= 2)
3875 return NT_STATUS_INVALID_PARAMETER;
3879 * name_buf is now null-terminated, we need to marshall as not
3880 * terminated
3883 namelen -= 2;
3885 SIVAL(data, ofs+4, namelen);
3886 SOFF_T(data, ofs+8, streams[i].size);
3887 SOFF_T(data, ofs+16, streams[i].alloc_size);
3888 memcpy(data+ofs+24, namebuf, namelen);
3889 TALLOC_FREE(namebuf);
3891 next_offset = ofs + 24 + namelen;
3893 if (i == num_streams-1) {
3894 SIVAL(data, ofs, 0);
3896 else {
3897 unsigned int align = ndr_align_size(next_offset, 8);
3899 memset(data+next_offset, 0, align);
3900 next_offset += align;
3902 SIVAL(data, ofs, next_offset - ofs);
3903 ofs = next_offset;
3906 ofs = next_offset;
3909 *data_size = ofs;
3911 return NT_STATUS_OK;
3914 /****************************************************************************
3915 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3916 ****************************************************************************/
3918 static void call_trans2qpipeinfo(connection_struct *conn,
3919 struct smb_request *req,
3920 unsigned int tran_call,
3921 char **pparams, int total_params,
3922 char **ppdata, int total_data,
3923 unsigned int max_data_bytes)
3925 char *params = *pparams;
3926 char *pdata = *ppdata;
3927 unsigned int data_size = 0;
3928 unsigned int param_size = 2;
3929 uint16 info_level;
3930 files_struct *fsp;
3932 if (!params) {
3933 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3934 return;
3937 if (total_params < 4) {
3938 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3939 return;
3942 fsp = file_fsp(req, SVAL(params,0));
3943 if (!fsp_is_np(fsp)) {
3944 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3945 return;
3948 info_level = SVAL(params,2);
3950 *pparams = (char *)SMB_REALLOC(*pparams,2);
3951 if (*pparams == NULL) {
3952 reply_nterror(req, NT_STATUS_NO_MEMORY);
3953 return;
3955 params = *pparams;
3956 SSVAL(params,0,0);
3957 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3958 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3959 if (*ppdata == NULL ) {
3960 reply_nterror(req, NT_STATUS_NO_MEMORY);
3961 return;
3963 pdata = *ppdata;
3965 switch (info_level) {
3966 case SMB_FILE_STANDARD_INFORMATION:
3967 memset(pdata,0,24);
3968 SOFF_T(pdata,0,4096LL);
3969 SIVAL(pdata,16,1);
3970 SIVAL(pdata,20,1);
3971 data_size = 24;
3972 break;
3974 default:
3975 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3976 return;
3979 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3980 max_data_bytes);
3982 return;
3985 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3986 TALLOC_CTX *mem_ctx,
3987 uint16_t info_level,
3988 files_struct *fsp,
3989 const struct smb_filename *smb_fname,
3990 bool delete_pending,
3991 struct timespec write_time_ts,
3992 bool ms_dfs_link,
3993 struct ea_list *ea_list,
3994 int lock_data_count,
3995 char *lock_data,
3996 uint16_t flags2,
3997 unsigned int max_data_bytes,
3998 char **ppdata,
3999 unsigned int *pdata_size)
4001 char *pdata = *ppdata;
4002 char *dstart, *dend;
4003 unsigned int data_size;
4004 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4005 time_t create_time, mtime, atime, c_time;
4006 SMB_STRUCT_STAT sbuf;
4007 char *p;
4008 char *base_name;
4009 char *dos_fname;
4010 int mode;
4011 int nlink;
4012 NTSTATUS status;
4013 uint64_t file_size = 0;
4014 uint64_t pos = 0;
4015 uint64_t allocation_size = 0;
4016 uint64_t file_index = 0;
4017 uint32_t access_mask = 0;
4019 sbuf = smb_fname->st;
4021 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4022 return NT_STATUS_INVALID_LEVEL;
4025 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4026 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4027 info_level, max_data_bytes));
4029 if (ms_dfs_link) {
4030 mode = dos_mode_msdfs(conn, smb_fname);
4031 } else {
4032 mode = dos_mode(conn, smb_fname);
4034 if (!mode)
4035 mode = FILE_ATTRIBUTE_NORMAL;
4037 nlink = sbuf.st_ex_nlink;
4039 if (nlink && (mode&aDIR)) {
4040 nlink = 1;
4043 if ((nlink > 0) && delete_pending) {
4044 nlink -= 1;
4047 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4048 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4049 if (*ppdata == NULL) {
4050 return NT_STATUS_NO_MEMORY;
4052 pdata = *ppdata;
4053 dstart = pdata;
4054 dend = dstart + data_size - 1;
4056 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4057 update_stat_ex_mtime(&sbuf, write_time_ts);
4060 create_time_ts = get_create_timespec(fsp, smb_fname);
4061 mtime_ts = sbuf.st_ex_mtime;
4062 atime_ts = sbuf.st_ex_atime;
4063 ctime_ts = get_change_timespec(fsp, smb_fname);
4065 if (lp_dos_filetime_resolution(SNUM(conn))) {
4066 dos_filetime_timespec(&create_time_ts);
4067 dos_filetime_timespec(&mtime_ts);
4068 dos_filetime_timespec(&atime_ts);
4069 dos_filetime_timespec(&ctime_ts);
4072 create_time = convert_timespec_to_time_t(create_time_ts);
4073 mtime = convert_timespec_to_time_t(mtime_ts);
4074 atime = convert_timespec_to_time_t(atime_ts);
4075 c_time = convert_timespec_to_time_t(ctime_ts);
4077 p = strrchr_m(smb_fname->base_name,'/');
4078 if (!p)
4079 base_name = smb_fname->base_name;
4080 else
4081 base_name = p+1;
4083 /* NT expects the name to be in an exact form of the *full*
4084 filename. See the trans2 torture test */
4085 if (ISDOT(base_name)) {
4086 dos_fname = talloc_strdup(mem_ctx, "\\");
4087 if (!dos_fname) {
4088 return NT_STATUS_NO_MEMORY;
4090 } else {
4091 dos_fname = talloc_asprintf(mem_ctx,
4092 "\\%s",
4093 smb_fname->base_name);
4094 if (!dos_fname) {
4095 return NT_STATUS_NO_MEMORY;
4097 if (is_ntfs_stream_smb_fname(smb_fname)) {
4098 dos_fname = talloc_asprintf(dos_fname, "%s",
4099 smb_fname->stream_name);
4100 if (!dos_fname) {
4101 return NT_STATUS_NO_MEMORY;
4105 string_replace(dos_fname, '/', '\\');
4108 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4110 if (!fsp) {
4111 /* Do we have this path open ? */
4112 files_struct *fsp1;
4113 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4114 fsp1 = file_find_di_first(fileid);
4115 if (fsp1 && fsp1->initial_allocation_size) {
4116 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4120 if (!(mode & aDIR)) {
4121 file_size = get_file_size_stat(&sbuf);
4124 if (fsp) {
4125 pos = fsp->fh->position_information;
4128 if (fsp) {
4129 access_mask = fsp->access_mask;
4130 } else {
4131 /* GENERIC_EXECUTE mapping from Windows */
4132 access_mask = 0x12019F;
4135 /* This should be an index number - looks like
4136 dev/ino to me :-)
4138 I think this causes us to fail the IFSKIT
4139 BasicFileInformationTest. -tpot */
4140 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4141 file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4143 switch (info_level) {
4144 case SMB_INFO_STANDARD:
4145 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4146 data_size = 22;
4147 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4148 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4149 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4150 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4151 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4152 SSVAL(pdata,l1_attrFile,mode);
4153 break;
4155 case SMB_INFO_QUERY_EA_SIZE:
4157 unsigned int ea_size =
4158 estimate_ea_size(conn, fsp,
4159 smb_fname->base_name);
4160 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4161 data_size = 26;
4162 srv_put_dos_date2(pdata,0,create_time);
4163 srv_put_dos_date2(pdata,4,atime);
4164 srv_put_dos_date2(pdata,8,mtime); /* write time */
4165 SIVAL(pdata,12,(uint32)file_size);
4166 SIVAL(pdata,16,(uint32)allocation_size);
4167 SSVAL(pdata,20,mode);
4168 SIVAL(pdata,22,ea_size);
4169 break;
4172 case SMB_INFO_IS_NAME_VALID:
4173 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4174 if (fsp) {
4175 /* os/2 needs this ? really ?*/
4176 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4178 /* This is only reached for qpathinfo */
4179 data_size = 0;
4180 break;
4182 case SMB_INFO_QUERY_EAS_FROM_LIST:
4184 size_t total_ea_len = 0;
4185 struct ea_list *ea_file_list = NULL;
4187 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4189 ea_file_list =
4190 get_ea_list_from_file(mem_ctx, conn, fsp,
4191 smb_fname->base_name,
4192 &total_ea_len);
4193 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4195 if (!ea_list || (total_ea_len > data_size)) {
4196 data_size = 4;
4197 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4198 break;
4201 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4202 break;
4205 case SMB_INFO_QUERY_ALL_EAS:
4207 /* We have data_size bytes to put EA's into. */
4208 size_t total_ea_len = 0;
4210 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4212 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4213 smb_fname->base_name,
4214 &total_ea_len);
4215 if (!ea_list || (total_ea_len > data_size)) {
4216 data_size = 4;
4217 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4218 break;
4221 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4222 break;
4225 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4227 /* We have data_size bytes to put EA's into. */
4228 size_t total_ea_len = 0;
4229 struct ea_list *ea_file_list = NULL;
4231 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4233 /*TODO: add filtering and index handling */
4235 ea_file_list =
4236 get_ea_list_from_file(mem_ctx, conn, fsp,
4237 smb_fname->base_name,
4238 &total_ea_len);
4239 if (!ea_file_list) {
4240 return NT_STATUS_NO_EAS_ON_FILE;
4243 status = fill_ea_chained_buffer(mem_ctx,
4244 pdata,
4245 data_size,
4246 &data_size,
4247 conn, ea_file_list);
4248 if (!NT_STATUS_IS_OK(status)) {
4249 return status;
4251 break;
4254 case SMB_FILE_BASIC_INFORMATION:
4255 case SMB_QUERY_FILE_BASIC_INFO:
4257 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4258 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4259 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4260 } else {
4261 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4262 data_size = 40;
4263 SIVAL(pdata,36,0);
4265 put_long_date_timespec(pdata,create_time_ts);
4266 put_long_date_timespec(pdata+8,atime_ts);
4267 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4268 put_long_date_timespec(pdata+24,ctime_ts); /* change time */
4269 SIVAL(pdata,32,mode);
4271 DEBUG(5,("SMB_QFBI - "));
4272 DEBUG(5,("create: %s ", ctime(&create_time)));
4273 DEBUG(5,("access: %s ", ctime(&atime)));
4274 DEBUG(5,("write: %s ", ctime(&mtime)));
4275 DEBUG(5,("change: %s ", ctime(&c_time)));
4276 DEBUG(5,("mode: %x\n", mode));
4277 break;
4279 case SMB_FILE_STANDARD_INFORMATION:
4280 case SMB_QUERY_FILE_STANDARD_INFO:
4282 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4283 data_size = 24;
4284 SOFF_T(pdata,0,allocation_size);
4285 SOFF_T(pdata,8,file_size);
4286 SIVAL(pdata,16,nlink);
4287 SCVAL(pdata,20,delete_pending?1:0);
4288 SCVAL(pdata,21,(mode&aDIR)?1:0);
4289 SSVAL(pdata,22,0); /* Padding. */
4290 break;
4292 case SMB_FILE_EA_INFORMATION:
4293 case SMB_QUERY_FILE_EA_INFO:
4295 unsigned int ea_size =
4296 estimate_ea_size(conn, fsp, smb_fname->base_name);
4297 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4298 data_size = 4;
4299 SIVAL(pdata,0,ea_size);
4300 break;
4303 /* Get the 8.3 name - used if NT SMB was negotiated. */
4304 case SMB_QUERY_FILE_ALT_NAME_INFO:
4305 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4307 int len;
4308 char mangled_name[13];
4309 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4310 if (!name_to_8_3(base_name,mangled_name,
4311 True,conn->params)) {
4312 return NT_STATUS_NO_MEMORY;
4314 len = srvstr_push(dstart, flags2,
4315 pdata+4, mangled_name,
4316 PTR_DIFF(dend, pdata+4),
4317 STR_UNICODE);
4318 data_size = 4 + len;
4319 SIVAL(pdata,0,len);
4320 break;
4323 case SMB_QUERY_FILE_NAME_INFO:
4325 int len;
4327 this must be *exactly* right for ACLs on mapped drives to work
4329 len = srvstr_push(dstart, flags2,
4330 pdata+4, dos_fname,
4331 PTR_DIFF(dend, pdata+4),
4332 STR_UNICODE);
4333 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4334 data_size = 4 + len;
4335 SIVAL(pdata,0,len);
4336 break;
4339 case SMB_FILE_ALLOCATION_INFORMATION:
4340 case SMB_QUERY_FILE_ALLOCATION_INFO:
4341 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4342 data_size = 8;
4343 SOFF_T(pdata,0,allocation_size);
4344 break;
4346 case SMB_FILE_END_OF_FILE_INFORMATION:
4347 case SMB_QUERY_FILE_END_OF_FILEINFO:
4348 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4349 data_size = 8;
4350 SOFF_T(pdata,0,file_size);
4351 break;
4353 case SMB_QUERY_FILE_ALL_INFO:
4354 case SMB_FILE_ALL_INFORMATION:
4356 int len;
4357 unsigned int ea_size =
4358 estimate_ea_size(conn, fsp, smb_fname->base_name);
4359 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4360 put_long_date_timespec(pdata,create_time_ts);
4361 put_long_date_timespec(pdata+8,atime_ts);
4362 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4363 put_long_date_timespec(pdata+24,ctime_ts); /* change time */
4364 SIVAL(pdata,32,mode);
4365 SIVAL(pdata,36,0); /* padding. */
4366 pdata += 40;
4367 SOFF_T(pdata,0,allocation_size);
4368 SOFF_T(pdata,8,file_size);
4369 SIVAL(pdata,16,nlink);
4370 SCVAL(pdata,20,delete_pending);
4371 SCVAL(pdata,21,(mode&aDIR)?1:0);
4372 SSVAL(pdata,22,0);
4373 pdata += 24;
4374 SIVAL(pdata,0,ea_size);
4375 pdata += 4; /* EA info */
4376 len = srvstr_push(dstart, flags2,
4377 pdata+4, dos_fname,
4378 PTR_DIFF(dend, pdata+4),
4379 STR_UNICODE);
4380 SIVAL(pdata,0,len);
4381 pdata += 4 + len;
4382 data_size = PTR_DIFF(pdata,(*ppdata));
4383 break;
4386 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4388 int len;
4389 unsigned int ea_size =
4390 estimate_ea_size(conn, fsp, smb_fname->base_name);
4391 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4392 put_long_date_timespec(pdata+0x00,create_time_ts);
4393 put_long_date_timespec(pdata+0x08,atime_ts);
4394 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4395 put_long_date_timespec(pdata+0x18,ctime_ts); /* change time */
4396 SIVAL(pdata, 0x20, mode);
4397 SIVAL(pdata, 0x24, 0); /* padding. */
4398 SBVAL(pdata, 0x28, allocation_size);
4399 SBVAL(pdata, 0x30, file_size);
4400 SIVAL(pdata, 0x38, nlink);
4401 SCVAL(pdata, 0x3C, delete_pending);
4402 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4403 SSVAL(pdata, 0x3E, 0); /* padding */
4404 SBVAL(pdata, 0x40, file_index);
4405 SIVAL(pdata, 0x48, ea_size);
4406 SIVAL(pdata, 0x4C, access_mask);
4407 SBVAL(pdata, 0x50, pos);
4408 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4409 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4411 pdata += 0x60;
4413 len = srvstr_push(dstart, flags2,
4414 pdata+4, dos_fname,
4415 PTR_DIFF(dend, pdata+4),
4416 STR_UNICODE);
4417 SIVAL(pdata,0,len);
4418 pdata += 4 + len;
4419 data_size = PTR_DIFF(pdata,(*ppdata));
4420 break;
4422 case SMB_FILE_INTERNAL_INFORMATION:
4424 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4425 SBVAL(pdata, 0, file_index);
4426 data_size = 8;
4427 break;
4429 case SMB_FILE_ACCESS_INFORMATION:
4430 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4431 SIVAL(pdata, 0, access_mask);
4432 data_size = 4;
4433 break;
4435 case SMB_FILE_NAME_INFORMATION:
4436 /* Pathname with leading '\'. */
4438 size_t byte_len;
4439 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4440 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4441 SIVAL(pdata,0,byte_len);
4442 data_size = 4 + byte_len;
4443 break;
4446 case SMB_FILE_DISPOSITION_INFORMATION:
4447 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4448 data_size = 1;
4449 SCVAL(pdata,0,delete_pending);
4450 break;
4452 case SMB_FILE_POSITION_INFORMATION:
4453 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4454 data_size = 8;
4455 SOFF_T(pdata,0,pos);
4456 break;
4458 case SMB_FILE_MODE_INFORMATION:
4459 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4460 SIVAL(pdata,0,mode);
4461 data_size = 4;
4462 break;
4464 case SMB_FILE_ALIGNMENT_INFORMATION:
4465 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4466 SIVAL(pdata,0,0); /* No alignment needed. */
4467 data_size = 4;
4468 break;
4471 * NT4 server just returns "invalid query" to this - if we try
4472 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4473 * want this. JRA.
4475 /* The first statement above is false - verified using Thursby
4476 * client against NT4 -- gcolley.
4478 case SMB_QUERY_FILE_STREAM_INFO:
4479 case SMB_FILE_STREAM_INFORMATION: {
4480 unsigned int num_streams;
4481 struct stream_struct *streams;
4483 DEBUG(10,("smbd_do_qfilepathinfo: "
4484 "SMB_FILE_STREAM_INFORMATION\n"));
4486 if (is_ntfs_stream_smb_fname(smb_fname)) {
4487 return NT_STATUS_INVALID_PARAMETER;
4490 status = SMB_VFS_STREAMINFO(
4491 conn, fsp, smb_fname->base_name, talloc_tos(),
4492 &num_streams, &streams);
4494 if (!NT_STATUS_IS_OK(status)) {
4495 DEBUG(10, ("could not get stream info: %s\n",
4496 nt_errstr(status)));
4497 return status;
4500 status = marshall_stream_info(num_streams, streams,
4501 pdata, max_data_bytes,
4502 &data_size);
4504 if (!NT_STATUS_IS_OK(status)) {
4505 DEBUG(10, ("marshall_stream_info failed: %s\n",
4506 nt_errstr(status)));
4507 return status;
4510 TALLOC_FREE(streams);
4512 break;
4514 case SMB_QUERY_COMPRESSION_INFO:
4515 case SMB_FILE_COMPRESSION_INFORMATION:
4516 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4517 SOFF_T(pdata,0,file_size);
4518 SIVAL(pdata,8,0); /* ??? */
4519 SIVAL(pdata,12,0); /* ??? */
4520 data_size = 16;
4521 break;
4523 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4524 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4525 put_long_date_timespec(pdata,create_time_ts);
4526 put_long_date_timespec(pdata+8,atime_ts);
4527 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4528 put_long_date_timespec(pdata+24,ctime_ts); /* change time */
4529 SOFF_T(pdata,32,allocation_size);
4530 SOFF_T(pdata,40,file_size);
4531 SIVAL(pdata,48,mode);
4532 SIVAL(pdata,52,0); /* ??? */
4533 data_size = 56;
4534 break;
4536 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4537 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4538 SIVAL(pdata,0,mode);
4539 SIVAL(pdata,4,0);
4540 data_size = 8;
4541 break;
4544 * CIFS UNIX Extensions.
4547 case SMB_QUERY_FILE_UNIX_BASIC:
4549 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4550 data_size = PTR_DIFF(pdata,(*ppdata));
4553 int i;
4554 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4556 for (i=0; i<100; i++)
4557 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4558 DEBUG(4,("\n"));
4561 break;
4563 case SMB_QUERY_FILE_UNIX_INFO2:
4565 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4566 data_size = PTR_DIFF(pdata,(*ppdata));
4569 int i;
4570 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4572 for (i=0; i<100; i++)
4573 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4574 DEBUG(4,("\n"));
4577 break;
4579 case SMB_QUERY_FILE_UNIX_LINK:
4581 int len;
4582 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4584 if (!buffer) {
4585 return NT_STATUS_NO_MEMORY;
4588 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4589 #ifdef S_ISLNK
4590 if(!S_ISLNK(sbuf.st_ex_mode)) {
4591 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4593 #else
4594 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4595 #endif
4596 len = SMB_VFS_READLINK(conn,
4597 smb_fname->base_name,
4598 buffer, PATH_MAX);
4599 if (len == -1) {
4600 return map_nt_error_from_unix(errno);
4602 buffer[len] = 0;
4603 len = srvstr_push(dstart, flags2,
4604 pdata, buffer,
4605 PTR_DIFF(dend, pdata),
4606 STR_TERMINATE);
4607 pdata += len;
4608 data_size = PTR_DIFF(pdata,(*ppdata));
4610 break;
4613 #if defined(HAVE_POSIX_ACLS)
4614 case SMB_QUERY_POSIX_ACL:
4616 SMB_ACL_T file_acl = NULL;
4617 SMB_ACL_T def_acl = NULL;
4618 uint16 num_file_acls = 0;
4619 uint16 num_def_acls = 0;
4621 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4622 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4623 } else {
4624 file_acl =
4625 SMB_VFS_SYS_ACL_GET_FILE(conn,
4626 smb_fname->base_name,
4627 SMB_ACL_TYPE_ACCESS);
4630 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4631 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4632 "not implemented on "
4633 "filesystem containing %s\n",
4634 smb_fname->base_name));
4635 return NT_STATUS_NOT_IMPLEMENTED;
4638 if (S_ISDIR(sbuf.st_ex_mode)) {
4639 if (fsp && fsp->is_directory) {
4640 def_acl =
4641 SMB_VFS_SYS_ACL_GET_FILE(
4642 conn,
4643 fsp->fsp_name->base_name,
4644 SMB_ACL_TYPE_DEFAULT);
4645 } else {
4646 def_acl =
4647 SMB_VFS_SYS_ACL_GET_FILE(
4648 conn,
4649 smb_fname->base_name,
4650 SMB_ACL_TYPE_DEFAULT);
4652 def_acl = free_empty_sys_acl(conn, def_acl);
4655 num_file_acls = count_acl_entries(conn, file_acl);
4656 num_def_acls = count_acl_entries(conn, def_acl);
4658 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4659 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4660 data_size,
4661 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4662 SMB_POSIX_ACL_HEADER_SIZE) ));
4663 if (file_acl) {
4664 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4666 if (def_acl) {
4667 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4669 return NT_STATUS_BUFFER_TOO_SMALL;
4672 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4673 SSVAL(pdata,2,num_file_acls);
4674 SSVAL(pdata,4,num_def_acls);
4675 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4676 if (file_acl) {
4677 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4679 if (def_acl) {
4680 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4682 return NT_STATUS_INTERNAL_ERROR;
4684 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4685 if (file_acl) {
4686 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4688 if (def_acl) {
4689 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4691 return NT_STATUS_INTERNAL_ERROR;
4694 if (file_acl) {
4695 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4697 if (def_acl) {
4698 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4700 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4701 break;
4703 #endif
4706 case SMB_QUERY_POSIX_LOCK:
4708 uint64_t count;
4709 uint64_t offset;
4710 uint32 lock_pid;
4711 enum brl_type lock_type;
4713 /* We need an open file with a real fd for this. */
4714 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4715 return NT_STATUS_INVALID_LEVEL;
4718 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4719 return NT_STATUS_INVALID_PARAMETER;
4722 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4723 case POSIX_LOCK_TYPE_READ:
4724 lock_type = READ_LOCK;
4725 break;
4726 case POSIX_LOCK_TYPE_WRITE:
4727 lock_type = WRITE_LOCK;
4728 break;
4729 case POSIX_LOCK_TYPE_UNLOCK:
4730 default:
4731 /* There's no point in asking for an unlock... */
4732 return NT_STATUS_INVALID_PARAMETER;
4735 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4736 #if defined(HAVE_LONGLONG)
4737 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4738 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4739 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4740 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4741 #else /* HAVE_LONGLONG */
4742 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4743 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4744 #endif /* HAVE_LONGLONG */
4746 status = query_lock(fsp,
4747 &lock_pid,
4748 &count,
4749 &offset,
4750 &lock_type,
4751 POSIX_LOCK);
4753 if (ERROR_WAS_LOCK_DENIED(status)) {
4754 /* Here we need to report who has it locked... */
4755 data_size = POSIX_LOCK_DATA_SIZE;
4757 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4758 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4759 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4760 #if defined(HAVE_LONGLONG)
4761 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4762 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4763 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4764 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4765 #else /* HAVE_LONGLONG */
4766 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4767 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4768 #endif /* HAVE_LONGLONG */
4770 } else if (NT_STATUS_IS_OK(status)) {
4771 /* For success we just return a copy of what we sent
4772 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4773 data_size = POSIX_LOCK_DATA_SIZE;
4774 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4775 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4776 } else {
4777 return status;
4779 break;
4782 default:
4783 return NT_STATUS_INVALID_LEVEL;
4786 *pdata_size = data_size;
4787 return NT_STATUS_OK;
4790 /****************************************************************************
4791 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4792 file name or file id).
4793 ****************************************************************************/
4795 static void call_trans2qfilepathinfo(connection_struct *conn,
4796 struct smb_request *req,
4797 unsigned int tran_call,
4798 char **pparams, int total_params,
4799 char **ppdata, int total_data,
4800 unsigned int max_data_bytes)
4802 char *params = *pparams;
4803 char *pdata = *ppdata;
4804 uint16 info_level;
4805 unsigned int data_size = 0;
4806 unsigned int param_size = 2;
4807 struct smb_filename *smb_fname = NULL;
4808 bool delete_pending = False;
4809 struct timespec write_time_ts;
4810 files_struct *fsp = NULL;
4811 struct file_id fileid;
4812 struct ea_list *ea_list = NULL;
4813 int lock_data_count = 0;
4814 char *lock_data = NULL;
4815 bool ms_dfs_link = false;
4816 NTSTATUS status = NT_STATUS_OK;
4818 if (!params) {
4819 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4820 return;
4823 ZERO_STRUCT(write_time_ts);
4825 if (tran_call == TRANSACT2_QFILEINFO) {
4826 if (total_params < 4) {
4827 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4828 return;
4831 if (IS_IPC(conn)) {
4832 call_trans2qpipeinfo(conn, req, tran_call,
4833 pparams, total_params,
4834 ppdata, total_data,
4835 max_data_bytes);
4836 return;
4839 fsp = file_fsp(req, SVAL(params,0));
4840 info_level = SVAL(params,2);
4842 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4844 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4845 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4846 return;
4849 /* Initial check for valid fsp ptr. */
4850 if (!check_fsp_open(conn, req, fsp)) {
4851 return;
4854 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
4855 &smb_fname);
4856 if (!NT_STATUS_IS_OK(status)) {
4857 reply_nterror(req, status);
4858 return;
4861 if(fsp->fake_file_handle) {
4863 * This is actually for the QUOTA_FAKE_FILE --metze
4866 /* We know this name is ok, it's already passed the checks. */
4868 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4870 * This is actually a QFILEINFO on a directory
4871 * handle (returned from an NT SMB). NT5.0 seems
4872 * to do this call. JRA.
4875 if (INFO_LEVEL_IS_UNIX(info_level)) {
4876 /* Always do lstat for UNIX calls. */
4877 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4878 DEBUG(3,("call_trans2qfilepathinfo: "
4879 "SMB_VFS_LSTAT of %s failed "
4880 "(%s)\n",
4881 smb_fname_str_dbg(smb_fname),
4882 strerror(errno)));
4883 reply_nterror(req,
4884 map_nt_error_from_unix(errno));
4885 return;
4887 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4888 DEBUG(3,("call_trans2qfilepathinfo: "
4889 "SMB_VFS_STAT of %s failed (%s)\n",
4890 smb_fname_str_dbg(smb_fname),
4891 strerror(errno)));
4892 reply_nterror(req,
4893 map_nt_error_from_unix(errno));
4894 return;
4897 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4898 get_file_infos(fileid, &delete_pending, &write_time_ts);
4899 } else {
4901 * Original code - this is an open file.
4903 if (!check_fsp(conn, req, fsp)) {
4904 return;
4907 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4908 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4909 fsp->fnum, strerror(errno)));
4910 reply_nterror(req,
4911 map_nt_error_from_unix(errno));
4912 return;
4914 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4915 get_file_infos(fileid, &delete_pending, &write_time_ts);
4918 } else {
4919 char *fname = NULL;
4921 /* qpathinfo */
4922 if (total_params < 7) {
4923 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4924 return;
4927 info_level = SVAL(params,0);
4929 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4931 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4932 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4933 return;
4936 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
4937 total_params - 6,
4938 STR_TERMINATE, &status);
4939 if (!NT_STATUS_IS_OK(status)) {
4940 reply_nterror(req, status);
4941 return;
4944 status = filename_convert(req,
4945 conn,
4946 req->flags2 & FLAGS2_DFS_PATHNAMES,
4947 fname,
4949 NULL,
4950 &smb_fname);
4951 if (!NT_STATUS_IS_OK(status)) {
4952 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4953 reply_botherror(req,
4954 NT_STATUS_PATH_NOT_COVERED,
4955 ERRSRV, ERRbadpath);
4956 return;
4958 reply_nterror(req, status);
4959 return;
4962 /* If this is a stream, check if there is a delete_pending. */
4963 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4964 && is_ntfs_stream_smb_fname(smb_fname)) {
4965 struct smb_filename *smb_fname_base = NULL;
4967 /* Create an smb_filename with stream_name == NULL. */
4968 status =
4969 create_synthetic_smb_fname(talloc_tos(),
4970 smb_fname->base_name,
4971 NULL, NULL,
4972 &smb_fname_base);
4973 if (!NT_STATUS_IS_OK(status)) {
4974 reply_nterror(req, status);
4975 return;
4978 if (INFO_LEVEL_IS_UNIX(info_level)) {
4979 /* Always do lstat for UNIX calls. */
4980 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4981 DEBUG(3,("call_trans2qfilepathinfo: "
4982 "SMB_VFS_LSTAT of %s failed "
4983 "(%s)\n",
4984 smb_fname_str_dbg(smb_fname_base),
4985 strerror(errno)));
4986 TALLOC_FREE(smb_fname_base);
4987 reply_nterror(req,
4988 map_nt_error_from_unix(errno));
4989 return;
4991 } else {
4992 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4993 DEBUG(3,("call_trans2qfilepathinfo: "
4994 "fileinfo of %s failed "
4995 "(%s)\n",
4996 smb_fname_str_dbg(smb_fname_base),
4997 strerror(errno)));
4998 TALLOC_FREE(smb_fname_base);
4999 reply_nterror(req,
5000 map_nt_error_from_unix(errno));
5001 return;
5005 fileid = vfs_file_id_from_sbuf(conn,
5006 &smb_fname_base->st);
5007 TALLOC_FREE(smb_fname_base);
5008 get_file_infos(fileid, &delete_pending, NULL);
5009 if (delete_pending) {
5010 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5011 return;
5015 if (INFO_LEVEL_IS_UNIX(info_level)) {
5016 /* Always do lstat for UNIX calls. */
5017 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5018 DEBUG(3,("call_trans2qfilepathinfo: "
5019 "SMB_VFS_LSTAT of %s failed (%s)\n",
5020 smb_fname_str_dbg(smb_fname),
5021 strerror(errno)));
5022 reply_nterror(req,
5023 map_nt_error_from_unix(errno));
5024 return;
5027 } else if (!VALID_STAT(smb_fname->st) &&
5028 SMB_VFS_STAT(conn, smb_fname) &&
5029 (info_level != SMB_INFO_IS_NAME_VALID)) {
5030 ms_dfs_link = check_msdfs_link(conn,
5031 smb_fname->base_name,
5032 &smb_fname->st);
5034 if (!ms_dfs_link) {
5035 DEBUG(3,("call_trans2qfilepathinfo: "
5036 "SMB_VFS_STAT of %s failed (%s)\n",
5037 smb_fname_str_dbg(smb_fname),
5038 strerror(errno)));
5039 reply_nterror(req,
5040 map_nt_error_from_unix(errno));
5041 return;
5045 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5046 get_file_infos(fileid, &delete_pending, &write_time_ts);
5047 if (delete_pending) {
5048 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5049 return;
5053 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5054 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5055 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5057 /* Pull out any data sent here before we realloc. */
5058 switch (info_level) {
5059 case SMB_INFO_QUERY_EAS_FROM_LIST:
5061 /* Pull any EA list from the data portion. */
5062 uint32 ea_size;
5064 if (total_data < 4) {
5065 reply_nterror(
5066 req, NT_STATUS_INVALID_PARAMETER);
5067 return;
5069 ea_size = IVAL(pdata,0);
5071 if (total_data > 0 && ea_size != total_data) {
5072 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5073 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5074 reply_nterror(
5075 req, NT_STATUS_INVALID_PARAMETER);
5076 return;
5079 if (!lp_ea_support(SNUM(conn))) {
5080 reply_doserror(req, ERRDOS,
5081 ERReasnotsupported);
5082 return;
5085 /* Pull out the list of names. */
5086 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5087 if (!ea_list) {
5088 reply_nterror(
5089 req, NT_STATUS_INVALID_PARAMETER);
5090 return;
5092 break;
5095 case SMB_QUERY_POSIX_LOCK:
5097 if (fsp == NULL || fsp->fh->fd == -1) {
5098 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5099 return;
5102 if (total_data != POSIX_LOCK_DATA_SIZE) {
5103 reply_nterror(
5104 req, NT_STATUS_INVALID_PARAMETER);
5105 return;
5108 /* Copy the lock range data. */
5109 lock_data = (char *)TALLOC_MEMDUP(
5110 req, pdata, total_data);
5111 if (!lock_data) {
5112 reply_nterror(req, NT_STATUS_NO_MEMORY);
5113 return;
5115 lock_data_count = total_data;
5117 default:
5118 break;
5121 *pparams = (char *)SMB_REALLOC(*pparams,2);
5122 if (*pparams == NULL) {
5123 reply_nterror(req, NT_STATUS_NO_MEMORY);
5124 return;
5126 params = *pparams;
5127 SSVAL(params,0,0);
5130 * draft-leach-cifs-v1-spec-02.txt
5131 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5132 * says:
5134 * The requested information is placed in the Data portion of the
5135 * transaction response. For the information levels greater than 0x100,
5136 * the transaction response has 1 parameter word which should be
5137 * ignored by the client.
5139 * However Windows only follows this rule for the IS_NAME_VALID call.
5141 switch (info_level) {
5142 case SMB_INFO_IS_NAME_VALID:
5143 param_size = 0;
5144 break;
5147 if ((info_level & 0xFF00) == 0xFF00) {
5149 * We use levels that start with 0xFF00
5150 * internally to represent SMB2 specific levels
5152 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5153 return;
5156 status = smbd_do_qfilepathinfo(conn, req, info_level,
5157 fsp, smb_fname,
5158 delete_pending, write_time_ts,
5159 ms_dfs_link, ea_list,
5160 lock_data_count, lock_data,
5161 req->flags2, max_data_bytes,
5162 ppdata, &data_size);
5163 if (!NT_STATUS_IS_OK(status)) {
5164 reply_nterror(req, status);
5165 return;
5168 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5169 max_data_bytes);
5171 return;
5174 /****************************************************************************
5175 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5176 code.
5177 ****************************************************************************/
5179 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5180 connection_struct *conn,
5181 const struct smb_filename *smb_fname_old,
5182 const struct smb_filename *smb_fname_new)
5184 NTSTATUS status = NT_STATUS_OK;
5186 /* source must already exist. */
5187 if (!VALID_STAT(smb_fname_old->st)) {
5188 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5191 /* Disallow if newname already exists. */
5192 if (VALID_STAT(smb_fname_new->st)) {
5193 return NT_STATUS_OBJECT_NAME_COLLISION;
5196 /* No links from a directory. */
5197 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5198 return NT_STATUS_FILE_IS_A_DIRECTORY;
5201 /* Setting a hardlink to/from a stream isn't currently supported. */
5202 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5203 is_ntfs_stream_smb_fname(smb_fname_new)) {
5204 return NT_STATUS_INVALID_PARAMETER;
5207 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5208 smb_fname_old->base_name, smb_fname_new->base_name));
5210 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5211 smb_fname_new->base_name) != 0) {
5212 status = map_nt_error_from_unix(errno);
5213 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5214 nt_errstr(status), smb_fname_old->base_name,
5215 smb_fname_new->base_name));
5217 return status;
5220 /****************************************************************************
5221 Deal with setting the time from any of the setfilepathinfo functions.
5222 ****************************************************************************/
5224 NTSTATUS smb_set_file_time(connection_struct *conn,
5225 files_struct *fsp,
5226 const struct smb_filename *smb_fname,
5227 struct smb_file_time *ft,
5228 bool setting_write_time)
5230 struct smb_filename *smb_fname_base = NULL;
5231 uint32 action =
5232 FILE_NOTIFY_CHANGE_LAST_ACCESS
5233 |FILE_NOTIFY_CHANGE_LAST_WRITE
5234 |FILE_NOTIFY_CHANGE_CREATION;
5235 NTSTATUS status;
5237 if (!VALID_STAT(smb_fname->st)) {
5238 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5241 /* get some defaults (no modifications) if any info is zero or -1. */
5242 if (null_timespec(ft->create_time)) {
5243 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5246 if (null_timespec(ft->atime)) {
5247 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5250 if (null_timespec(ft->mtime)) {
5251 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5254 if (!setting_write_time) {
5255 /* ft->mtime comes from change time, not write time. */
5256 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5259 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5260 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5261 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5262 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5263 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5264 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5265 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5266 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5268 if (setting_write_time) {
5270 * This was a Windows setfileinfo on an open file.
5271 * NT does this a lot. We also need to
5272 * set the time here, as it can be read by
5273 * FindFirst/FindNext and with the patch for bug #2045
5274 * in smbd/fileio.c it ensures that this timestamp is
5275 * kept sticky even after a write. We save the request
5276 * away and will set it on file close and after a write. JRA.
5279 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5280 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5282 if (fsp != NULL) {
5283 if (fsp->base_fsp) {
5284 set_sticky_write_time_fsp(fsp->base_fsp,
5285 ft->mtime);
5286 } else {
5287 set_sticky_write_time_fsp(fsp, ft->mtime);
5289 } else {
5290 set_sticky_write_time_path(
5291 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5292 ft->mtime);
5296 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5298 /* Always call ntimes on the base, even if a stream was passed in. */
5299 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5300 NULL, &smb_fname->st,
5301 &smb_fname_base);
5302 if (!NT_STATUS_IS_OK(status)) {
5303 return status;
5306 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5307 TALLOC_FREE(smb_fname_base);
5308 return map_nt_error_from_unix(errno);
5310 TALLOC_FREE(smb_fname_base);
5312 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5313 smb_fname->base_name);
5314 return NT_STATUS_OK;
5317 /****************************************************************************
5318 Deal with setting the dosmode from any of the setfilepathinfo functions.
5319 ****************************************************************************/
5321 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5322 const struct smb_filename *smb_fname,
5323 uint32 dosmode)
5325 struct smb_filename *smb_fname_base = NULL;
5326 NTSTATUS status;
5328 if (!VALID_STAT(smb_fname->st)) {
5329 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5332 /* Always operate on the base_name, even if a stream was passed in. */
5333 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5334 NULL, &smb_fname->st,
5335 &smb_fname_base);
5336 if (!NT_STATUS_IS_OK(status)) {
5337 return status;
5340 if (dosmode) {
5341 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5342 dosmode |= aDIR;
5343 } else {
5344 dosmode &= ~aDIR;
5348 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5350 /* check the mode isn't different, before changing it */
5351 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5352 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5353 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5354 (unsigned int)dosmode));
5356 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5357 false)) {
5358 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5359 "%s failed (%s)\n",
5360 smb_fname_str_dbg(smb_fname_base),
5361 strerror(errno)));
5362 status = map_nt_error_from_unix(errno);
5363 goto out;
5366 status = NT_STATUS_OK;
5367 out:
5368 TALLOC_FREE(smb_fname_base);
5369 return status;
5372 /****************************************************************************
5373 Deal with setting the size from any of the setfilepathinfo functions.
5374 ****************************************************************************/
5376 static NTSTATUS smb_set_file_size(connection_struct *conn,
5377 struct smb_request *req,
5378 files_struct *fsp,
5379 const struct smb_filename *smb_fname,
5380 const SMB_STRUCT_STAT *psbuf,
5381 SMB_OFF_T size)
5383 NTSTATUS status = NT_STATUS_OK;
5384 struct smb_filename *smb_fname_tmp = NULL;
5385 files_struct *new_fsp = NULL;
5387 if (!VALID_STAT(*psbuf)) {
5388 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5391 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5393 if (size == get_file_size_stat(psbuf)) {
5394 return NT_STATUS_OK;
5397 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5398 smb_fname_str_dbg(smb_fname), (double)size));
5400 if (fsp && fsp->fh->fd != -1) {
5401 /* Handle based call. */
5402 if (vfs_set_filelen(fsp, size) == -1) {
5403 return map_nt_error_from_unix(errno);
5405 trigger_write_time_update_immediate(fsp);
5406 return NT_STATUS_OK;
5409 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5410 if (!NT_STATUS_IS_OK(status)) {
5411 return status;
5414 smb_fname_tmp->st = *psbuf;
5416 status = SMB_VFS_CREATE_FILE(
5417 conn, /* conn */
5418 req, /* req */
5419 0, /* root_dir_fid */
5420 smb_fname_tmp, /* fname */
5421 FILE_WRITE_ATTRIBUTES, /* access_mask */
5422 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5423 FILE_SHARE_DELETE),
5424 FILE_OPEN, /* create_disposition*/
5425 0, /* create_options */
5426 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5427 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5428 0, /* allocation_size */
5429 NULL, /* sd */
5430 NULL, /* ea_list */
5431 &new_fsp, /* result */
5432 NULL); /* pinfo */
5434 TALLOC_FREE(smb_fname_tmp);
5436 if (!NT_STATUS_IS_OK(status)) {
5437 /* NB. We check for open_was_deferred in the caller. */
5438 return status;
5441 if (vfs_set_filelen(new_fsp, size) == -1) {
5442 status = map_nt_error_from_unix(errno);
5443 close_file(req, new_fsp,NORMAL_CLOSE);
5444 return status;
5447 trigger_write_time_update_immediate(new_fsp);
5448 close_file(req, new_fsp,NORMAL_CLOSE);
5449 return NT_STATUS_OK;
5452 /****************************************************************************
5453 Deal with SMB_INFO_SET_EA.
5454 ****************************************************************************/
5456 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5457 const char *pdata,
5458 int total_data,
5459 files_struct *fsp,
5460 const struct smb_filename *smb_fname)
5462 struct ea_list *ea_list = NULL;
5463 TALLOC_CTX *ctx = NULL;
5464 NTSTATUS status = NT_STATUS_OK;
5466 if (total_data < 10) {
5468 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5469 length. They seem to have no effect. Bug #3212. JRA */
5471 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5472 /* We're done. We only get EA info in this call. */
5473 return NT_STATUS_OK;
5476 return NT_STATUS_INVALID_PARAMETER;
5479 if (IVAL(pdata,0) > total_data) {
5480 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5481 IVAL(pdata,0), (unsigned int)total_data));
5482 return NT_STATUS_INVALID_PARAMETER;
5485 ctx = talloc_tos();
5486 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5487 if (!ea_list) {
5488 return NT_STATUS_INVALID_PARAMETER;
5490 status = set_ea(conn, fsp, smb_fname, ea_list);
5492 return status;
5495 /****************************************************************************
5496 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5497 ****************************************************************************/
5499 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5500 const char *pdata,
5501 int total_data,
5502 files_struct *fsp,
5503 const struct smb_filename *smb_fname)
5505 NTSTATUS status = NT_STATUS_OK;
5506 bool delete_on_close;
5507 uint32 dosmode = 0;
5509 if (total_data < 1) {
5510 return NT_STATUS_INVALID_PARAMETER;
5513 if (fsp == NULL) {
5514 return NT_STATUS_INVALID_HANDLE;
5517 delete_on_close = (CVAL(pdata,0) ? True : False);
5518 dosmode = dos_mode(conn, smb_fname);
5520 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5521 "delete_on_close = %u\n",
5522 smb_fname_str_dbg(smb_fname),
5523 (unsigned int)dosmode,
5524 (unsigned int)delete_on_close ));
5526 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5528 if (!NT_STATUS_IS_OK(status)) {
5529 return status;
5532 /* The set is across all open files on this dev/inode pair. */
5533 if (!set_delete_on_close(fsp, delete_on_close,
5534 &conn->server_info->utok)) {
5535 return NT_STATUS_ACCESS_DENIED;
5537 return NT_STATUS_OK;
5540 /****************************************************************************
5541 Deal with SMB_FILE_POSITION_INFORMATION.
5542 ****************************************************************************/
5544 static NTSTATUS smb_file_position_information(connection_struct *conn,
5545 const char *pdata,
5546 int total_data,
5547 files_struct *fsp)
5549 uint64_t position_information;
5551 if (total_data < 8) {
5552 return NT_STATUS_INVALID_PARAMETER;
5555 if (fsp == NULL) {
5556 /* Ignore on pathname based set. */
5557 return NT_STATUS_OK;
5560 position_information = (uint64_t)IVAL(pdata,0);
5561 #ifdef LARGE_SMB_OFF_T
5562 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5563 #else /* LARGE_SMB_OFF_T */
5564 if (IVAL(pdata,4) != 0) {
5565 /* more than 32 bits? */
5566 return NT_STATUS_INVALID_PARAMETER;
5568 #endif /* LARGE_SMB_OFF_T */
5570 DEBUG(10,("smb_file_position_information: Set file position "
5571 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5572 (double)position_information));
5573 fsp->fh->position_information = position_information;
5574 return NT_STATUS_OK;
5577 /****************************************************************************
5578 Deal with SMB_FILE_MODE_INFORMATION.
5579 ****************************************************************************/
5581 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5582 const char *pdata,
5583 int total_data)
5585 uint32 mode;
5587 if (total_data < 4) {
5588 return NT_STATUS_INVALID_PARAMETER;
5590 mode = IVAL(pdata,0);
5591 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5592 return NT_STATUS_INVALID_PARAMETER;
5594 return NT_STATUS_OK;
5597 /****************************************************************************
5598 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5599 ****************************************************************************/
5601 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5602 struct smb_request *req,
5603 const char *pdata,
5604 int total_data,
5605 const struct smb_filename *smb_fname)
5607 char *link_target = NULL;
5608 const char *newname = smb_fname->base_name;
5609 NTSTATUS status = NT_STATUS_OK;
5610 TALLOC_CTX *ctx = talloc_tos();
5612 /* Set a symbolic link. */
5613 /* Don't allow this if follow links is false. */
5615 if (total_data == 0) {
5616 return NT_STATUS_INVALID_PARAMETER;
5619 if (!lp_symlinks(SNUM(conn))) {
5620 return NT_STATUS_ACCESS_DENIED;
5623 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5624 total_data, STR_TERMINATE);
5626 if (!link_target) {
5627 return NT_STATUS_INVALID_PARAMETER;
5630 /* !widelinks forces the target path to be within the share. */
5631 /* This means we can interpret the target as a pathname. */
5632 if (!lp_widelinks(SNUM(conn))) {
5633 char *rel_name = NULL;
5634 char *last_dirp = NULL;
5636 if (*link_target == '/') {
5637 /* No absolute paths allowed. */
5638 return NT_STATUS_ACCESS_DENIED;
5640 rel_name = talloc_strdup(ctx,newname);
5641 if (!rel_name) {
5642 return NT_STATUS_NO_MEMORY;
5644 last_dirp = strrchr_m(rel_name, '/');
5645 if (last_dirp) {
5646 last_dirp[1] = '\0';
5647 } else {
5648 rel_name = talloc_strdup(ctx,"./");
5649 if (!rel_name) {
5650 return NT_STATUS_NO_MEMORY;
5653 rel_name = talloc_asprintf_append(rel_name,
5654 "%s",
5655 link_target);
5656 if (!rel_name) {
5657 return NT_STATUS_NO_MEMORY;
5660 status = check_name(conn, rel_name);
5661 if (!NT_STATUS_IS_OK(status)) {
5662 return status;
5666 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5667 newname, link_target ));
5669 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5670 return map_nt_error_from_unix(errno);
5673 return NT_STATUS_OK;
5676 /****************************************************************************
5677 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5678 ****************************************************************************/
5680 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5681 struct smb_request *req,
5682 const char *pdata, int total_data,
5683 const struct smb_filename *smb_fname_new)
5685 char *oldname = NULL;
5686 struct smb_filename *smb_fname_old = NULL;
5687 TALLOC_CTX *ctx = talloc_tos();
5688 NTSTATUS status = NT_STATUS_OK;
5690 /* Set a hard link. */
5691 if (total_data == 0) {
5692 return NT_STATUS_INVALID_PARAMETER;
5695 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5696 total_data, STR_TERMINATE, &status);
5697 if (!NT_STATUS_IS_OK(status)) {
5698 return status;
5701 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5702 smb_fname_str_dbg(smb_fname_new), oldname));
5704 status = filename_convert(ctx,
5705 conn,
5706 req->flags2 & FLAGS2_DFS_PATHNAMES,
5707 oldname,
5709 NULL,
5710 &smb_fname_old);
5711 if (!NT_STATUS_IS_OK(status)) {
5712 return status;
5715 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5718 /****************************************************************************
5719 Deal with SMB_FILE_RENAME_INFORMATION.
5720 ****************************************************************************/
5722 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5723 struct smb_request *req,
5724 const char *pdata,
5725 int total_data,
5726 files_struct *fsp,
5727 struct smb_filename *smb_fname_src)
5729 bool overwrite;
5730 uint32 root_fid;
5731 uint32 len;
5732 char *newname = NULL;
5733 struct smb_filename *smb_fname_dst = NULL;
5734 bool dest_has_wcard = False;
5735 NTSTATUS status = NT_STATUS_OK;
5736 char *p;
5737 TALLOC_CTX *ctx = talloc_tos();
5739 if (total_data < 13) {
5740 return NT_STATUS_INVALID_PARAMETER;
5743 overwrite = (CVAL(pdata,0) ? True : False);
5744 root_fid = IVAL(pdata,4);
5745 len = IVAL(pdata,8);
5747 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5748 return NT_STATUS_INVALID_PARAMETER;
5751 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5752 len, 0, &status,
5753 &dest_has_wcard);
5754 if (!NT_STATUS_IS_OK(status)) {
5755 return status;
5758 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5759 newname));
5761 status = resolve_dfspath_wcard(ctx, conn,
5762 req->flags2 & FLAGS2_DFS_PATHNAMES,
5763 newname,
5764 &newname,
5765 &dest_has_wcard);
5766 if (!NT_STATUS_IS_OK(status)) {
5767 return status;
5770 /* Check the new name has no '/' characters. */
5771 if (strchr_m(newname, '/')) {
5772 return NT_STATUS_NOT_SUPPORTED;
5775 if (fsp && fsp->base_fsp) {
5776 /* newname must be a stream name. */
5777 if (newname[0] != ':') {
5778 return NT_STATUS_NOT_SUPPORTED;
5781 /* Create an smb_fname to call rename_internals_fsp() with. */
5782 status = create_synthetic_smb_fname(talloc_tos(),
5783 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5784 &smb_fname_dst);
5785 if (!NT_STATUS_IS_OK(status)) {
5786 goto out;
5790 * Set the original last component, since
5791 * rename_internals_fsp() requires it.
5793 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5794 newname);
5795 if (smb_fname_dst->original_lcomp == NULL) {
5796 status = NT_STATUS_NO_MEMORY;
5797 goto out;
5800 } else {
5802 * Build up an smb_fname_dst based on the filename passed in.
5803 * We basically just strip off the last component, and put on
5804 * the newname instead.
5806 char *base_name = NULL;
5808 /* newname must *not* be a stream name. */
5809 if (newname[0] == ':') {
5810 return NT_STATUS_NOT_SUPPORTED;
5814 * Strip off the last component (filename) of the path passed
5815 * in.
5817 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5818 if (!base_name) {
5819 return NT_STATUS_NO_MEMORY;
5821 p = strrchr_m(base_name, '/');
5822 if (p) {
5823 p[1] = '\0';
5824 } else {
5825 base_name = talloc_strdup(ctx, "./");
5826 if (!base_name) {
5827 return NT_STATUS_NO_MEMORY;
5830 /* Append the new name. */
5831 base_name = talloc_asprintf_append(base_name,
5832 "%s",
5833 newname);
5834 if (!base_name) {
5835 return NT_STATUS_NO_MEMORY;
5838 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
5839 (UCF_SAVE_LCOMP |
5840 (dest_has_wcard ?
5841 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
5842 0)));
5844 /* If an error we expect this to be
5845 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5847 if (!NT_STATUS_IS_OK(status)) {
5848 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5849 status)) {
5850 goto out;
5852 /* Create an smb_fname to call rename_internals_fsp() */
5853 status = create_synthetic_smb_fname(ctx,
5854 base_name, NULL,
5855 NULL,
5856 &smb_fname_dst);
5857 if (!NT_STATUS_IS_OK(status)) {
5858 goto out;
5863 if (fsp) {
5864 DEBUG(10,("smb_file_rename_information: "
5865 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5866 fsp->fnum, fsp_str_dbg(fsp),
5867 smb_fname_str_dbg(smb_fname_dst)));
5868 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
5869 overwrite);
5870 } else {
5871 DEBUG(10,("smb_file_rename_information: "
5872 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5873 smb_fname_str_dbg(smb_fname_src),
5874 smb_fname_str_dbg(smb_fname_dst)));
5875 status = rename_internals(ctx, conn, req, smb_fname_src,
5876 smb_fname_dst, 0, overwrite, false,
5877 dest_has_wcard,
5878 FILE_WRITE_ATTRIBUTES);
5880 out:
5881 TALLOC_FREE(smb_fname_dst);
5882 return status;
5885 /****************************************************************************
5886 Deal with SMB_SET_POSIX_ACL.
5887 ****************************************************************************/
5889 #if defined(HAVE_POSIX_ACLS)
5890 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5891 const char *pdata,
5892 int total_data,
5893 files_struct *fsp,
5894 const struct smb_filename *smb_fname)
5896 uint16 posix_acl_version;
5897 uint16 num_file_acls;
5898 uint16 num_def_acls;
5899 bool valid_file_acls = True;
5900 bool valid_def_acls = True;
5902 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5903 return NT_STATUS_INVALID_PARAMETER;
5905 posix_acl_version = SVAL(pdata,0);
5906 num_file_acls = SVAL(pdata,2);
5907 num_def_acls = SVAL(pdata,4);
5909 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5910 valid_file_acls = False;
5911 num_file_acls = 0;
5914 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5915 valid_def_acls = False;
5916 num_def_acls = 0;
5919 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5920 return NT_STATUS_INVALID_PARAMETER;
5923 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5924 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5925 return NT_STATUS_INVALID_PARAMETER;
5928 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5929 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
5930 (unsigned int)num_file_acls,
5931 (unsigned int)num_def_acls));
5933 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
5934 smb_fname->base_name, num_file_acls,
5935 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5936 return map_nt_error_from_unix(errno);
5939 if (valid_def_acls && !set_unix_posix_default_acl(conn,
5940 smb_fname->base_name, &smb_fname->st, num_def_acls,
5941 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5942 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5943 return map_nt_error_from_unix(errno);
5945 return NT_STATUS_OK;
5947 #endif
5949 /****************************************************************************
5950 Deal with SMB_SET_POSIX_LOCK.
5951 ****************************************************************************/
5953 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5954 struct smb_request *req,
5955 const char *pdata,
5956 int total_data,
5957 files_struct *fsp)
5959 uint64_t count;
5960 uint64_t offset;
5961 uint32 lock_pid;
5962 bool blocking_lock = False;
5963 enum brl_type lock_type;
5965 NTSTATUS status = NT_STATUS_OK;
5967 if (fsp == NULL || fsp->fh->fd == -1) {
5968 return NT_STATUS_INVALID_HANDLE;
5971 if (total_data != POSIX_LOCK_DATA_SIZE) {
5972 return NT_STATUS_INVALID_PARAMETER;
5975 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5976 case POSIX_LOCK_TYPE_READ:
5977 lock_type = READ_LOCK;
5978 break;
5979 case POSIX_LOCK_TYPE_WRITE:
5980 /* Return the right POSIX-mappable error code for files opened read-only. */
5981 if (!fsp->can_write) {
5982 return NT_STATUS_INVALID_HANDLE;
5984 lock_type = WRITE_LOCK;
5985 break;
5986 case POSIX_LOCK_TYPE_UNLOCK:
5987 lock_type = UNLOCK_LOCK;
5988 break;
5989 default:
5990 return NT_STATUS_INVALID_PARAMETER;
5993 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5994 blocking_lock = False;
5995 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5996 blocking_lock = True;
5997 } else {
5998 return NT_STATUS_INVALID_PARAMETER;
6001 if (!lp_blocking_locks(SNUM(conn))) {
6002 blocking_lock = False;
6005 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6006 #if defined(HAVE_LONGLONG)
6007 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6008 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6009 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6010 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6011 #else /* HAVE_LONGLONG */
6012 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6013 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6014 #endif /* HAVE_LONGLONG */
6016 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6017 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6018 fsp_str_dbg(fsp),
6019 (unsigned int)lock_type,
6020 (unsigned int)lock_pid,
6021 (double)count,
6022 (double)offset ));
6024 if (lock_type == UNLOCK_LOCK) {
6025 status = do_unlock(smbd_messaging_context(),
6026 fsp,
6027 lock_pid,
6028 count,
6029 offset,
6030 POSIX_LOCK);
6031 } else {
6032 uint32 block_smbpid;
6034 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6035 fsp,
6036 lock_pid,
6037 count,
6038 offset,
6039 lock_type,
6040 POSIX_LOCK,
6041 blocking_lock,
6042 &status,
6043 &block_smbpid,
6044 NULL);
6046 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6048 * A blocking lock was requested. Package up
6049 * this smb into a queued request and push it
6050 * onto the blocking lock queue.
6052 if(push_blocking_lock_request(br_lck,
6053 req,
6054 fsp,
6055 -1, /* infinite timeout. */
6057 lock_pid,
6058 lock_type,
6059 POSIX_LOCK,
6060 offset,
6061 count,
6062 block_smbpid)) {
6063 TALLOC_FREE(br_lck);
6064 return status;
6067 TALLOC_FREE(br_lck);
6070 return status;
6073 /****************************************************************************
6074 Deal with SMB_SET_FILE_BASIC_INFO.
6075 ****************************************************************************/
6077 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6078 const char *pdata,
6079 int total_data,
6080 files_struct *fsp,
6081 const struct smb_filename *smb_fname)
6083 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6084 struct smb_file_time ft;
6085 uint32 dosmode = 0;
6086 NTSTATUS status = NT_STATUS_OK;
6088 ZERO_STRUCT(ft);
6090 if (total_data < 36) {
6091 return NT_STATUS_INVALID_PARAMETER;
6094 /* Set the attributes */
6095 dosmode = IVAL(pdata,32);
6096 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6097 if (!NT_STATUS_IS_OK(status)) {
6098 return status;
6101 /* create time */
6102 ft.create_time = interpret_long_date(pdata);
6104 /* access time */
6105 ft.atime = interpret_long_date(pdata+8);
6107 /* write time. */
6108 ft.mtime = interpret_long_date(pdata+16);
6110 /* change time. */
6111 ft.ctime = interpret_long_date(pdata+24);
6113 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6114 smb_fname_str_dbg(smb_fname)));
6116 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6117 true);
6120 /****************************************************************************
6121 Deal with SMB_INFO_STANDARD.
6122 ****************************************************************************/
6124 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6125 const char *pdata,
6126 int total_data,
6127 files_struct *fsp,
6128 const struct smb_filename *smb_fname)
6130 struct smb_file_time ft;
6132 ZERO_STRUCT(ft);
6134 if (total_data < 12) {
6135 return NT_STATUS_INVALID_PARAMETER;
6138 /* create time */
6139 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6140 /* access time */
6141 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6142 /* write time */
6143 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6145 DEBUG(10,("smb_set_info_standard: file %s\n",
6146 smb_fname_str_dbg(smb_fname)));
6148 return smb_set_file_time(conn,
6149 fsp,
6150 smb_fname,
6151 &ft,
6152 true);
6155 /****************************************************************************
6156 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6157 ****************************************************************************/
6159 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6160 struct smb_request *req,
6161 const char *pdata,
6162 int total_data,
6163 files_struct *fsp,
6164 struct smb_filename *smb_fname)
6166 uint64_t allocation_size = 0;
6167 NTSTATUS status = NT_STATUS_OK;
6168 files_struct *new_fsp = NULL;
6170 if (!VALID_STAT(smb_fname->st)) {
6171 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6174 if (total_data < 8) {
6175 return NT_STATUS_INVALID_PARAMETER;
6178 allocation_size = (uint64_t)IVAL(pdata,0);
6179 #ifdef LARGE_SMB_OFF_T
6180 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6181 #else /* LARGE_SMB_OFF_T */
6182 if (IVAL(pdata,4) != 0) {
6183 /* more than 32 bits? */
6184 return NT_STATUS_INVALID_PARAMETER;
6186 #endif /* LARGE_SMB_OFF_T */
6188 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6189 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6190 (double)allocation_size));
6192 if (allocation_size) {
6193 allocation_size = smb_roundup(conn, allocation_size);
6196 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6197 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6198 (double)allocation_size));
6200 if (fsp && fsp->fh->fd != -1) {
6201 /* Open file handle. */
6202 /* Only change if needed. */
6203 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6204 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6205 return map_nt_error_from_unix(errno);
6208 /* But always update the time. */
6210 * This is equivalent to a write. Ensure it's seen immediately
6211 * if there are no pending writes.
6213 trigger_write_time_update_immediate(fsp);
6214 return NT_STATUS_OK;
6217 /* Pathname or stat or directory file. */
6218 status = SMB_VFS_CREATE_FILE(
6219 conn, /* conn */
6220 req, /* req */
6221 0, /* root_dir_fid */
6222 smb_fname, /* fname */
6223 FILE_WRITE_DATA, /* access_mask */
6224 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6225 FILE_SHARE_DELETE),
6226 FILE_OPEN, /* create_disposition*/
6227 0, /* create_options */
6228 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6229 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6230 0, /* allocation_size */
6231 NULL, /* sd */
6232 NULL, /* ea_list */
6233 &new_fsp, /* result */
6234 NULL); /* pinfo */
6236 if (!NT_STATUS_IS_OK(status)) {
6237 /* NB. We check for open_was_deferred in the caller. */
6238 return status;
6241 /* Only change if needed. */
6242 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6243 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6244 status = map_nt_error_from_unix(errno);
6245 close_file(req, new_fsp, NORMAL_CLOSE);
6246 return status;
6250 /* Changing the allocation size should set the last mod time. */
6252 * This is equivalent to a write. Ensure it's seen immediately
6253 * if there are no pending writes.
6255 trigger_write_time_update_immediate(new_fsp);
6257 close_file(req, new_fsp, NORMAL_CLOSE);
6258 return NT_STATUS_OK;
6261 /****************************************************************************
6262 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6263 ****************************************************************************/
6265 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6266 struct smb_request *req,
6267 const char *pdata,
6268 int total_data,
6269 files_struct *fsp,
6270 const struct smb_filename *smb_fname)
6272 SMB_OFF_T size;
6274 if (total_data < 8) {
6275 return NT_STATUS_INVALID_PARAMETER;
6278 size = IVAL(pdata,0);
6279 #ifdef LARGE_SMB_OFF_T
6280 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6281 #else /* LARGE_SMB_OFF_T */
6282 if (IVAL(pdata,4) != 0) {
6283 /* more than 32 bits? */
6284 return NT_STATUS_INVALID_PARAMETER;
6286 #endif /* LARGE_SMB_OFF_T */
6287 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6288 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6289 (double)size));
6291 return smb_set_file_size(conn, req,
6292 fsp,
6293 smb_fname,
6294 &smb_fname->st,
6295 size);
6298 /****************************************************************************
6299 Allow a UNIX info mknod.
6300 ****************************************************************************/
6302 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6303 const char *pdata,
6304 int total_data,
6305 const struct smb_filename *smb_fname)
6307 uint32 file_type = IVAL(pdata,56);
6308 #if defined(HAVE_MAKEDEV)
6309 uint32 dev_major = IVAL(pdata,60);
6310 uint32 dev_minor = IVAL(pdata,68);
6311 #endif
6312 SMB_DEV_T dev = (SMB_DEV_T)0;
6313 uint32 raw_unixmode = IVAL(pdata,84);
6314 NTSTATUS status;
6315 mode_t unixmode;
6317 if (total_data < 100) {
6318 return NT_STATUS_INVALID_PARAMETER;
6321 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6322 PERM_NEW_FILE, &unixmode);
6323 if (!NT_STATUS_IS_OK(status)) {
6324 return status;
6327 #if defined(HAVE_MAKEDEV)
6328 dev = makedev(dev_major, dev_minor);
6329 #endif
6331 switch (file_type) {
6332 #if defined(S_IFIFO)
6333 case UNIX_TYPE_FIFO:
6334 unixmode |= S_IFIFO;
6335 break;
6336 #endif
6337 #if defined(S_IFSOCK)
6338 case UNIX_TYPE_SOCKET:
6339 unixmode |= S_IFSOCK;
6340 break;
6341 #endif
6342 #if defined(S_IFCHR)
6343 case UNIX_TYPE_CHARDEV:
6344 unixmode |= S_IFCHR;
6345 break;
6346 #endif
6347 #if defined(S_IFBLK)
6348 case UNIX_TYPE_BLKDEV:
6349 unixmode |= S_IFBLK;
6350 break;
6351 #endif
6352 default:
6353 return NT_STATUS_INVALID_PARAMETER;
6356 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6357 "%.0f mode 0%o for file %s\n", (double)dev,
6358 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6360 /* Ok - do the mknod. */
6361 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6362 return map_nt_error_from_unix(errno);
6365 /* If any of the other "set" calls fail we
6366 * don't want to end up with a half-constructed mknod.
6369 if (lp_inherit_perms(SNUM(conn))) {
6370 char *parent;
6371 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6372 &parent, NULL)) {
6373 return NT_STATUS_NO_MEMORY;
6375 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6376 unixmode);
6377 TALLOC_FREE(parent);
6380 return NT_STATUS_OK;
6383 /****************************************************************************
6384 Deal with SMB_SET_FILE_UNIX_BASIC.
6385 ****************************************************************************/
6387 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6388 struct smb_request *req,
6389 const char *pdata,
6390 int total_data,
6391 files_struct *fsp,
6392 const struct smb_filename *smb_fname)
6394 struct smb_file_time ft;
6395 uint32 raw_unixmode;
6396 mode_t unixmode;
6397 SMB_OFF_T size = 0;
6398 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6399 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6400 NTSTATUS status = NT_STATUS_OK;
6401 bool delete_on_fail = False;
6402 enum perm_type ptype;
6403 files_struct *all_fsps = NULL;
6404 bool modify_mtime = true;
6405 struct file_id id;
6406 SMB_STRUCT_STAT sbuf;
6408 ZERO_STRUCT(ft);
6410 if (total_data < 100) {
6411 return NT_STATUS_INVALID_PARAMETER;
6414 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6415 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6416 size=IVAL(pdata,0); /* first 8 Bytes are size */
6417 #ifdef LARGE_SMB_OFF_T
6418 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6419 #else /* LARGE_SMB_OFF_T */
6420 if (IVAL(pdata,4) != 0) {
6421 /* more than 32 bits? */
6422 return NT_STATUS_INVALID_PARAMETER;
6424 #endif /* LARGE_SMB_OFF_T */
6427 ft.atime = interpret_long_date(pdata+24); /* access_time */
6428 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6429 set_owner = (uid_t)IVAL(pdata,40);
6430 set_grp = (gid_t)IVAL(pdata,48);
6431 raw_unixmode = IVAL(pdata,84);
6433 if (VALID_STAT(smb_fname->st)) {
6434 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6435 ptype = PERM_EXISTING_DIR;
6436 } else {
6437 ptype = PERM_EXISTING_FILE;
6439 } else {
6440 ptype = PERM_NEW_FILE;
6443 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6444 ptype, &unixmode);
6445 if (!NT_STATUS_IS_OK(status)) {
6446 return status;
6449 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6450 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6451 smb_fname_str_dbg(smb_fname), (double)size,
6452 (unsigned int)set_owner, (unsigned int)set_grp,
6453 (int)raw_unixmode));
6455 sbuf = smb_fname->st;
6457 if (!VALID_STAT(sbuf)) {
6458 struct smb_filename *smb_fname_tmp = NULL;
6460 * The only valid use of this is to create character and block
6461 * devices, and named pipes. This is deprecated (IMHO) and
6462 * a new info level should be used for mknod. JRA.
6465 status = smb_unix_mknod(conn,
6466 pdata,
6467 total_data,
6468 smb_fname);
6469 if (!NT_STATUS_IS_OK(status)) {
6470 return status;
6473 status = copy_smb_filename(talloc_tos(), smb_fname,
6474 &smb_fname_tmp);
6475 if (!NT_STATUS_IS_OK(status)) {
6476 return status;
6479 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6480 status = map_nt_error_from_unix(errno);
6481 TALLOC_FREE(smb_fname_tmp);
6482 SMB_VFS_UNLINK(conn, smb_fname);
6483 return status;
6486 sbuf = smb_fname_tmp->st;
6487 TALLOC_FREE(smb_fname_tmp);
6489 /* Ensure we don't try and change anything else. */
6490 raw_unixmode = SMB_MODE_NO_CHANGE;
6491 size = get_file_size_stat(&sbuf);
6492 ft.atime = sbuf.st_ex_atime;
6493 ft.mtime = sbuf.st_ex_mtime;
6495 * We continue here as we might want to change the
6496 * owner uid/gid.
6498 delete_on_fail = True;
6501 #if 1
6502 /* Horrible backwards compatibility hack as an old server bug
6503 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6504 * */
6506 if (!size) {
6507 size = get_file_size_stat(&sbuf);
6509 #endif
6512 * Deal with the UNIX specific mode set.
6515 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6516 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6517 "setting mode 0%o for file %s\n",
6518 (unsigned int)unixmode,
6519 smb_fname_str_dbg(smb_fname)));
6520 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6521 return map_nt_error_from_unix(errno);
6526 * Deal with the UNIX specific uid set.
6529 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6530 (sbuf.st_ex_uid != set_owner)) {
6531 int ret;
6533 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6534 "changing owner %u for path %s\n",
6535 (unsigned int)set_owner,
6536 smb_fname_str_dbg(smb_fname)));
6538 if (S_ISLNK(sbuf.st_ex_mode)) {
6539 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6540 set_owner, (gid_t)-1);
6541 } else {
6542 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6543 set_owner, (gid_t)-1);
6546 if (ret != 0) {
6547 status = map_nt_error_from_unix(errno);
6548 if (delete_on_fail) {
6549 SMB_VFS_UNLINK(conn, smb_fname);
6551 return status;
6556 * Deal with the UNIX specific gid set.
6559 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6560 (sbuf.st_ex_gid != set_grp)) {
6561 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6562 "changing group %u for file %s\n",
6563 (unsigned int)set_owner,
6564 smb_fname_str_dbg(smb_fname)));
6565 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6566 set_grp) != 0) {
6567 status = map_nt_error_from_unix(errno);
6568 if (delete_on_fail) {
6569 SMB_VFS_UNLINK(conn, smb_fname);
6571 return status;
6575 /* Deal with any size changes. */
6577 status = smb_set_file_size(conn, req,
6578 fsp,
6579 smb_fname,
6580 &sbuf,
6581 size);
6582 if (!NT_STATUS_IS_OK(status)) {
6583 return status;
6586 /* Deal with any time changes. */
6587 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6588 /* No change, don't cancel anything. */
6589 return status;
6592 id = vfs_file_id_from_sbuf(conn, &sbuf);
6593 for(all_fsps = file_find_di_first(id); all_fsps;
6594 all_fsps = file_find_di_next(all_fsps)) {
6596 * We're setting the time explicitly for UNIX.
6597 * Cancel any pending changes over all handles.
6599 all_fsps->update_write_time_on_close = false;
6600 TALLOC_FREE(all_fsps->update_write_time_event);
6604 * Override the "setting_write_time"
6605 * parameter here as it almost does what
6606 * we need. Just remember if we modified
6607 * mtime and send the notify ourselves.
6609 if (null_timespec(ft.mtime)) {
6610 modify_mtime = false;
6613 status = smb_set_file_time(conn,
6614 fsp,
6615 smb_fname,
6616 &ft,
6617 false);
6618 if (modify_mtime) {
6619 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6620 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6622 return status;
6625 /****************************************************************************
6626 Deal with SMB_SET_FILE_UNIX_INFO2.
6627 ****************************************************************************/
6629 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6630 struct smb_request *req,
6631 const char *pdata,
6632 int total_data,
6633 files_struct *fsp,
6634 const struct smb_filename *smb_fname)
6636 NTSTATUS status;
6637 uint32 smb_fflags;
6638 uint32 smb_fmask;
6640 if (total_data < 116) {
6641 return NT_STATUS_INVALID_PARAMETER;
6644 /* Start by setting all the fields that are common between UNIX_BASIC
6645 * and UNIX_INFO2.
6647 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6648 fsp, smb_fname);
6649 if (!NT_STATUS_IS_OK(status)) {
6650 return status;
6653 smb_fflags = IVAL(pdata, 108);
6654 smb_fmask = IVAL(pdata, 112);
6656 /* NB: We should only attempt to alter the file flags if the client
6657 * sends a non-zero mask.
6659 if (smb_fmask != 0) {
6660 int stat_fflags = 0;
6662 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6663 smb_fmask, &stat_fflags)) {
6664 /* Client asked to alter a flag we don't understand. */
6665 return NT_STATUS_INVALID_PARAMETER;
6668 if (fsp && fsp->fh->fd != -1) {
6669 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6670 return NT_STATUS_NOT_SUPPORTED;
6671 } else {
6672 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6673 stat_fflags) != 0) {
6674 return map_nt_error_from_unix(errno);
6679 /* XXX: need to add support for changing the create_time here. You
6680 * can do this for paths on Darwin with setattrlist(2). The right way
6681 * to hook this up is probably by extending the VFS utimes interface.
6684 return NT_STATUS_OK;
6687 /****************************************************************************
6688 Create a directory with POSIX semantics.
6689 ****************************************************************************/
6691 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6692 struct smb_request *req,
6693 char **ppdata,
6694 int total_data,
6695 struct smb_filename *smb_fname,
6696 int *pdata_return_size)
6698 NTSTATUS status = NT_STATUS_OK;
6699 uint32 raw_unixmode = 0;
6700 uint32 mod_unixmode = 0;
6701 mode_t unixmode = (mode_t)0;
6702 files_struct *fsp = NULL;
6703 uint16 info_level_return = 0;
6704 int info;
6705 char *pdata = *ppdata;
6707 if (total_data < 18) {
6708 return NT_STATUS_INVALID_PARAMETER;
6711 raw_unixmode = IVAL(pdata,8);
6712 /* Next 4 bytes are not yet defined. */
6714 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6715 PERM_NEW_DIR, &unixmode);
6716 if (!NT_STATUS_IS_OK(status)) {
6717 return status;
6720 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6722 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6723 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6725 status = SMB_VFS_CREATE_FILE(
6726 conn, /* conn */
6727 req, /* req */
6728 0, /* root_dir_fid */
6729 smb_fname, /* fname */
6730 FILE_READ_ATTRIBUTES, /* access_mask */
6731 FILE_SHARE_NONE, /* share_access */
6732 FILE_CREATE, /* create_disposition*/
6733 FILE_DIRECTORY_FILE, /* create_options */
6734 mod_unixmode, /* file_attributes */
6735 0, /* oplock_request */
6736 0, /* allocation_size */
6737 NULL, /* sd */
6738 NULL, /* ea_list */
6739 &fsp, /* result */
6740 &info); /* pinfo */
6742 if (NT_STATUS_IS_OK(status)) {
6743 close_file(req, fsp, NORMAL_CLOSE);
6746 info_level_return = SVAL(pdata,16);
6748 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6749 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6750 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6751 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6752 } else {
6753 *pdata_return_size = 12;
6756 /* Realloc the data size */
6757 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6758 if (*ppdata == NULL) {
6759 *pdata_return_size = 0;
6760 return NT_STATUS_NO_MEMORY;
6762 pdata = *ppdata;
6764 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6765 SSVAL(pdata,2,0); /* No fnum. */
6766 SIVAL(pdata,4,info); /* Was directory created. */
6768 switch (info_level_return) {
6769 case SMB_QUERY_FILE_UNIX_BASIC:
6770 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6771 SSVAL(pdata,10,0); /* Padding. */
6772 store_file_unix_basic(conn, pdata + 12, fsp,
6773 &smb_fname->st);
6774 break;
6775 case SMB_QUERY_FILE_UNIX_INFO2:
6776 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6777 SSVAL(pdata,10,0); /* Padding. */
6778 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6779 &smb_fname->st);
6780 break;
6781 default:
6782 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6783 SSVAL(pdata,10,0); /* Padding. */
6784 break;
6787 return status;
6790 /****************************************************************************
6791 Open/Create a file with POSIX semantics.
6792 ****************************************************************************/
6794 static NTSTATUS smb_posix_open(connection_struct *conn,
6795 struct smb_request *req,
6796 char **ppdata,
6797 int total_data,
6798 struct smb_filename *smb_fname,
6799 int *pdata_return_size)
6801 bool extended_oplock_granted = False;
6802 char *pdata = *ppdata;
6803 uint32 flags = 0;
6804 uint32 wire_open_mode = 0;
6805 uint32 raw_unixmode = 0;
6806 uint32 mod_unixmode = 0;
6807 uint32 create_disp = 0;
6808 uint32 access_mask = 0;
6809 uint32 create_options = 0;
6810 NTSTATUS status = NT_STATUS_OK;
6811 mode_t unixmode = (mode_t)0;
6812 files_struct *fsp = NULL;
6813 int oplock_request = 0;
6814 int info = 0;
6815 uint16 info_level_return = 0;
6817 if (total_data < 18) {
6818 return NT_STATUS_INVALID_PARAMETER;
6821 flags = IVAL(pdata,0);
6822 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6823 if (oplock_request) {
6824 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6827 wire_open_mode = IVAL(pdata,4);
6829 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6830 return smb_posix_mkdir(conn, req,
6831 ppdata,
6832 total_data,
6833 smb_fname,
6834 pdata_return_size);
6837 switch (wire_open_mode & SMB_ACCMODE) {
6838 case SMB_O_RDONLY:
6839 access_mask = FILE_READ_DATA;
6840 break;
6841 case SMB_O_WRONLY:
6842 access_mask = FILE_WRITE_DATA;
6843 break;
6844 case SMB_O_RDWR:
6845 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6846 break;
6847 default:
6848 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6849 (unsigned int)wire_open_mode ));
6850 return NT_STATUS_INVALID_PARAMETER;
6853 wire_open_mode &= ~SMB_ACCMODE;
6855 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6856 create_disp = FILE_CREATE;
6857 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6858 create_disp = FILE_OVERWRITE_IF;
6859 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6860 create_disp = FILE_OPEN_IF;
6861 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6862 create_disp = FILE_OPEN;
6863 } else {
6864 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6865 (unsigned int)wire_open_mode ));
6866 return NT_STATUS_INVALID_PARAMETER;
6869 raw_unixmode = IVAL(pdata,8);
6870 /* Next 4 bytes are not yet defined. */
6872 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6873 (VALID_STAT(smb_fname->st) ?
6874 PERM_EXISTING_FILE : PERM_NEW_FILE),
6875 &unixmode);
6877 if (!NT_STATUS_IS_OK(status)) {
6878 return status;
6881 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6883 if (wire_open_mode & SMB_O_SYNC) {
6884 create_options |= FILE_WRITE_THROUGH;
6886 if (wire_open_mode & SMB_O_APPEND) {
6887 access_mask |= FILE_APPEND_DATA;
6889 if (wire_open_mode & SMB_O_DIRECT) {
6890 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6893 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6894 smb_fname_str_dbg(smb_fname),
6895 (unsigned int)wire_open_mode,
6896 (unsigned int)unixmode ));
6898 status = SMB_VFS_CREATE_FILE(
6899 conn, /* conn */
6900 req, /* req */
6901 0, /* root_dir_fid */
6902 smb_fname, /* fname */
6903 access_mask, /* access_mask */
6904 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6905 FILE_SHARE_DELETE),
6906 create_disp, /* create_disposition*/
6907 FILE_NON_DIRECTORY_FILE, /* create_options */
6908 mod_unixmode, /* file_attributes */
6909 oplock_request, /* oplock_request */
6910 0, /* allocation_size */
6911 NULL, /* sd */
6912 NULL, /* ea_list */
6913 &fsp, /* result */
6914 &info); /* pinfo */
6916 if (!NT_STATUS_IS_OK(status)) {
6917 return status;
6920 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6921 extended_oplock_granted = True;
6924 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6925 extended_oplock_granted = True;
6928 info_level_return = SVAL(pdata,16);
6930 /* Allocate the correct return size. */
6932 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6933 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6934 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6935 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6936 } else {
6937 *pdata_return_size = 12;
6940 /* Realloc the data size */
6941 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6942 if (*ppdata == NULL) {
6943 close_file(req, fsp, ERROR_CLOSE);
6944 *pdata_return_size = 0;
6945 return NT_STATUS_NO_MEMORY;
6947 pdata = *ppdata;
6949 if (extended_oplock_granted) {
6950 if (flags & REQUEST_BATCH_OPLOCK) {
6951 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6952 } else {
6953 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6955 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6956 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6957 } else {
6958 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6961 SSVAL(pdata,2,fsp->fnum);
6962 SIVAL(pdata,4,info); /* Was file created etc. */
6964 switch (info_level_return) {
6965 case SMB_QUERY_FILE_UNIX_BASIC:
6966 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6967 SSVAL(pdata,10,0); /* padding. */
6968 store_file_unix_basic(conn, pdata + 12, fsp,
6969 &smb_fname->st);
6970 break;
6971 case SMB_QUERY_FILE_UNIX_INFO2:
6972 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6973 SSVAL(pdata,10,0); /* padding. */
6974 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6975 &smb_fname->st);
6976 break;
6977 default:
6978 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6979 SSVAL(pdata,10,0); /* padding. */
6980 break;
6982 return NT_STATUS_OK;
6985 /****************************************************************************
6986 Delete a file with POSIX semantics.
6987 ****************************************************************************/
6989 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6990 struct smb_request *req,
6991 const char *pdata,
6992 int total_data,
6993 struct smb_filename *smb_fname)
6995 NTSTATUS status = NT_STATUS_OK;
6996 files_struct *fsp = NULL;
6997 uint16 flags = 0;
6998 char del = 1;
6999 int info = 0;
7000 int create_options = 0;
7001 int i;
7002 struct share_mode_lock *lck = NULL;
7004 if (total_data < 2) {
7005 return NT_STATUS_INVALID_PARAMETER;
7008 flags = SVAL(pdata,0);
7010 if (!VALID_STAT(smb_fname->st)) {
7011 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7014 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7015 !VALID_STAT_OF_DIR(smb_fname->st)) {
7016 return NT_STATUS_NOT_A_DIRECTORY;
7019 DEBUG(10,("smb_posix_unlink: %s %s\n",
7020 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7021 smb_fname_str_dbg(smb_fname)));
7023 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7024 create_options |= FILE_DIRECTORY_FILE;
7027 status = SMB_VFS_CREATE_FILE(
7028 conn, /* conn */
7029 req, /* req */
7030 0, /* root_dir_fid */
7031 smb_fname, /* fname */
7032 DELETE_ACCESS, /* access_mask */
7033 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7034 FILE_SHARE_DELETE),
7035 FILE_OPEN, /* create_disposition*/
7036 create_options, /* create_options */
7037 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7038 0, /* oplock_request */
7039 0, /* allocation_size */
7040 NULL, /* sd */
7041 NULL, /* ea_list */
7042 &fsp, /* result */
7043 &info); /* pinfo */
7045 if (!NT_STATUS_IS_OK(status)) {
7046 return status;
7050 * Don't lie to client. If we can't really delete due to
7051 * non-POSIX opens return SHARING_VIOLATION.
7054 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7055 NULL);
7056 if (lck == NULL) {
7057 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7058 "lock for file %s\n", fsp_str_dbg(fsp)));
7059 close_file(req, fsp, NORMAL_CLOSE);
7060 return NT_STATUS_INVALID_PARAMETER;
7064 * See if others still have the file open. If this is the case, then
7065 * don't delete. If all opens are POSIX delete we can set the delete
7066 * on close disposition.
7068 for (i=0; i<lck->num_share_modes; i++) {
7069 struct share_mode_entry *e = &lck->share_modes[i];
7070 if (is_valid_share_mode_entry(e)) {
7071 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7072 continue;
7074 /* Fail with sharing violation. */
7075 close_file(req, fsp, NORMAL_CLOSE);
7076 TALLOC_FREE(lck);
7077 return NT_STATUS_SHARING_VIOLATION;
7082 * Set the delete on close.
7084 status = smb_set_file_disposition_info(conn,
7085 &del,
7087 fsp,
7088 smb_fname);
7090 if (!NT_STATUS_IS_OK(status)) {
7091 close_file(req, fsp, NORMAL_CLOSE);
7092 TALLOC_FREE(lck);
7093 return status;
7095 TALLOC_FREE(lck);
7096 return close_file(req, fsp, NORMAL_CLOSE);
7099 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7100 struct smb_request *req,
7101 TALLOC_CTX *mem_ctx,
7102 uint16_t info_level,
7103 files_struct *fsp,
7104 struct smb_filename *smb_fname,
7105 char **ppdata, int total_data,
7106 int *ret_data_size)
7108 char *pdata = *ppdata;
7109 NTSTATUS status = NT_STATUS_OK;
7110 int data_return_size = 0;
7112 *ret_data_size = 0;
7114 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7115 return NT_STATUS_INVALID_LEVEL;
7118 if (!CAN_WRITE(conn)) {
7119 /* Allow POSIX opens. The open path will deny
7120 * any non-readonly opens. */
7121 if (info_level != SMB_POSIX_PATH_OPEN) {
7122 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7126 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7127 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7128 fsp ? fsp->fnum : -1, info_level, total_data));
7130 switch (info_level) {
7132 case SMB_INFO_STANDARD:
7134 status = smb_set_info_standard(conn,
7135 pdata,
7136 total_data,
7137 fsp,
7138 smb_fname);
7139 break;
7142 case SMB_INFO_SET_EA:
7144 status = smb_info_set_ea(conn,
7145 pdata,
7146 total_data,
7147 fsp,
7148 smb_fname);
7149 break;
7152 case SMB_SET_FILE_BASIC_INFO:
7153 case SMB_FILE_BASIC_INFORMATION:
7155 status = smb_set_file_basic_info(conn,
7156 pdata,
7157 total_data,
7158 fsp,
7159 smb_fname);
7160 break;
7163 case SMB_FILE_ALLOCATION_INFORMATION:
7164 case SMB_SET_FILE_ALLOCATION_INFO:
7166 status = smb_set_file_allocation_info(conn, req,
7167 pdata,
7168 total_data,
7169 fsp,
7170 smb_fname);
7171 break;
7174 case SMB_FILE_END_OF_FILE_INFORMATION:
7175 case SMB_SET_FILE_END_OF_FILE_INFO:
7177 status = smb_set_file_end_of_file_info(conn, req,
7178 pdata,
7179 total_data,
7180 fsp,
7181 smb_fname);
7182 break;
7185 case SMB_FILE_DISPOSITION_INFORMATION:
7186 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7188 #if 0
7189 /* JRA - We used to just ignore this on a path ?
7190 * Shouldn't this be invalid level on a pathname
7191 * based call ?
7193 if (tran_call != TRANSACT2_SETFILEINFO) {
7194 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7196 #endif
7197 status = smb_set_file_disposition_info(conn,
7198 pdata,
7199 total_data,
7200 fsp,
7201 smb_fname);
7202 break;
7205 case SMB_FILE_POSITION_INFORMATION:
7207 status = smb_file_position_information(conn,
7208 pdata,
7209 total_data,
7210 fsp);
7211 break;
7214 /* From tridge Samba4 :
7215 * MODE_INFORMATION in setfileinfo (I have no
7216 * idea what "mode information" on a file is - it takes a value of 0,
7217 * 2, 4 or 6. What could it be?).
7220 case SMB_FILE_MODE_INFORMATION:
7222 status = smb_file_mode_information(conn,
7223 pdata,
7224 total_data);
7225 break;
7229 * CIFS UNIX extensions.
7232 case SMB_SET_FILE_UNIX_BASIC:
7234 status = smb_set_file_unix_basic(conn, req,
7235 pdata,
7236 total_data,
7237 fsp,
7238 smb_fname);
7239 break;
7242 case SMB_SET_FILE_UNIX_INFO2:
7244 status = smb_set_file_unix_info2(conn, req,
7245 pdata,
7246 total_data,
7247 fsp,
7248 smb_fname);
7249 break;
7252 case SMB_SET_FILE_UNIX_LINK:
7254 if (fsp) {
7255 /* We must have a pathname for this. */
7256 return NT_STATUS_INVALID_LEVEL;
7258 status = smb_set_file_unix_link(conn, req, pdata,
7259 total_data, smb_fname);
7260 break;
7263 case SMB_SET_FILE_UNIX_HLINK:
7265 if (fsp) {
7266 /* We must have a pathname for this. */
7267 return NT_STATUS_INVALID_LEVEL;
7269 status = smb_set_file_unix_hlink(conn, req,
7270 pdata, total_data,
7271 smb_fname);
7272 break;
7275 case SMB_FILE_RENAME_INFORMATION:
7277 status = smb_file_rename_information(conn, req,
7278 pdata, total_data,
7279 fsp, smb_fname);
7280 break;
7283 #if defined(HAVE_POSIX_ACLS)
7284 case SMB_SET_POSIX_ACL:
7286 status = smb_set_posix_acl(conn,
7287 pdata,
7288 total_data,
7289 fsp,
7290 smb_fname);
7291 break;
7293 #endif
7295 case SMB_SET_POSIX_LOCK:
7297 if (!fsp) {
7298 return NT_STATUS_INVALID_LEVEL;
7300 status = smb_set_posix_lock(conn, req,
7301 pdata, total_data, fsp);
7302 break;
7305 case SMB_POSIX_PATH_OPEN:
7307 if (fsp) {
7308 /* We must have a pathname for this. */
7309 return NT_STATUS_INVALID_LEVEL;
7312 status = smb_posix_open(conn, req,
7313 ppdata,
7314 total_data,
7315 smb_fname,
7316 &data_return_size);
7317 break;
7320 case SMB_POSIX_PATH_UNLINK:
7322 if (fsp) {
7323 /* We must have a pathname for this. */
7324 return NT_STATUS_INVALID_LEVEL;
7327 status = smb_posix_unlink(conn, req,
7328 pdata,
7329 total_data,
7330 smb_fname);
7331 break;
7334 default:
7335 return NT_STATUS_INVALID_LEVEL;
7338 if (!NT_STATUS_IS_OK(status)) {
7339 return status;
7342 *ret_data_size = data_return_size;
7343 return NT_STATUS_OK;
7346 /****************************************************************************
7347 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7348 ****************************************************************************/
7350 static void call_trans2setfilepathinfo(connection_struct *conn,
7351 struct smb_request *req,
7352 unsigned int tran_call,
7353 char **pparams, int total_params,
7354 char **ppdata, int total_data,
7355 unsigned int max_data_bytes)
7357 char *params = *pparams;
7358 char *pdata = *ppdata;
7359 uint16 info_level;
7360 struct smb_filename *smb_fname = NULL;
7361 files_struct *fsp = NULL;
7362 NTSTATUS status = NT_STATUS_OK;
7363 int data_return_size = 0;
7365 if (!params) {
7366 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7367 return;
7370 if (tran_call == TRANSACT2_SETFILEINFO) {
7371 if (total_params < 4) {
7372 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7373 return;
7376 fsp = file_fsp(req, SVAL(params,0));
7377 /* Basic check for non-null fsp. */
7378 if (!check_fsp_open(conn, req, fsp)) {
7379 return;
7381 info_level = SVAL(params,2);
7383 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7384 &smb_fname);
7385 if (!NT_STATUS_IS_OK(status)) {
7386 reply_nterror(req, status);
7387 return;
7390 if(fsp->is_directory || fsp->fh->fd == -1) {
7392 * This is actually a SETFILEINFO on a directory
7393 * handle (returned from an NT SMB). NT5.0 seems
7394 * to do this call. JRA.
7396 if (INFO_LEVEL_IS_UNIX(info_level)) {
7397 /* Always do lstat for UNIX calls. */
7398 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7399 DEBUG(3,("call_trans2setfilepathinfo: "
7400 "SMB_VFS_LSTAT of %s failed "
7401 "(%s)\n",
7402 smb_fname_str_dbg(smb_fname),
7403 strerror(errno)));
7404 reply_nterror(req, map_nt_error_from_unix(errno));
7405 return;
7407 } else {
7408 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7409 DEBUG(3,("call_trans2setfilepathinfo: "
7410 "fileinfo of %s failed (%s)\n",
7411 smb_fname_str_dbg(smb_fname),
7412 strerror(errno)));
7413 reply_nterror(req, map_nt_error_from_unix(errno));
7414 return;
7417 } else if (fsp->print_file) {
7419 * Doing a DELETE_ON_CLOSE should cancel a print job.
7421 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7422 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7424 DEBUG(3,("call_trans2setfilepathinfo: "
7425 "Cancelling print job (%s)\n",
7426 fsp_str_dbg(fsp)));
7428 SSVAL(params,0,0);
7429 send_trans2_replies(conn, req, params, 2,
7430 *ppdata, 0,
7431 max_data_bytes);
7432 return;
7433 } else {
7434 reply_doserror(req, ERRDOS, ERRbadpath);
7435 return;
7437 } else {
7439 * Original code - this is an open file.
7441 if (!check_fsp(conn, req, fsp)) {
7442 return;
7445 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7446 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7447 "of fnum %d failed (%s)\n", fsp->fnum,
7448 strerror(errno)));
7449 reply_nterror(req, map_nt_error_from_unix(errno));
7450 return;
7453 } else {
7454 char *fname = NULL;
7456 /* set path info */
7457 if (total_params < 7) {
7458 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7459 return;
7462 info_level = SVAL(params,0);
7463 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7464 total_params - 6, STR_TERMINATE,
7465 &status);
7466 if (!NT_STATUS_IS_OK(status)) {
7467 reply_nterror(req, status);
7468 return;
7471 status = filename_convert(req, conn,
7472 req->flags2 & FLAGS2_DFS_PATHNAMES,
7473 fname,
7475 NULL,
7476 &smb_fname);
7477 if (!NT_STATUS_IS_OK(status)) {
7478 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7479 reply_botherror(req,
7480 NT_STATUS_PATH_NOT_COVERED,
7481 ERRSRV, ERRbadpath);
7482 return;
7484 reply_nterror(req, status);
7485 return;
7488 if (INFO_LEVEL_IS_UNIX(info_level)) {
7490 * For CIFS UNIX extensions the target name may not exist.
7493 /* Always do lstat for UNIX calls. */
7494 SMB_VFS_LSTAT(conn, smb_fname);
7496 } else if (!VALID_STAT(smb_fname->st) &&
7497 SMB_VFS_STAT(conn, smb_fname)) {
7498 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7499 "%s failed (%s)\n",
7500 smb_fname_str_dbg(smb_fname),
7501 strerror(errno)));
7502 reply_nterror(req, map_nt_error_from_unix(errno));
7503 return;
7507 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7508 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7509 fsp ? fsp->fnum : -1, info_level,total_data));
7511 /* Realloc the parameter size */
7512 *pparams = (char *)SMB_REALLOC(*pparams,2);
7513 if (*pparams == NULL) {
7514 reply_nterror(req, NT_STATUS_NO_MEMORY);
7515 return;
7517 params = *pparams;
7519 SSVAL(params,0,0);
7521 status = smbd_do_setfilepathinfo(conn, req, req,
7522 info_level,
7523 fsp,
7524 smb_fname,
7525 ppdata, total_data,
7526 &data_return_size);
7527 if (!NT_STATUS_IS_OK(status)) {
7528 if (open_was_deferred(req->mid)) {
7529 /* We have re-scheduled this call. */
7530 return;
7532 if (blocking_lock_was_deferred(req->mid)) {
7533 /* We have re-scheduled this call. */
7534 return;
7536 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7537 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7538 ERRSRV, ERRbadpath);
7539 return;
7541 if (info_level == SMB_POSIX_PATH_OPEN) {
7542 reply_openerror(req, status);
7543 return;
7546 reply_nterror(req, status);
7547 return;
7550 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7551 max_data_bytes);
7553 return;
7556 /****************************************************************************
7557 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7558 ****************************************************************************/
7560 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7561 char **pparams, int total_params,
7562 char **ppdata, int total_data,
7563 unsigned int max_data_bytes)
7565 struct smb_filename *smb_dname = NULL;
7566 char *params = *pparams;
7567 char *pdata = *ppdata;
7568 char *directory = NULL;
7569 NTSTATUS status = NT_STATUS_OK;
7570 struct ea_list *ea_list = NULL;
7571 TALLOC_CTX *ctx = talloc_tos();
7573 if (!CAN_WRITE(conn)) {
7574 reply_doserror(req, ERRSRV, ERRaccess);
7575 return;
7578 if (total_params < 5) {
7579 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7580 return;
7583 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7584 total_params - 4, STR_TERMINATE,
7585 &status);
7586 if (!NT_STATUS_IS_OK(status)) {
7587 reply_nterror(req, status);
7588 return;
7591 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7593 status = filename_convert(ctx,
7594 conn,
7595 req->flags2 & FLAGS2_DFS_PATHNAMES,
7596 directory,
7598 NULL,
7599 &smb_dname);
7601 if (!NT_STATUS_IS_OK(status)) {
7602 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7603 reply_botherror(req,
7604 NT_STATUS_PATH_NOT_COVERED,
7605 ERRSRV, ERRbadpath);
7606 return;
7608 reply_nterror(req, status);
7609 return;
7612 /* Any data in this call is an EA list. */
7613 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7614 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7615 goto out;
7619 * OS/2 workplace shell seems to send SET_EA requests of "null"
7620 * length (4 bytes containing IVAL 4).
7621 * They seem to have no effect. Bug #3212. JRA.
7624 if (total_data != 4) {
7625 if (total_data < 10) {
7626 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7627 goto out;
7630 if (IVAL(pdata,0) > total_data) {
7631 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7632 IVAL(pdata,0), (unsigned int)total_data));
7633 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7634 goto out;
7637 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7638 total_data - 4);
7639 if (!ea_list) {
7640 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7641 goto out;
7644 /* If total_data == 4 Windows doesn't care what values
7645 * are placed in that field, it just ignores them.
7646 * The System i QNTC IBM SMB client puts bad values here,
7647 * so ignore them. */
7649 status = create_directory(conn, req, smb_dname);
7651 if (!NT_STATUS_IS_OK(status)) {
7652 reply_nterror(req, status);
7653 goto out;
7656 /* Try and set any given EA. */
7657 if (ea_list) {
7658 status = set_ea(conn, NULL, smb_dname, ea_list);
7659 if (!NT_STATUS_IS_OK(status)) {
7660 reply_nterror(req, status);
7661 goto out;
7665 /* Realloc the parameter and data sizes */
7666 *pparams = (char *)SMB_REALLOC(*pparams,2);
7667 if(*pparams == NULL) {
7668 reply_nterror(req, NT_STATUS_NO_MEMORY);
7669 goto out;
7671 params = *pparams;
7673 SSVAL(params,0,0);
7675 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7677 out:
7678 TALLOC_FREE(smb_dname);
7679 return;
7682 /****************************************************************************
7683 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7684 We don't actually do this - we just send a null response.
7685 ****************************************************************************/
7687 static void call_trans2findnotifyfirst(connection_struct *conn,
7688 struct smb_request *req,
7689 char **pparams, int total_params,
7690 char **ppdata, int total_data,
7691 unsigned int max_data_bytes)
7693 char *params = *pparams;
7694 uint16 info_level;
7696 if (total_params < 6) {
7697 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7698 return;
7701 info_level = SVAL(params,4);
7702 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7704 switch (info_level) {
7705 case 1:
7706 case 2:
7707 break;
7708 default:
7709 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7710 return;
7713 /* Realloc the parameter and data sizes */
7714 *pparams = (char *)SMB_REALLOC(*pparams,6);
7715 if (*pparams == NULL) {
7716 reply_nterror(req, NT_STATUS_NO_MEMORY);
7717 return;
7719 params = *pparams;
7721 SSVAL(params,0,fnf_handle);
7722 SSVAL(params,2,0); /* No changes */
7723 SSVAL(params,4,0); /* No EA errors */
7725 fnf_handle++;
7727 if(fnf_handle == 0)
7728 fnf_handle = 257;
7730 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7732 return;
7735 /****************************************************************************
7736 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7737 changes). Currently this does nothing.
7738 ****************************************************************************/
7740 static void call_trans2findnotifynext(connection_struct *conn,
7741 struct smb_request *req,
7742 char **pparams, int total_params,
7743 char **ppdata, int total_data,
7744 unsigned int max_data_bytes)
7746 char *params = *pparams;
7748 DEBUG(3,("call_trans2findnotifynext\n"));
7750 /* Realloc the parameter and data sizes */
7751 *pparams = (char *)SMB_REALLOC(*pparams,4);
7752 if (*pparams == NULL) {
7753 reply_nterror(req, NT_STATUS_NO_MEMORY);
7754 return;
7756 params = *pparams;
7758 SSVAL(params,0,0); /* No changes */
7759 SSVAL(params,2,0); /* No EA errors */
7761 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7763 return;
7766 /****************************************************************************
7767 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7768 ****************************************************************************/
7770 static void call_trans2getdfsreferral(connection_struct *conn,
7771 struct smb_request *req,
7772 char **pparams, int total_params,
7773 char **ppdata, int total_data,
7774 unsigned int max_data_bytes)
7776 char *params = *pparams;
7777 char *pathname = NULL;
7778 int reply_size = 0;
7779 int max_referral_level;
7780 NTSTATUS status = NT_STATUS_OK;
7781 TALLOC_CTX *ctx = talloc_tos();
7783 DEBUG(10,("call_trans2getdfsreferral\n"));
7785 if (total_params < 3) {
7786 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7787 return;
7790 max_referral_level = SVAL(params,0);
7792 if(!lp_host_msdfs()) {
7793 reply_doserror(req, ERRDOS, ERRbadfunc);
7794 return;
7797 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7798 total_params - 2, STR_TERMINATE);
7799 if (!pathname) {
7800 reply_nterror(req, NT_STATUS_NOT_FOUND);
7801 return;
7803 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7804 ppdata,&status)) < 0) {
7805 reply_nterror(req, status);
7806 return;
7809 SSVAL(req->inbuf, smb_flg2,
7810 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7811 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7813 return;
7816 #define LMCAT_SPL 0x53
7817 #define LMFUNC_GETJOBID 0x60
7819 /****************************************************************************
7820 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7821 ****************************************************************************/
7823 static void call_trans2ioctl(connection_struct *conn,
7824 struct smb_request *req,
7825 char **pparams, int total_params,
7826 char **ppdata, int total_data,
7827 unsigned int max_data_bytes)
7829 char *pdata = *ppdata;
7830 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7832 /* check for an invalid fid before proceeding */
7834 if (!fsp) {
7835 reply_doserror(req, ERRDOS, ERRbadfid);
7836 return;
7839 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7840 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7841 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7842 if (*ppdata == NULL) {
7843 reply_nterror(req, NT_STATUS_NO_MEMORY);
7844 return;
7846 pdata = *ppdata;
7848 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7849 CAN ACCEPT THIS IN UNICODE. JRA. */
7851 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7852 srvstr_push(pdata, req->flags2, pdata + 2,
7853 global_myname(), 15,
7854 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7855 srvstr_push(pdata, req->flags2, pdata+18,
7856 lp_servicename(SNUM(conn)), 13,
7857 STR_ASCII|STR_TERMINATE); /* Service name */
7858 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7859 max_data_bytes);
7860 return;
7863 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7864 reply_doserror(req, ERRSRV, ERRerror);
7867 /****************************************************************************
7868 Reply to a SMBfindclose (stop trans2 directory search).
7869 ****************************************************************************/
7871 void reply_findclose(struct smb_request *req)
7873 int dptr_num;
7874 struct smbd_server_connection *sconn = smbd_server_conn;
7876 START_PROFILE(SMBfindclose);
7878 if (req->wct < 1) {
7879 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7880 END_PROFILE(SMBfindclose);
7881 return;
7884 dptr_num = SVALS(req->vwv+0, 0);
7886 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7888 dptr_close(sconn, &dptr_num);
7890 reply_outbuf(req, 0, 0);
7892 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7894 END_PROFILE(SMBfindclose);
7895 return;
7898 /****************************************************************************
7899 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7900 ****************************************************************************/
7902 void reply_findnclose(struct smb_request *req)
7904 int dptr_num;
7906 START_PROFILE(SMBfindnclose);
7908 if (req->wct < 1) {
7909 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7910 END_PROFILE(SMBfindnclose);
7911 return;
7914 dptr_num = SVAL(req->vwv+0, 0);
7916 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7918 /* We never give out valid handles for a
7919 findnotifyfirst - so any dptr_num is ok here.
7920 Just ignore it. */
7922 reply_outbuf(req, 0, 0);
7924 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7926 END_PROFILE(SMBfindnclose);
7927 return;
7930 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7931 struct trans_state *state)
7933 if (Protocol >= PROTOCOL_NT1) {
7934 req->flags2 |= 0x40; /* IS_LONG_NAME */
7935 SSVAL(req->inbuf,smb_flg2,req->flags2);
7938 if (conn->encrypt_level == Required && !req->encrypted) {
7939 if (state->call != TRANSACT2_QFSINFO &&
7940 state->call != TRANSACT2_SETFSINFO) {
7941 DEBUG(0,("handle_trans2: encryption required "
7942 "with call 0x%x\n",
7943 (unsigned int)state->call));
7944 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7945 return;
7949 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7951 /* Now we must call the relevant TRANS2 function */
7952 switch(state->call) {
7953 case TRANSACT2_OPEN:
7955 START_PROFILE(Trans2_open);
7956 call_trans2open(conn, req,
7957 &state->param, state->total_param,
7958 &state->data, state->total_data,
7959 state->max_data_return);
7960 END_PROFILE(Trans2_open);
7961 break;
7964 case TRANSACT2_FINDFIRST:
7966 START_PROFILE(Trans2_findfirst);
7967 call_trans2findfirst(conn, req,
7968 &state->param, state->total_param,
7969 &state->data, state->total_data,
7970 state->max_data_return);
7971 END_PROFILE(Trans2_findfirst);
7972 break;
7975 case TRANSACT2_FINDNEXT:
7977 START_PROFILE(Trans2_findnext);
7978 call_trans2findnext(conn, req,
7979 &state->param, state->total_param,
7980 &state->data, state->total_data,
7981 state->max_data_return);
7982 END_PROFILE(Trans2_findnext);
7983 break;
7986 case TRANSACT2_QFSINFO:
7988 START_PROFILE(Trans2_qfsinfo);
7989 call_trans2qfsinfo(conn, req,
7990 &state->param, state->total_param,
7991 &state->data, state->total_data,
7992 state->max_data_return);
7993 END_PROFILE(Trans2_qfsinfo);
7994 break;
7997 case TRANSACT2_SETFSINFO:
7999 START_PROFILE(Trans2_setfsinfo);
8000 call_trans2setfsinfo(conn, req,
8001 &state->param, state->total_param,
8002 &state->data, state->total_data,
8003 state->max_data_return);
8004 END_PROFILE(Trans2_setfsinfo);
8005 break;
8008 case TRANSACT2_QPATHINFO:
8009 case TRANSACT2_QFILEINFO:
8011 START_PROFILE(Trans2_qpathinfo);
8012 call_trans2qfilepathinfo(conn, req, state->call,
8013 &state->param, state->total_param,
8014 &state->data, state->total_data,
8015 state->max_data_return);
8016 END_PROFILE(Trans2_qpathinfo);
8017 break;
8020 case TRANSACT2_SETPATHINFO:
8021 case TRANSACT2_SETFILEINFO:
8023 START_PROFILE(Trans2_setpathinfo);
8024 call_trans2setfilepathinfo(conn, req, state->call,
8025 &state->param, state->total_param,
8026 &state->data, state->total_data,
8027 state->max_data_return);
8028 END_PROFILE(Trans2_setpathinfo);
8029 break;
8032 case TRANSACT2_FINDNOTIFYFIRST:
8034 START_PROFILE(Trans2_findnotifyfirst);
8035 call_trans2findnotifyfirst(conn, req,
8036 &state->param, state->total_param,
8037 &state->data, state->total_data,
8038 state->max_data_return);
8039 END_PROFILE(Trans2_findnotifyfirst);
8040 break;
8043 case TRANSACT2_FINDNOTIFYNEXT:
8045 START_PROFILE(Trans2_findnotifynext);
8046 call_trans2findnotifynext(conn, req,
8047 &state->param, state->total_param,
8048 &state->data, state->total_data,
8049 state->max_data_return);
8050 END_PROFILE(Trans2_findnotifynext);
8051 break;
8054 case TRANSACT2_MKDIR:
8056 START_PROFILE(Trans2_mkdir);
8057 call_trans2mkdir(conn, req,
8058 &state->param, state->total_param,
8059 &state->data, state->total_data,
8060 state->max_data_return);
8061 END_PROFILE(Trans2_mkdir);
8062 break;
8065 case TRANSACT2_GET_DFS_REFERRAL:
8067 START_PROFILE(Trans2_get_dfs_referral);
8068 call_trans2getdfsreferral(conn, req,
8069 &state->param, state->total_param,
8070 &state->data, state->total_data,
8071 state->max_data_return);
8072 END_PROFILE(Trans2_get_dfs_referral);
8073 break;
8076 case TRANSACT2_IOCTL:
8078 START_PROFILE(Trans2_ioctl);
8079 call_trans2ioctl(conn, req,
8080 &state->param, state->total_param,
8081 &state->data, state->total_data,
8082 state->max_data_return);
8083 END_PROFILE(Trans2_ioctl);
8084 break;
8087 default:
8088 /* Error in request */
8089 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8090 reply_doserror(req, ERRSRV,ERRerror);
8094 /****************************************************************************
8095 Reply to a SMBtrans2.
8096 ****************************************************************************/
8098 void reply_trans2(struct smb_request *req)
8100 connection_struct *conn = req->conn;
8101 unsigned int dsoff;
8102 unsigned int dscnt;
8103 unsigned int psoff;
8104 unsigned int pscnt;
8105 unsigned int tran_call;
8106 struct trans_state *state;
8107 NTSTATUS result;
8109 START_PROFILE(SMBtrans2);
8111 if (req->wct < 14) {
8112 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8113 END_PROFILE(SMBtrans2);
8114 return;
8117 dsoff = SVAL(req->vwv+12, 0);
8118 dscnt = SVAL(req->vwv+11, 0);
8119 psoff = SVAL(req->vwv+10, 0);
8120 pscnt = SVAL(req->vwv+9, 0);
8121 tran_call = SVAL(req->vwv+14, 0);
8123 result = allow_new_trans(conn->pending_trans, req->mid);
8124 if (!NT_STATUS_IS_OK(result)) {
8125 DEBUG(2, ("Got invalid trans2 request: %s\n",
8126 nt_errstr(result)));
8127 reply_nterror(req, result);
8128 END_PROFILE(SMBtrans2);
8129 return;
8132 if (IS_IPC(conn)) {
8133 switch (tran_call) {
8134 /* List the allowed trans2 calls on IPC$ */
8135 case TRANSACT2_OPEN:
8136 case TRANSACT2_GET_DFS_REFERRAL:
8137 case TRANSACT2_QFILEINFO:
8138 case TRANSACT2_QFSINFO:
8139 case TRANSACT2_SETFSINFO:
8140 break;
8141 default:
8142 reply_doserror(req, ERRSRV, ERRaccess);
8143 END_PROFILE(SMBtrans2);
8144 return;
8148 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8149 DEBUG(0, ("talloc failed\n"));
8150 reply_nterror(req, NT_STATUS_NO_MEMORY);
8151 END_PROFILE(SMBtrans2);
8152 return;
8155 state->cmd = SMBtrans2;
8157 state->mid = req->mid;
8158 state->vuid = req->vuid;
8159 state->setup_count = SVAL(req->vwv+13, 0);
8160 state->setup = NULL;
8161 state->total_param = SVAL(req->vwv+0, 0);
8162 state->param = NULL;
8163 state->total_data = SVAL(req->vwv+1, 0);
8164 state->data = NULL;
8165 state->max_param_return = SVAL(req->vwv+2, 0);
8166 state->max_data_return = SVAL(req->vwv+3, 0);
8167 state->max_setup_return = SVAL(req->vwv+4, 0);
8168 state->close_on_completion = BITSETW(req->vwv+5, 0);
8169 state->one_way = BITSETW(req->vwv+5, 1);
8171 state->call = tran_call;
8173 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8174 is so as a sanity check */
8175 if (state->setup_count != 1) {
8177 * Need to have rc=0 for ioctl to get job id for OS/2.
8178 * Network printing will fail if function is not successful.
8179 * Similar function in reply.c will be used if protocol
8180 * is LANMAN1.0 instead of LM1.2X002.
8181 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8182 * outbuf doesn't have to be set(only job id is used).
8184 if ( (state->setup_count == 4)
8185 && (tran_call == TRANSACT2_IOCTL)
8186 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8187 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8188 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8189 } else {
8190 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8191 DEBUG(2,("Transaction is %d\n",tran_call));
8192 TALLOC_FREE(state);
8193 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8194 END_PROFILE(SMBtrans2);
8195 return;
8199 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8200 goto bad_param;
8202 if (state->total_data) {
8204 if (trans_oob(state->total_data, 0, dscnt)
8205 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8206 goto bad_param;
8209 /* Can't use talloc here, the core routines do realloc on the
8210 * params and data. */
8211 state->data = (char *)SMB_MALLOC(state->total_data);
8212 if (state->data == NULL) {
8213 DEBUG(0,("reply_trans2: data malloc fail for %u "
8214 "bytes !\n", (unsigned int)state->total_data));
8215 TALLOC_FREE(state);
8216 reply_nterror(req, NT_STATUS_NO_MEMORY);
8217 END_PROFILE(SMBtrans2);
8218 return;
8221 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8224 if (state->total_param) {
8226 if (trans_oob(state->total_param, 0, pscnt)
8227 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8228 goto bad_param;
8231 /* Can't use talloc here, the core routines do realloc on the
8232 * params and data. */
8233 state->param = (char *)SMB_MALLOC(state->total_param);
8234 if (state->param == NULL) {
8235 DEBUG(0,("reply_trans: param malloc fail for %u "
8236 "bytes !\n", (unsigned int)state->total_param));
8237 SAFE_FREE(state->data);
8238 TALLOC_FREE(state);
8239 reply_nterror(req, NT_STATUS_NO_MEMORY);
8240 END_PROFILE(SMBtrans2);
8241 return;
8244 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8247 state->received_data = dscnt;
8248 state->received_param = pscnt;
8250 if ((state->received_param == state->total_param) &&
8251 (state->received_data == state->total_data)) {
8253 handle_trans2(conn, req, state);
8255 SAFE_FREE(state->data);
8256 SAFE_FREE(state->param);
8257 TALLOC_FREE(state);
8258 END_PROFILE(SMBtrans2);
8259 return;
8262 DLIST_ADD(conn->pending_trans, state);
8264 /* We need to send an interim response then receive the rest
8265 of the parameter/data bytes */
8266 reply_outbuf(req, 0, 0);
8267 show_msg((char *)req->outbuf);
8268 END_PROFILE(SMBtrans2);
8269 return;
8271 bad_param:
8273 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8274 SAFE_FREE(state->data);
8275 SAFE_FREE(state->param);
8276 TALLOC_FREE(state);
8277 END_PROFILE(SMBtrans2);
8278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8282 /****************************************************************************
8283 Reply to a SMBtranss2
8284 ****************************************************************************/
8286 void reply_transs2(struct smb_request *req)
8288 connection_struct *conn = req->conn;
8289 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8290 struct trans_state *state;
8292 START_PROFILE(SMBtranss2);
8294 show_msg((char *)req->inbuf);
8296 if (req->wct < 8) {
8297 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8298 END_PROFILE(SMBtranss2);
8299 return;
8302 for (state = conn->pending_trans; state != NULL;
8303 state = state->next) {
8304 if (state->mid == req->mid) {
8305 break;
8309 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8310 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8311 END_PROFILE(SMBtranss2);
8312 return;
8315 /* Revise state->total_param and state->total_data in case they have
8316 changed downwards */
8318 if (SVAL(req->vwv+0, 0) < state->total_param)
8319 state->total_param = SVAL(req->vwv+0, 0);
8320 if (SVAL(req->vwv+1, 0) < state->total_data)
8321 state->total_data = SVAL(req->vwv+1, 0);
8323 pcnt = SVAL(req->vwv+2, 0);
8324 poff = SVAL(req->vwv+3, 0);
8325 pdisp = SVAL(req->vwv+4, 0);
8327 dcnt = SVAL(req->vwv+5, 0);
8328 doff = SVAL(req->vwv+6, 0);
8329 ddisp = SVAL(req->vwv+7, 0);
8331 state->received_param += pcnt;
8332 state->received_data += dcnt;
8334 if ((state->received_data > state->total_data) ||
8335 (state->received_param > state->total_param))
8336 goto bad_param;
8338 if (pcnt) {
8339 if (trans_oob(state->total_param, pdisp, pcnt)
8340 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8341 goto bad_param;
8343 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8346 if (dcnt) {
8347 if (trans_oob(state->total_data, ddisp, dcnt)
8348 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8349 goto bad_param;
8351 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8354 if ((state->received_param < state->total_param) ||
8355 (state->received_data < state->total_data)) {
8356 END_PROFILE(SMBtranss2);
8357 return;
8360 handle_trans2(conn, req, state);
8362 DLIST_REMOVE(conn->pending_trans, state);
8363 SAFE_FREE(state->data);
8364 SAFE_FREE(state->param);
8365 TALLOC_FREE(state);
8367 END_PROFILE(SMBtranss2);
8368 return;
8370 bad_param:
8372 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8373 DLIST_REMOVE(conn->pending_trans, state);
8374 SAFE_FREE(state->data);
8375 SAFE_FREE(state->param);
8376 TALLOC_FREE(state);
8377 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8378 END_PROFILE(SMBtranss2);
8379 return;