pyldb: Raise proper exception when attempting to assign a string to a dn
[Samba/fernandojvsilva.git] / source3 / smbd / trans2.c
blob184a8580970acd3f2de4df0158457cc3d7b09246
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(connection_struct *conn,
1169 const char *str,
1170 const char *mask)
1172 if (mask[0] == '.' && mask[1] == 0)
1173 return False;
1174 if (dptr_has_wild(conn->dirptr)) {
1175 return False;
1177 if (conn->case_sensitive)
1178 return strcmp(str,mask)==0;
1179 else
1180 return StrCaseCmp(str,mask) == 0;
1183 /****************************************************************************
1184 Return the filetype for UNIX extensions.
1185 ****************************************************************************/
1187 static uint32 unix_filetype(mode_t mode)
1189 if(S_ISREG(mode))
1190 return UNIX_TYPE_FILE;
1191 else if(S_ISDIR(mode))
1192 return UNIX_TYPE_DIR;
1193 #ifdef S_ISLNK
1194 else if(S_ISLNK(mode))
1195 return UNIX_TYPE_SYMLINK;
1196 #endif
1197 #ifdef S_ISCHR
1198 else if(S_ISCHR(mode))
1199 return UNIX_TYPE_CHARDEV;
1200 #endif
1201 #ifdef S_ISBLK
1202 else if(S_ISBLK(mode))
1203 return UNIX_TYPE_BLKDEV;
1204 #endif
1205 #ifdef S_ISFIFO
1206 else if(S_ISFIFO(mode))
1207 return UNIX_TYPE_FIFO;
1208 #endif
1209 #ifdef S_ISSOCK
1210 else if(S_ISSOCK(mode))
1211 return UNIX_TYPE_SOCKET;
1212 #endif
1214 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1215 return UNIX_TYPE_UNKNOWN;
1218 /****************************************************************************
1219 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1220 ****************************************************************************/
1222 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1224 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1225 const SMB_STRUCT_STAT *psbuf,
1226 uint32 perms,
1227 enum perm_type ptype,
1228 mode_t *ret_perms)
1230 mode_t ret = 0;
1232 if (perms == SMB_MODE_NO_CHANGE) {
1233 if (!VALID_STAT(*psbuf)) {
1234 return NT_STATUS_INVALID_PARAMETER;
1235 } else {
1236 *ret_perms = psbuf->st_ex_mode;
1237 return NT_STATUS_OK;
1241 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1242 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1243 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1244 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1245 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1246 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1247 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1248 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1249 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1250 #ifdef S_ISVTX
1251 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1252 #endif
1253 #ifdef S_ISGID
1254 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1255 #endif
1256 #ifdef S_ISUID
1257 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1258 #endif
1260 switch (ptype) {
1261 case PERM_NEW_FILE:
1262 /* Apply mode mask */
1263 ret &= lp_create_mask(SNUM(conn));
1264 /* Add in force bits */
1265 ret |= lp_force_create_mode(SNUM(conn));
1266 break;
1267 case PERM_NEW_DIR:
1268 ret &= lp_dir_mask(SNUM(conn));
1269 /* Add in force bits */
1270 ret |= lp_force_dir_mode(SNUM(conn));
1271 break;
1272 case PERM_EXISTING_FILE:
1273 /* Apply mode mask */
1274 ret &= lp_security_mask(SNUM(conn));
1275 /* Add in force bits */
1276 ret |= lp_force_security_mode(SNUM(conn));
1277 break;
1278 case PERM_EXISTING_DIR:
1279 /* Apply mode mask */
1280 ret &= lp_dir_security_mask(SNUM(conn));
1281 /* Add in force bits */
1282 ret |= lp_force_dir_security_mode(SNUM(conn));
1283 break;
1286 *ret_perms = ret;
1287 return NT_STATUS_OK;
1290 /****************************************************************************
1291 Needed to show the msdfs symlinks as directories. Modifies psbuf
1292 to be a directory if it's a msdfs link.
1293 ****************************************************************************/
1295 static bool check_msdfs_link(connection_struct *conn,
1296 const char *pathname,
1297 SMB_STRUCT_STAT *psbuf)
1299 int saved_errno = errno;
1300 if(lp_host_msdfs() &&
1301 lp_msdfs_root(SNUM(conn)) &&
1302 is_msdfs_link(conn, pathname, psbuf)) {
1304 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1305 "as a directory\n",
1306 pathname));
1307 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1308 errno = saved_errno;
1309 return true;
1311 errno = saved_errno;
1312 return false;
1316 /****************************************************************************
1317 Get a level dependent lanman2 dir entry.
1318 ****************************************************************************/
1320 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1321 connection_struct *conn,
1322 uint16 flags2,
1323 const char *path_mask,
1324 uint32 dirtype,
1325 int info_level,
1326 int requires_resume_key,
1327 bool dont_descend,
1328 bool ask_sharemode,
1329 char **ppdata,
1330 char *base_data,
1331 char *end_data,
1332 int space_remaining,
1333 bool *out_of_space,
1334 bool *got_exact_match,
1335 int *last_entry_off,
1336 struct ea_list *name_list)
1338 char *dname;
1339 bool found = False;
1340 SMB_STRUCT_STAT sbuf;
1341 const char *mask = NULL;
1342 char *pathreal = NULL;
1343 char *fname = NULL;
1344 char *p, *q, *pdata = *ppdata;
1345 uint32 reskey=0;
1346 long prev_dirpos=0;
1347 uint32 mode=0;
1348 SMB_OFF_T file_size = 0;
1349 uint64_t allocation_size = 0;
1350 uint32 len;
1351 struct timespec mdate_ts, adate_ts, create_date_ts;
1352 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1353 char *nameptr;
1354 char *last_entry_ptr;
1355 bool was_8_3;
1356 uint32 nt_extmode; /* Used for NT connections instead of mode */
1357 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1358 bool check_mangled_names = lp_manglednames(conn->params);
1359 char mangled_name[13]; /* mangled 8.3 name. */
1361 *out_of_space = False;
1362 *got_exact_match = False;
1364 ZERO_STRUCT(mdate_ts);
1365 ZERO_STRUCT(adate_ts);
1366 ZERO_STRUCT(create_date_ts);
1368 if (!conn->dirptr) {
1369 return(False);
1372 p = strrchr_m(path_mask,'/');
1373 if(p != NULL) {
1374 if(p[1] == '\0') {
1375 mask = talloc_strdup(ctx,"*.*");
1376 } else {
1377 mask = p+1;
1379 } else {
1380 mask = path_mask;
1383 while (!found) {
1384 bool got_match;
1385 bool ms_dfs_link = False;
1387 /* Needed if we run out of space */
1388 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1389 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1392 * Due to bugs in NT client redirectors we are not using
1393 * resume keys any more - set them to zero.
1394 * Check out the related comments in findfirst/findnext.
1395 * JRA.
1398 reskey = 0;
1400 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1401 (long)conn->dirptr,curr_dirpos));
1403 if (!dname) {
1404 return(False);
1408 * fname may get mangled, dname is never mangled.
1409 * Whenever we're accessing the filesystem we use
1410 * pathreal which is composed from dname.
1413 pathreal = NULL;
1414 fname = dname;
1416 /* Mangle fname if it's an illegal name. */
1417 if (mangle_must_mangle(dname,conn->params)) {
1418 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1419 TALLOC_FREE(fname);
1420 continue; /* Error - couldn't mangle. */
1422 fname = talloc_strdup(ctx, mangled_name);
1423 if (!fname) {
1424 return False;
1428 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1429 got_match = mask_match(fname, mask, conn->case_sensitive);
1432 if(!got_match && check_mangled_names &&
1433 !mangle_is_8_3(fname, False, conn->params)) {
1435 * It turns out that NT matches wildcards against
1436 * both long *and* short names. This may explain some
1437 * of the wildcard wierdness from old DOS clients
1438 * that some people have been seeing.... JRA.
1440 /* Force the mangling into 8.3. */
1441 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1442 TALLOC_FREE(fname);
1443 continue; /* Error - couldn't mangle. */
1446 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1447 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1451 if (got_match) {
1452 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1453 struct smb_filename *smb_fname = NULL;
1454 NTSTATUS status;
1456 if (dont_descend && !isdots) {
1457 TALLOC_FREE(fname);
1458 continue;
1461 if (needslash) {
1462 pathreal = NULL;
1463 pathreal = talloc_asprintf(ctx,
1464 "%s/%s",
1465 conn->dirpath,
1466 dname);
1467 } else {
1468 pathreal = talloc_asprintf(ctx,
1469 "%s%s",
1470 conn->dirpath,
1471 dname);
1474 if (!pathreal) {
1475 TALLOC_FREE(fname);
1476 return False;
1479 /* A dirent from dptr_ReadDirName isn't a stream. */
1480 status = create_synthetic_smb_fname(ctx, pathreal,
1481 NULL, &sbuf,
1482 &smb_fname);
1483 if (!NT_STATUS_IS_OK(status)) {
1484 TALLOC_FREE(fname);
1485 return false;
1488 if (INFO_LEVEL_IS_UNIX(info_level)) {
1489 if (SMB_VFS_LSTAT(conn, smb_fname) != 0) {
1490 DEBUG(5,("get_lanman2_dir_entry: "
1491 "Couldn't lstat [%s] (%s)\n",
1492 smb_fname_str_dbg(smb_fname),
1493 strerror(errno)));
1494 TALLOC_FREE(smb_fname);
1495 TALLOC_FREE(pathreal);
1496 TALLOC_FREE(fname);
1497 continue;
1499 } else if (!VALID_STAT(smb_fname->st) &&
1500 SMB_VFS_STAT(conn, smb_fname) != 0) {
1501 /* Needed to show the msdfs symlinks as
1502 * directories */
1504 ms_dfs_link =
1505 check_msdfs_link(conn,
1506 smb_fname->base_name,
1507 &smb_fname->st);
1508 if (!ms_dfs_link) {
1509 DEBUG(5,("get_lanman2_dir_entry: "
1510 "Couldn't stat [%s] (%s)\n",
1511 smb_fname_str_dbg(smb_fname),
1512 strerror(errno)));
1513 TALLOC_FREE(smb_fname);
1514 TALLOC_FREE(pathreal);
1515 TALLOC_FREE(fname);
1516 continue;
1520 if (ms_dfs_link) {
1521 mode = dos_mode_msdfs(conn, smb_fname);
1522 } else {
1523 mode = dos_mode(conn, smb_fname);
1526 if (!dir_check_ftype(conn,mode,dirtype)) {
1527 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1528 TALLOC_FREE(smb_fname);
1529 TALLOC_FREE(pathreal);
1530 TALLOC_FREE(fname);
1531 continue;
1534 if (!(mode & aDIR)) {
1535 file_size = get_file_size_stat(&smb_fname->st);
1537 allocation_size =
1538 SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1540 if (ask_sharemode) {
1541 struct timespec write_time_ts;
1542 struct file_id fileid;
1544 ZERO_STRUCT(write_time_ts);
1545 fileid = vfs_file_id_from_sbuf(conn,
1546 &smb_fname->st);
1547 get_file_infos(fileid, NULL, &write_time_ts);
1548 if (!null_timespec(write_time_ts)) {
1549 update_stat_ex_mtime(&smb_fname->st,
1550 write_time_ts);
1554 mdate_ts = smb_fname->st.st_ex_mtime;
1555 adate_ts = smb_fname->st.st_ex_atime;
1556 create_date_ts = smb_fname->st.st_ex_btime;
1558 if (lp_dos_filetime_resolution(SNUM(conn))) {
1559 dos_filetime_timespec(&create_date_ts);
1560 dos_filetime_timespec(&mdate_ts);
1561 dos_filetime_timespec(&adate_ts);
1564 create_date = convert_timespec_to_time_t(create_date_ts);
1565 mdate = convert_timespec_to_time_t(mdate_ts);
1566 adate = convert_timespec_to_time_t(adate_ts);
1568 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1569 smb_fname_str_dbg(smb_fname), fname));
1571 found = True;
1573 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1574 sbuf = smb_fname->st;
1576 TALLOC_FREE(smb_fname);
1579 if (!found)
1580 TALLOC_FREE(fname);
1583 p = pdata;
1584 last_entry_ptr = p;
1586 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1588 switch (info_level) {
1589 case SMB_FIND_INFO_STANDARD:
1590 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1591 if(requires_resume_key) {
1592 SIVAL(p,0,reskey);
1593 p += 4;
1595 srv_put_dos_date2(p,0,create_date);
1596 srv_put_dos_date2(p,4,adate);
1597 srv_put_dos_date2(p,8,mdate);
1598 SIVAL(p,12,(uint32)file_size);
1599 SIVAL(p,16,(uint32)allocation_size);
1600 SSVAL(p,20,mode);
1601 p += 23;
1602 nameptr = p;
1603 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1604 p += ucs2_align(base_data, p, 0);
1606 len = srvstr_push(base_data, flags2, p,
1607 fname, PTR_DIFF(end_data, p),
1608 STR_TERMINATE);
1609 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1610 if (len > 2) {
1611 SCVAL(nameptr, -1, len - 2);
1612 } else {
1613 SCVAL(nameptr, -1, 0);
1615 } else {
1616 if (len > 1) {
1617 SCVAL(nameptr, -1, len - 1);
1618 } else {
1619 SCVAL(nameptr, -1, 0);
1622 p += len;
1623 break;
1625 case SMB_FIND_EA_SIZE:
1626 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1627 if(requires_resume_key) {
1628 SIVAL(p,0,reskey);
1629 p += 4;
1631 srv_put_dos_date2(p,0,create_date);
1632 srv_put_dos_date2(p,4,adate);
1633 srv_put_dos_date2(p,8,mdate);
1634 SIVAL(p,12,(uint32)file_size);
1635 SIVAL(p,16,(uint32)allocation_size);
1636 SSVAL(p,20,mode);
1638 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1639 SIVAL(p,22,ea_size); /* Extended attributes */
1641 p += 27;
1642 nameptr = p - 1;
1643 len = srvstr_push(base_data, flags2,
1644 p, fname, PTR_DIFF(end_data, p),
1645 STR_TERMINATE | STR_NOALIGN);
1646 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1647 if (len > 2) {
1648 len -= 2;
1649 } else {
1650 len = 0;
1652 } else {
1653 if (len > 1) {
1654 len -= 1;
1655 } else {
1656 len = 0;
1659 SCVAL(nameptr,0,len);
1660 p += len;
1661 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1662 break;
1664 case SMB_FIND_EA_LIST:
1666 struct ea_list *file_list = NULL;
1667 size_t ea_len = 0;
1669 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1670 if (!name_list) {
1671 return False;
1673 if(requires_resume_key) {
1674 SIVAL(p,0,reskey);
1675 p += 4;
1677 srv_put_dos_date2(p,0,create_date);
1678 srv_put_dos_date2(p,4,adate);
1679 srv_put_dos_date2(p,8,mdate);
1680 SIVAL(p,12,(uint32)file_size);
1681 SIVAL(p,16,(uint32)allocation_size);
1682 SSVAL(p,20,mode);
1683 p += 22; /* p now points to the EA area. */
1685 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1686 name_list = ea_list_union(name_list, file_list, &ea_len);
1688 /* We need to determine if this entry will fit in the space available. */
1689 /* Max string size is 255 bytes. */
1690 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1691 /* Move the dirptr back to prev_dirpos */
1692 dptr_SeekDir(conn->dirptr, prev_dirpos);
1693 *out_of_space = True;
1694 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1695 return False; /* Not finished - just out of space */
1698 /* Push the ea_data followed by the name. */
1699 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1700 nameptr = p;
1701 len = srvstr_push(base_data, flags2,
1702 p + 1, fname, PTR_DIFF(end_data, p+1),
1703 STR_TERMINATE | STR_NOALIGN);
1704 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1705 if (len > 2) {
1706 len -= 2;
1707 } else {
1708 len = 0;
1710 } else {
1711 if (len > 1) {
1712 len -= 1;
1713 } else {
1714 len = 0;
1717 SCVAL(nameptr,0,len);
1718 p += len + 1;
1719 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1720 break;
1723 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1724 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1725 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1726 p += 4;
1727 SIVAL(p,0,reskey); p += 4;
1728 put_long_date_timespec(p,create_date_ts); p += 8;
1729 put_long_date_timespec(p,adate_ts); p += 8;
1730 put_long_date_timespec(p,mdate_ts); p += 8;
1731 put_long_date_timespec(p,mdate_ts); p += 8;
1732 SOFF_T(p,0,file_size); p += 8;
1733 SOFF_T(p,0,allocation_size); p += 8;
1734 SIVAL(p,0,nt_extmode); p += 4;
1735 q = p; p += 4; /* q is placeholder for name length. */
1737 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1738 SIVAL(p,0,ea_size); /* Extended attributes */
1739 p += 4;
1741 /* Clear the short name buffer. This is
1742 * IMPORTANT as not doing so will trigger
1743 * a Win2k client bug. JRA.
1745 if (!was_8_3 && check_mangled_names) {
1746 if (!name_to_8_3(fname,mangled_name,True,
1747 conn->params)) {
1748 /* Error - mangle failed ! */
1749 memset(mangled_name,'\0',12);
1751 mangled_name[12] = 0;
1752 len = srvstr_push(base_data, flags2,
1753 p+2, mangled_name, 24,
1754 STR_UPPER|STR_UNICODE);
1755 if (len < 24) {
1756 memset(p + 2 + len,'\0',24 - len);
1758 SSVAL(p, 0, len);
1759 } else {
1760 memset(p,'\0',26);
1762 p += 2 + 24;
1763 len = srvstr_push(base_data, flags2, p,
1764 fname, PTR_DIFF(end_data, p),
1765 STR_TERMINATE_ASCII);
1766 SIVAL(q,0,len);
1767 p += len;
1768 SIVAL(p,0,0); /* Ensure any padding is null. */
1769 len = PTR_DIFF(p, pdata);
1770 len = (len + 3) & ~3;
1771 SIVAL(pdata,0,len);
1772 p = pdata + len;
1773 break;
1775 case SMB_FIND_FILE_DIRECTORY_INFO:
1776 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1777 p += 4;
1778 SIVAL(p,0,reskey); p += 4;
1779 put_long_date_timespec(p,create_date_ts); p += 8;
1780 put_long_date_timespec(p,adate_ts); p += 8;
1781 put_long_date_timespec(p,mdate_ts); p += 8;
1782 put_long_date_timespec(p,mdate_ts); p += 8;
1783 SOFF_T(p,0,file_size); p += 8;
1784 SOFF_T(p,0,allocation_size); p += 8;
1785 SIVAL(p,0,nt_extmode); p += 4;
1786 len = srvstr_push(base_data, flags2,
1787 p + 4, fname, PTR_DIFF(end_data, p+4),
1788 STR_TERMINATE_ASCII);
1789 SIVAL(p,0,len);
1790 p += 4 + len;
1791 SIVAL(p,0,0); /* Ensure any padding is null. */
1792 len = PTR_DIFF(p, pdata);
1793 len = (len + 3) & ~3;
1794 SIVAL(pdata,0,len);
1795 p = pdata + len;
1796 break;
1798 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1799 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1800 p += 4;
1801 SIVAL(p,0,reskey); p += 4;
1802 put_long_date_timespec(p,create_date_ts); p += 8;
1803 put_long_date_timespec(p,adate_ts); p += 8;
1804 put_long_date_timespec(p,mdate_ts); p += 8;
1805 put_long_date_timespec(p,mdate_ts); p += 8;
1806 SOFF_T(p,0,file_size); p += 8;
1807 SOFF_T(p,0,allocation_size); p += 8;
1808 SIVAL(p,0,nt_extmode); p += 4;
1809 q = p; p += 4; /* q is placeholder for name length. */
1811 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1812 SIVAL(p,0,ea_size); /* Extended attributes */
1813 p +=4;
1815 len = srvstr_push(base_data, flags2, p,
1816 fname, PTR_DIFF(end_data, p),
1817 STR_TERMINATE_ASCII);
1818 SIVAL(q, 0, len);
1819 p += len;
1821 SIVAL(p,0,0); /* Ensure any padding is null. */
1822 len = PTR_DIFF(p, pdata);
1823 len = (len + 3) & ~3;
1824 SIVAL(pdata,0,len);
1825 p = pdata + len;
1826 break;
1828 case SMB_FIND_FILE_NAMES_INFO:
1829 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1830 p += 4;
1831 SIVAL(p,0,reskey); p += 4;
1832 p += 4;
1833 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1834 acl on a dir (tridge) */
1835 len = srvstr_push(base_data, flags2, p,
1836 fname, PTR_DIFF(end_data, p),
1837 STR_TERMINATE_ASCII);
1838 SIVAL(p, -4, len);
1839 p += len;
1840 SIVAL(p,0,0); /* Ensure any padding is null. */
1841 len = PTR_DIFF(p, pdata);
1842 len = (len + 3) & ~3;
1843 SIVAL(pdata,0,len);
1844 p = pdata + len;
1845 break;
1847 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1848 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1849 p += 4;
1850 SIVAL(p,0,reskey); p += 4;
1851 put_long_date_timespec(p,create_date_ts); p += 8;
1852 put_long_date_timespec(p,adate_ts); p += 8;
1853 put_long_date_timespec(p,mdate_ts); p += 8;
1854 put_long_date_timespec(p,mdate_ts); p += 8;
1855 SOFF_T(p,0,file_size); p += 8;
1856 SOFF_T(p,0,allocation_size); p += 8;
1857 SIVAL(p,0,nt_extmode); p += 4;
1858 q = p; p += 4; /* q is placeholder for name length. */
1860 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1861 SIVAL(p,0,ea_size); /* Extended attributes */
1862 p +=4;
1864 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1865 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1866 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1867 len = srvstr_push(base_data, flags2, p,
1868 fname, PTR_DIFF(end_data, p),
1869 STR_TERMINATE_ASCII);
1870 SIVAL(q, 0, len);
1871 p += len;
1872 SIVAL(p,0,0); /* Ensure any padding is null. */
1873 len = PTR_DIFF(p, pdata);
1874 len = (len + 3) & ~3;
1875 SIVAL(pdata,0,len);
1876 p = pdata + len;
1877 break;
1879 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1880 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1881 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1882 p += 4;
1883 SIVAL(p,0,reskey); p += 4;
1884 put_long_date_timespec(p,create_date_ts); p += 8;
1885 put_long_date_timespec(p,adate_ts); p += 8;
1886 put_long_date_timespec(p,mdate_ts); p += 8;
1887 put_long_date_timespec(p,mdate_ts); p += 8;
1888 SOFF_T(p,0,file_size); p += 8;
1889 SOFF_T(p,0,allocation_size); p += 8;
1890 SIVAL(p,0,nt_extmode); p += 4;
1891 q = p; p += 4; /* q is placeholder for name length */
1893 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1894 SIVAL(p,0,ea_size); /* Extended attributes */
1895 p +=4;
1897 /* Clear the short name buffer. This is
1898 * IMPORTANT as not doing so will trigger
1899 * a Win2k client bug. JRA.
1901 if (!was_8_3 && check_mangled_names) {
1902 if (!name_to_8_3(fname,mangled_name,True,
1903 conn->params)) {
1904 /* Error - mangle failed ! */
1905 memset(mangled_name,'\0',12);
1907 mangled_name[12] = 0;
1908 len = srvstr_push(base_data, flags2,
1909 p+2, mangled_name, 24,
1910 STR_UPPER|STR_UNICODE);
1911 SSVAL(p, 0, len);
1912 if (len < 24) {
1913 memset(p + 2 + len,'\0',24 - len);
1915 SSVAL(p, 0, len);
1916 } else {
1917 memset(p,'\0',26);
1919 p += 26;
1920 SSVAL(p,0,0); p += 2; /* Reserved ? */
1921 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1922 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1923 len = srvstr_push(base_data, flags2, p,
1924 fname, PTR_DIFF(end_data, p),
1925 STR_TERMINATE_ASCII);
1926 SIVAL(q,0,len);
1927 p += len;
1928 SIVAL(p,0,0); /* Ensure any padding is null. */
1929 len = PTR_DIFF(p, pdata);
1930 len = (len + 3) & ~3;
1931 SIVAL(pdata,0,len);
1932 p = pdata + len;
1933 break;
1935 /* CIFS UNIX Extension. */
1937 case SMB_FIND_FILE_UNIX:
1938 case SMB_FIND_FILE_UNIX_INFO2:
1939 p+= 4;
1940 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1942 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1944 if (info_level == SMB_FIND_FILE_UNIX) {
1945 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1946 p = store_file_unix_basic(conn, p,
1947 NULL, &sbuf);
1948 len = srvstr_push(base_data, flags2, p,
1949 fname, PTR_DIFF(end_data, p),
1950 STR_TERMINATE);
1951 } else {
1952 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1953 p = store_file_unix_basic_info2(conn, p,
1954 NULL, &sbuf);
1955 nameptr = p;
1956 p += 4;
1957 len = srvstr_push(base_data, flags2, p, fname,
1958 PTR_DIFF(end_data, p), 0);
1959 SIVAL(nameptr, 0, len);
1962 p += len;
1963 SIVAL(p,0,0); /* Ensure any padding is null. */
1965 len = PTR_DIFF(p, pdata);
1966 len = (len + 3) & ~3;
1967 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1968 p = pdata + len;
1969 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1971 break;
1973 default:
1974 TALLOC_FREE(fname);
1975 return(False);
1978 TALLOC_FREE(fname);
1979 if (PTR_DIFF(p,pdata) > space_remaining) {
1980 /* Move the dirptr back to prev_dirpos */
1981 dptr_SeekDir(conn->dirptr, prev_dirpos);
1982 *out_of_space = True;
1983 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1984 return False; /* Not finished - just out of space */
1987 /* Setup the last entry pointer, as an offset from base_data */
1988 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1989 /* Advance the data pointer to the next slot */
1990 *ppdata = p;
1992 return(found);
1995 /****************************************************************************
1996 Reply to a TRANS2_FINDFIRST.
1997 ****************************************************************************/
1999 static void call_trans2findfirst(connection_struct *conn,
2000 struct smb_request *req,
2001 char **pparams, int total_params,
2002 char **ppdata, int total_data,
2003 unsigned int max_data_bytes)
2005 /* We must be careful here that we don't return more than the
2006 allowed number of data bytes. If this means returning fewer than
2007 maxentries then so be it. We assume that the redirector has
2008 enough room for the fixed number of parameter bytes it has
2009 requested. */
2010 struct smb_filename *smb_dname = NULL;
2011 char *params = *pparams;
2012 char *pdata = *ppdata;
2013 char *data_end;
2014 uint32 dirtype;
2015 int maxentries;
2016 uint16 findfirst_flags;
2017 bool close_after_first;
2018 bool close_if_end;
2019 bool requires_resume_key;
2020 int info_level;
2021 char *directory = NULL;
2022 char *mask = NULL;
2023 char *p;
2024 int last_entry_off=0;
2025 int dptr_num = -1;
2026 int numentries = 0;
2027 int i;
2028 bool finished = False;
2029 bool dont_descend = False;
2030 bool out_of_space = False;
2031 int space_remaining;
2032 bool mask_contains_wcard = False;
2033 struct ea_list *ea_list = NULL;
2034 NTSTATUS ntstatus = NT_STATUS_OK;
2035 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2036 TALLOC_CTX *ctx = talloc_tos();
2038 if (total_params < 13) {
2039 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2040 goto out;
2043 dirtype = SVAL(params,0);
2044 maxentries = SVAL(params,2);
2045 findfirst_flags = SVAL(params,4);
2046 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2047 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2048 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2049 info_level = SVAL(params,6);
2051 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2052 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2053 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2054 info_level, max_data_bytes));
2056 if (!maxentries) {
2057 /* W2K3 seems to treat zero as 1. */
2058 maxentries = 1;
2061 switch (info_level) {
2062 case SMB_FIND_INFO_STANDARD:
2063 case SMB_FIND_EA_SIZE:
2064 case SMB_FIND_EA_LIST:
2065 case SMB_FIND_FILE_DIRECTORY_INFO:
2066 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2067 case SMB_FIND_FILE_NAMES_INFO:
2068 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2069 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2070 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2071 break;
2072 case SMB_FIND_FILE_UNIX:
2073 case SMB_FIND_FILE_UNIX_INFO2:
2074 /* Always use filesystem for UNIX mtime query. */
2075 ask_sharemode = false;
2076 if (!lp_unix_extensions()) {
2077 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2078 goto out;
2080 break;
2081 default:
2082 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2083 goto out;
2086 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2087 params+12, total_params - 12,
2088 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2089 if (!NT_STATUS_IS_OK(ntstatus)) {
2090 reply_nterror(req, ntstatus);
2091 goto out;
2094 ntstatus = filename_convert(ctx, conn,
2095 req->flags2 & FLAGS2_DFS_PATHNAMES,
2096 directory,
2097 (UCF_SAVE_LCOMP |
2098 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2099 &mask_contains_wcard,
2100 &smb_dname);
2101 if (!NT_STATUS_IS_OK(ntstatus)) {
2102 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2103 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2104 ERRSRV, ERRbadpath);
2105 goto out;
2107 reply_nterror(req, ntstatus);
2108 goto out;
2111 mask = smb_dname->original_lcomp;
2113 directory = smb_dname->base_name;
2115 p = strrchr_m(directory,'/');
2116 if(p == NULL) {
2117 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2118 if((directory[0] == '.') && (directory[1] == '\0')) {
2119 mask = talloc_strdup(ctx,"*");
2120 if (!mask) {
2121 reply_nterror(req, NT_STATUS_NO_MEMORY);
2122 goto out;
2124 mask_contains_wcard = True;
2126 directory = talloc_strdup(talloc_tos(), "./");
2127 if (!directory) {
2128 reply_nterror(req, NT_STATUS_NO_MEMORY);
2129 goto out;
2131 } else {
2132 *p = 0;
2135 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2137 if (info_level == SMB_FIND_EA_LIST) {
2138 uint32 ea_size;
2140 if (total_data < 4) {
2141 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2142 goto out;
2145 ea_size = IVAL(pdata,0);
2146 if (ea_size != total_data) {
2147 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2148 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2149 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2150 goto out;
2153 if (!lp_ea_support(SNUM(conn))) {
2154 reply_doserror(req, ERRDOS, ERReasnotsupported);
2155 goto out;
2158 /* Pull out the list of names. */
2159 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2160 if (!ea_list) {
2161 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2162 goto out;
2166 *ppdata = (char *)SMB_REALLOC(
2167 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2168 if(*ppdata == NULL ) {
2169 reply_nterror(req, NT_STATUS_NO_MEMORY);
2170 goto out;
2172 pdata = *ppdata;
2173 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2175 /* Realloc the params space */
2176 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2177 if (*pparams == NULL) {
2178 reply_nterror(req, NT_STATUS_NO_MEMORY);
2179 goto out;
2181 params = *pparams;
2183 /* Save the wildcard match and attribs we are using on this directory -
2184 needed as lanman2 assumes these are being saved between calls */
2186 ntstatus = dptr_create(conn,
2187 directory,
2188 False,
2189 True,
2190 req->smbpid,
2191 mask,
2192 mask_contains_wcard,
2193 dirtype,
2194 &conn->dirptr);
2196 if (!NT_STATUS_IS_OK(ntstatus)) {
2197 reply_nterror(req, ntstatus);
2198 goto out;
2201 dptr_num = dptr_dnum(conn->dirptr);
2202 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2204 /* Initialize per TRANS2_FIND_FIRST operation data */
2205 dptr_init_search_op(conn->dirptr);
2207 /* We don't need to check for VOL here as this is returned by
2208 a different TRANS2 call. */
2210 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2211 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2212 dont_descend = True;
2214 p = pdata;
2215 space_remaining = max_data_bytes;
2216 out_of_space = False;
2218 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2219 bool got_exact_match = False;
2221 /* this is a heuristic to avoid seeking the dirptr except when
2222 absolutely necessary. It allows for a filename of about 40 chars */
2223 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2224 out_of_space = True;
2225 finished = False;
2226 } else {
2227 finished = !get_lanman2_dir_entry(ctx,
2228 conn,
2229 req->flags2,
2230 mask,dirtype,info_level,
2231 requires_resume_key,dont_descend,
2232 ask_sharemode,
2233 &p,pdata,data_end,
2234 space_remaining, &out_of_space,
2235 &got_exact_match,
2236 &last_entry_off, ea_list);
2239 if (finished && out_of_space)
2240 finished = False;
2242 if (!finished && !out_of_space)
2243 numentries++;
2246 * As an optimisation if we know we aren't looking
2247 * for a wildcard name (ie. the name matches the wildcard exactly)
2248 * then we can finish on any (first) match.
2249 * This speeds up large directory searches. JRA.
2252 if(got_exact_match)
2253 finished = True;
2255 /* Ensure space_remaining never goes -ve. */
2256 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2257 space_remaining = 0;
2258 out_of_space = true;
2259 } else {
2260 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2264 /* Check if we can close the dirptr */
2265 if(close_after_first || (finished && close_if_end)) {
2266 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2267 dptr_close(&dptr_num);
2271 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2272 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2273 * the protocol level is less than NT1. Tested with smbclient. JRA.
2274 * This should fix the OS/2 client bug #2335.
2277 if(numentries == 0) {
2278 dptr_close(&dptr_num);
2279 if (Protocol < PROTOCOL_NT1) {
2280 reply_doserror(req, ERRDOS, ERRnofiles);
2281 goto out;
2282 } else {
2283 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2284 ERRDOS, ERRbadfile);
2285 goto out;
2289 /* At this point pdata points to numentries directory entries. */
2291 /* Set up the return parameter block */
2292 SSVAL(params,0,dptr_num);
2293 SSVAL(params,2,numentries);
2294 SSVAL(params,4,finished);
2295 SSVAL(params,6,0); /* Never an EA error */
2296 SSVAL(params,8,last_entry_off);
2298 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2299 max_data_bytes);
2301 if ((! *directory) && dptr_path(dptr_num)) {
2302 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2303 if (!directory) {
2304 reply_nterror(req, NT_STATUS_NO_MEMORY);
2308 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2309 smb_fn_name(req->cmd),
2310 mask, directory, dirtype, numentries ) );
2313 * Force a name mangle here to ensure that the
2314 * mask as an 8.3 name is top of the mangled cache.
2315 * The reasons for this are subtle. Don't remove
2316 * this code unless you know what you are doing
2317 * (see PR#13758). JRA.
2320 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2321 char mangled_name[13];
2322 name_to_8_3(mask, mangled_name, True, conn->params);
2324 out:
2325 TALLOC_FREE(smb_dname);
2326 return;
2329 /****************************************************************************
2330 Reply to a TRANS2_FINDNEXT.
2331 ****************************************************************************/
2333 static void call_trans2findnext(connection_struct *conn,
2334 struct smb_request *req,
2335 char **pparams, int total_params,
2336 char **ppdata, int total_data,
2337 unsigned int max_data_bytes)
2339 /* We must be careful here that we don't return more than the
2340 allowed number of data bytes. If this means returning fewer than
2341 maxentries then so be it. We assume that the redirector has
2342 enough room for the fixed number of parameter bytes it has
2343 requested. */
2344 char *params = *pparams;
2345 char *pdata = *ppdata;
2346 char *data_end;
2347 int dptr_num;
2348 int maxentries;
2349 uint16 info_level;
2350 uint32 resume_key;
2351 uint16 findnext_flags;
2352 bool close_after_request;
2353 bool close_if_end;
2354 bool requires_resume_key;
2355 bool continue_bit;
2356 bool mask_contains_wcard = False;
2357 char *resume_name = NULL;
2358 const char *mask = NULL;
2359 const char *directory = NULL;
2360 char *p = NULL;
2361 uint16 dirtype;
2362 int numentries = 0;
2363 int i, last_entry_off=0;
2364 bool finished = False;
2365 bool dont_descend = False;
2366 bool out_of_space = False;
2367 int space_remaining;
2368 struct ea_list *ea_list = NULL;
2369 NTSTATUS ntstatus = NT_STATUS_OK;
2370 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2371 TALLOC_CTX *ctx = talloc_tos();
2373 if (total_params < 13) {
2374 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2375 return;
2378 dptr_num = SVAL(params,0);
2379 maxentries = SVAL(params,2);
2380 info_level = SVAL(params,4);
2381 resume_key = IVAL(params,6);
2382 findnext_flags = SVAL(params,10);
2383 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2384 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2385 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2386 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2388 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2389 params+12,
2390 total_params - 12, STR_TERMINATE, &ntstatus,
2391 &mask_contains_wcard);
2392 if (!NT_STATUS_IS_OK(ntstatus)) {
2393 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2394 complain (it thinks we're asking for the directory above the shared
2395 path or an invalid name). Catch this as the resume name is only compared, never used in
2396 a file access. JRA. */
2397 srvstr_pull_talloc(ctx, params, req->flags2,
2398 &resume_name, params+12,
2399 total_params - 12,
2400 STR_TERMINATE);
2402 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2403 reply_nterror(req, ntstatus);
2404 return;
2408 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2409 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2410 resume_key = %d resume name = %s continue=%d level = %d\n",
2411 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2412 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2414 if (!maxentries) {
2415 /* W2K3 seems to treat zero as 1. */
2416 maxentries = 1;
2419 switch (info_level) {
2420 case SMB_FIND_INFO_STANDARD:
2421 case SMB_FIND_EA_SIZE:
2422 case SMB_FIND_EA_LIST:
2423 case SMB_FIND_FILE_DIRECTORY_INFO:
2424 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2425 case SMB_FIND_FILE_NAMES_INFO:
2426 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2427 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2428 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2429 break;
2430 case SMB_FIND_FILE_UNIX:
2431 case SMB_FIND_FILE_UNIX_INFO2:
2432 /* Always use filesystem for UNIX mtime query. */
2433 ask_sharemode = false;
2434 if (!lp_unix_extensions()) {
2435 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2436 return;
2438 break;
2439 default:
2440 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2441 return;
2444 if (info_level == SMB_FIND_EA_LIST) {
2445 uint32 ea_size;
2447 if (total_data < 4) {
2448 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2449 return;
2452 ea_size = IVAL(pdata,0);
2453 if (ea_size != total_data) {
2454 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2455 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2456 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2457 return;
2460 if (!lp_ea_support(SNUM(conn))) {
2461 reply_doserror(req, ERRDOS, ERReasnotsupported);
2462 return;
2465 /* Pull out the list of names. */
2466 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2467 if (!ea_list) {
2468 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2469 return;
2473 *ppdata = (char *)SMB_REALLOC(
2474 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2475 if(*ppdata == NULL) {
2476 reply_nterror(req, NT_STATUS_NO_MEMORY);
2477 return;
2480 pdata = *ppdata;
2481 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2483 /* Realloc the params space */
2484 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2485 if(*pparams == NULL ) {
2486 reply_nterror(req, NT_STATUS_NO_MEMORY);
2487 return;
2490 params = *pparams;
2492 /* Check that the dptr is valid */
2493 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2494 reply_doserror(req, ERRDOS, ERRnofiles);
2495 return;
2498 string_set(&conn->dirpath,dptr_path(dptr_num));
2500 /* Get the wildcard mask from the dptr */
2501 if((p = dptr_wcard(dptr_num))== NULL) {
2502 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2503 reply_doserror(req, ERRDOS, ERRnofiles);
2504 return;
2507 mask = p;
2508 directory = conn->dirpath;
2510 /* Get the attr mask from the dptr */
2511 dirtype = dptr_attr(dptr_num);
2513 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2514 dptr_num, mask, dirtype,
2515 (long)conn->dirptr,
2516 dptr_TellDir(conn->dirptr)));
2518 /* Initialize per TRANS2_FIND_NEXT operation data */
2519 dptr_init_search_op(conn->dirptr);
2521 /* We don't need to check for VOL here as this is returned by
2522 a different TRANS2 call. */
2524 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2525 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2526 dont_descend = True;
2528 p = pdata;
2529 space_remaining = max_data_bytes;
2530 out_of_space = False;
2533 * Seek to the correct position. We no longer use the resume key but
2534 * depend on the last file name instead.
2537 if(*resume_name && !continue_bit) {
2538 SMB_STRUCT_STAT st;
2540 long current_pos = 0;
2542 * Remember, name_to_8_3 is called by
2543 * get_lanman2_dir_entry(), so the resume name
2544 * could be mangled. Ensure we check the unmangled name.
2547 if (mangle_is_mangled(resume_name, conn->params)) {
2548 char *new_resume_name = NULL;
2549 mangle_lookup_name_from_8_3(ctx,
2550 resume_name,
2551 &new_resume_name,
2552 conn->params);
2553 if (new_resume_name) {
2554 resume_name = new_resume_name;
2559 * Fix for NT redirector problem triggered by resume key indexes
2560 * changing between directory scans. We now return a resume key of 0
2561 * and instead look for the filename to continue from (also given
2562 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2563 * findfirst/findnext (as is usual) then the directory pointer
2564 * should already be at the correct place.
2567 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2568 } /* end if resume_name && !continue_bit */
2570 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2571 bool got_exact_match = False;
2573 /* this is a heuristic to avoid seeking the dirptr except when
2574 absolutely necessary. It allows for a filename of about 40 chars */
2575 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2576 out_of_space = True;
2577 finished = False;
2578 } else {
2579 finished = !get_lanman2_dir_entry(ctx,
2580 conn,
2581 req->flags2,
2582 mask,dirtype,info_level,
2583 requires_resume_key,dont_descend,
2584 ask_sharemode,
2585 &p,pdata,data_end,
2586 space_remaining, &out_of_space,
2587 &got_exact_match,
2588 &last_entry_off, ea_list);
2591 if (finished && out_of_space)
2592 finished = False;
2594 if (!finished && !out_of_space)
2595 numentries++;
2598 * As an optimisation if we know we aren't looking
2599 * for a wildcard name (ie. the name matches the wildcard exactly)
2600 * then we can finish on any (first) match.
2601 * This speeds up large directory searches. JRA.
2604 if(got_exact_match)
2605 finished = True;
2607 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2610 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2611 smb_fn_name(req->cmd),
2612 mask, directory, dirtype, numentries ) );
2614 /* Check if we can close the dirptr */
2615 if(close_after_request || (finished && close_if_end)) {
2616 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2617 dptr_close(&dptr_num); /* This frees up the saved mask */
2620 /* Set up the return parameter block */
2621 SSVAL(params,0,numentries);
2622 SSVAL(params,2,finished);
2623 SSVAL(params,4,0); /* Never an EA error */
2624 SSVAL(params,6,last_entry_off);
2626 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2627 max_data_bytes);
2629 return;
2632 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2634 E_md4hash(lp_servicename(SNUM(conn)),objid);
2635 return objid;
2638 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2640 SMB_ASSERT(extended_info != NULL);
2642 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2643 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2644 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2645 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2646 #ifdef SAMBA_VERSION_REVISION
2647 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2648 #endif
2649 extended_info->samba_subversion = 0;
2650 #ifdef SAMBA_VERSION_RC_RELEASE
2651 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2652 #else
2653 #ifdef SAMBA_VERSION_PRE_RELEASE
2654 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2655 #endif
2656 #endif
2657 #ifdef SAMBA_VERSION_VENDOR_PATCH
2658 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2659 #endif
2660 extended_info->samba_gitcommitdate = 0;
2661 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2662 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2663 #endif
2665 memset(extended_info->samba_version_string, 0,
2666 sizeof(extended_info->samba_version_string));
2668 snprintf (extended_info->samba_version_string,
2669 sizeof(extended_info->samba_version_string),
2670 "%s", samba_version_string());
2673 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2674 TALLOC_CTX *mem_ctx,
2675 uint16_t info_level,
2676 uint16_t flags2,
2677 unsigned int max_data_bytes,
2678 char **ppdata,
2679 int *ret_data_len)
2681 char *pdata, *end_data;
2682 int data_len = 0, len;
2683 const char *vname = volume_label(SNUM(conn));
2684 int snum = SNUM(conn);
2685 char *fstype = lp_fstype(SNUM(conn));
2686 uint32 additional_flags = 0;
2687 struct smb_filename *smb_fname_dot = NULL;
2688 SMB_STRUCT_STAT st;
2689 NTSTATUS status;
2691 if (IS_IPC(conn)) {
2692 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2693 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2694 "info level (0x%x) on IPC$.\n",
2695 (unsigned int)info_level));
2696 return NT_STATUS_ACCESS_DENIED;
2700 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2702 status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL,
2703 &smb_fname_dot);
2704 if (!NT_STATUS_IS_OK(status)) {
2705 return status;
2708 if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) {
2709 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2710 TALLOC_FREE(smb_fname_dot);
2711 return map_nt_error_from_unix(errno);
2714 st = smb_fname_dot->st;
2715 TALLOC_FREE(smb_fname_dot);
2717 *ppdata = (char *)SMB_REALLOC(
2718 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2719 if (*ppdata == NULL) {
2720 return NT_STATUS_NO_MEMORY;
2723 pdata = *ppdata;
2724 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2725 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2727 switch (info_level) {
2728 case SMB_INFO_ALLOCATION:
2730 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2731 data_len = 18;
2732 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2733 return map_nt_error_from_unix(errno);
2736 block_size = lp_block_size(snum);
2737 if (bsize < block_size) {
2738 uint64_t factor = block_size/bsize;
2739 bsize = block_size;
2740 dsize /= factor;
2741 dfree /= factor;
2743 if (bsize > block_size) {
2744 uint64_t factor = bsize/block_size;
2745 bsize = block_size;
2746 dsize *= factor;
2747 dfree *= factor;
2749 bytes_per_sector = 512;
2750 sectors_per_unit = bsize/bytes_per_sector;
2752 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2753 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2754 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2756 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2757 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2758 SIVAL(pdata,l1_cUnit,dsize);
2759 SIVAL(pdata,l1_cUnitAvail,dfree);
2760 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2761 break;
2764 case SMB_INFO_VOLUME:
2765 /* Return volume name */
2767 * Add volume serial number - hash of a combination of
2768 * the called hostname and the service name.
2770 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2772 * Win2k3 and previous mess this up by sending a name length
2773 * one byte short. I believe only older clients (OS/2 Win9x) use
2774 * this call so try fixing this by adding a terminating null to
2775 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2777 len = srvstr_push(
2778 pdata, flags2,
2779 pdata+l2_vol_szVolLabel, vname,
2780 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2781 STR_NOALIGN|STR_TERMINATE);
2782 SCVAL(pdata,l2_vol_cch,len);
2783 data_len = l2_vol_szVolLabel + len;
2784 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2785 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2786 len, vname));
2787 break;
2789 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2790 case SMB_FS_ATTRIBUTE_INFORMATION:
2792 additional_flags = 0;
2793 #if defined(HAVE_SYS_QUOTAS)
2794 additional_flags |= FILE_VOLUME_QUOTAS;
2795 #endif
2797 if(lp_nt_acl_support(SNUM(conn))) {
2798 additional_flags |= FILE_PERSISTENT_ACLS;
2801 /* Capabilities are filled in at connection time through STATVFS call */
2802 additional_flags |= conn->fs_capabilities;
2804 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2805 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2806 additional_flags); /* FS ATTRIBUTES */
2808 SIVAL(pdata,4,255); /* Max filename component length */
2809 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2810 and will think we can't do long filenames */
2811 len = srvstr_push(pdata, flags2, pdata+12, fstype,
2812 PTR_DIFF(end_data, pdata+12),
2813 STR_UNICODE);
2814 SIVAL(pdata,8,len);
2815 data_len = 12 + len;
2816 break;
2818 case SMB_QUERY_FS_LABEL_INFO:
2819 case SMB_FS_LABEL_INFORMATION:
2820 len = srvstr_push(pdata, flags2, pdata+4, vname,
2821 PTR_DIFF(end_data, pdata+4), 0);
2822 data_len = 4 + len;
2823 SIVAL(pdata,0,len);
2824 break;
2826 case SMB_QUERY_FS_VOLUME_INFO:
2827 case SMB_FS_VOLUME_INFORMATION:
2830 * Add volume serial number - hash of a combination of
2831 * the called hostname and the service name.
2833 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2834 (str_checksum(get_local_machine_name())<<16));
2836 /* Max label len is 32 characters. */
2837 len = srvstr_push(pdata, flags2, pdata+18, vname,
2838 PTR_DIFF(end_data, pdata+18),
2839 STR_UNICODE);
2840 SIVAL(pdata,12,len);
2841 data_len = 18+len;
2843 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2844 (int)strlen(vname),vname, lp_servicename(snum)));
2845 break;
2847 case SMB_QUERY_FS_SIZE_INFO:
2848 case SMB_FS_SIZE_INFORMATION:
2850 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2851 data_len = 24;
2852 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2853 return map_nt_error_from_unix(errno);
2855 block_size = lp_block_size(snum);
2856 if (bsize < block_size) {
2857 uint64_t factor = block_size/bsize;
2858 bsize = block_size;
2859 dsize /= factor;
2860 dfree /= factor;
2862 if (bsize > block_size) {
2863 uint64_t factor = bsize/block_size;
2864 bsize = block_size;
2865 dsize *= factor;
2866 dfree *= factor;
2868 bytes_per_sector = 512;
2869 sectors_per_unit = bsize/bytes_per_sector;
2870 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2871 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2872 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2873 SBIG_UINT(pdata,0,dsize);
2874 SBIG_UINT(pdata,8,dfree);
2875 SIVAL(pdata,16,sectors_per_unit);
2876 SIVAL(pdata,20,bytes_per_sector);
2877 break;
2880 case SMB_FS_FULL_SIZE_INFORMATION:
2882 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2883 data_len = 32;
2884 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2885 return map_nt_error_from_unix(errno);
2887 block_size = lp_block_size(snum);
2888 if (bsize < block_size) {
2889 uint64_t factor = block_size/bsize;
2890 bsize = block_size;
2891 dsize /= factor;
2892 dfree /= factor;
2894 if (bsize > block_size) {
2895 uint64_t factor = bsize/block_size;
2896 bsize = block_size;
2897 dsize *= factor;
2898 dfree *= factor;
2900 bytes_per_sector = 512;
2901 sectors_per_unit = bsize/bytes_per_sector;
2902 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2903 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2904 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2905 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2906 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2907 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2908 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2909 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2910 break;
2913 case SMB_QUERY_FS_DEVICE_INFO:
2914 case SMB_FS_DEVICE_INFORMATION:
2915 data_len = 8;
2916 SIVAL(pdata,0,0); /* dev type */
2917 SIVAL(pdata,4,0); /* characteristics */
2918 break;
2920 #ifdef HAVE_SYS_QUOTAS
2921 case SMB_FS_QUOTA_INFORMATION:
2923 * what we have to send --metze:
2925 * Unknown1: 24 NULL bytes
2926 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2927 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2928 * Quota Flags: 2 byte :
2929 * Unknown3: 6 NULL bytes
2931 * 48 bytes total
2933 * details for Quota Flags:
2935 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2936 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2937 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2938 * 0x0001 Enable Quotas: enable quota for this fs
2942 /* we need to fake up a fsp here,
2943 * because its not send in this call
2945 files_struct fsp;
2946 SMB_NTQUOTA_STRUCT quotas;
2948 ZERO_STRUCT(fsp);
2949 ZERO_STRUCT(quotas);
2951 fsp.conn = conn;
2952 fsp.fnum = -1;
2954 /* access check */
2955 if (conn->server_info->utok.uid != sec_initial_uid()) {
2956 DEBUG(0,("set_user_quota: access_denied "
2957 "service [%s] user [%s]\n",
2958 lp_servicename(SNUM(conn)),
2959 conn->server_info->unix_name));
2960 return NT_STATUS_ACCESS_DENIED;
2963 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2964 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2965 return map_nt_error_from_unix(errno);
2968 data_len = 48;
2970 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2971 lp_servicename(SNUM(conn))));
2973 /* Unknown1 24 NULL bytes*/
2974 SBIG_UINT(pdata,0,(uint64_t)0);
2975 SBIG_UINT(pdata,8,(uint64_t)0);
2976 SBIG_UINT(pdata,16,(uint64_t)0);
2978 /* Default Soft Quota 8 bytes */
2979 SBIG_UINT(pdata,24,quotas.softlim);
2981 /* Default Hard Quota 8 bytes */
2982 SBIG_UINT(pdata,32,quotas.hardlim);
2984 /* Quota flag 2 bytes */
2985 SSVAL(pdata,40,quotas.qflags);
2987 /* Unknown3 6 NULL bytes */
2988 SSVAL(pdata,42,0);
2989 SIVAL(pdata,44,0);
2991 break;
2993 #endif /* HAVE_SYS_QUOTAS */
2994 case SMB_FS_OBJECTID_INFORMATION:
2996 unsigned char objid[16];
2997 struct smb_extended_info extended_info;
2998 memcpy(pdata,create_volume_objectid(conn, objid),16);
2999 samba_extended_info_version (&extended_info);
3000 SIVAL(pdata,16,extended_info.samba_magic);
3001 SIVAL(pdata,20,extended_info.samba_version);
3002 SIVAL(pdata,24,extended_info.samba_subversion);
3003 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3004 memcpy(pdata+36,extended_info.samba_version_string,28);
3005 data_len = 64;
3006 break;
3010 * Query the version and capabilities of the CIFS UNIX extensions
3011 * in use.
3014 case SMB_QUERY_CIFS_UNIX_INFO:
3016 bool large_write = lp_min_receive_file_size() &&
3017 !srv_is_signing_active(smbd_server_conn);
3018 bool large_read = !srv_is_signing_active(smbd_server_conn);
3019 int encrypt_caps = 0;
3021 if (!lp_unix_extensions()) {
3022 return NT_STATUS_INVALID_LEVEL;
3025 switch (conn->encrypt_level) {
3026 case 0:
3027 encrypt_caps = 0;
3028 break;
3029 case 1:
3030 case Auto:
3031 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3032 break;
3033 case Required:
3034 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3035 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3036 large_write = false;
3037 large_read = false;
3038 break;
3041 data_len = 12;
3042 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3043 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3045 /* We have POSIX ACLs, pathname, encryption,
3046 * large read/write, and locking capability. */
3048 SBIG_UINT(pdata,4,((uint64_t)(
3049 CIFS_UNIX_POSIX_ACLS_CAP|
3050 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3051 CIFS_UNIX_FCNTL_LOCKS_CAP|
3052 CIFS_UNIX_EXTATTR_CAP|
3053 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3054 encrypt_caps|
3055 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3056 (large_write ?
3057 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3058 break;
3061 case SMB_QUERY_POSIX_FS_INFO:
3063 int rc;
3064 vfs_statvfs_struct svfs;
3066 if (!lp_unix_extensions()) {
3067 return NT_STATUS_INVALID_LEVEL;
3070 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3072 if (!rc) {
3073 data_len = 56;
3074 SIVAL(pdata,0,svfs.OptimalTransferSize);
3075 SIVAL(pdata,4,svfs.BlockSize);
3076 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3077 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3078 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3079 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3080 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3081 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3082 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3083 #ifdef EOPNOTSUPP
3084 } else if (rc == EOPNOTSUPP) {
3085 return NT_STATUS_INVALID_LEVEL;
3086 #endif /* EOPNOTSUPP */
3087 } else {
3088 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3089 return NT_STATUS_DOS(ERRSRV, ERRerror);
3091 break;
3094 case SMB_QUERY_POSIX_WHOAMI:
3096 uint32_t flags = 0;
3097 uint32_t sid_bytes;
3098 int i;
3100 if (!lp_unix_extensions()) {
3101 return NT_STATUS_INVALID_LEVEL;
3104 if (max_data_bytes < 40) {
3105 return NT_STATUS_BUFFER_TOO_SMALL;
3108 /* We ARE guest if global_sid_Builtin_Guests is
3109 * in our list of SIDs.
3111 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3112 conn->server_info->ptok)) {
3113 flags |= SMB_WHOAMI_GUEST;
3116 /* We are NOT guest if global_sid_Authenticated_Users
3117 * is in our list of SIDs.
3119 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3120 conn->server_info->ptok)) {
3121 flags &= ~SMB_WHOAMI_GUEST;
3124 /* NOTE: 8 bytes for UID/GID, irrespective of native
3125 * platform size. This matches
3126 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3128 data_len = 4 /* flags */
3129 + 4 /* flag mask */
3130 + 8 /* uid */
3131 + 8 /* gid */
3132 + 4 /* ngroups */
3133 + 4 /* num_sids */
3134 + 4 /* SID bytes */
3135 + 4 /* pad/reserved */
3136 + (conn->server_info->utok.ngroups * 8)
3137 /* groups list */
3138 + (conn->server_info->ptok->num_sids *
3139 SID_MAX_SIZE)
3140 /* SID list */;
3142 SIVAL(pdata, 0, flags);
3143 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3144 SBIG_UINT(pdata, 8,
3145 (uint64_t)conn->server_info->utok.uid);
3146 SBIG_UINT(pdata, 16,
3147 (uint64_t)conn->server_info->utok.gid);
3150 if (data_len >= max_data_bytes) {
3151 /* Potential overflow, skip the GIDs and SIDs. */
3153 SIVAL(pdata, 24, 0); /* num_groups */
3154 SIVAL(pdata, 28, 0); /* num_sids */
3155 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3156 SIVAL(pdata, 36, 0); /* reserved */
3158 data_len = 40;
3159 break;
3162 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3163 SIVAL(pdata, 28, conn->server_info->num_sids);
3165 /* We walk the SID list twice, but this call is fairly
3166 * infrequent, and I don't expect that it's performance
3167 * sensitive -- jpeach
3169 for (i = 0, sid_bytes = 0;
3170 i < conn->server_info->ptok->num_sids; ++i) {
3171 sid_bytes += ndr_size_dom_sid(
3172 &conn->server_info->ptok->user_sids[i],
3173 NULL,
3177 /* SID list byte count */
3178 SIVAL(pdata, 32, sid_bytes);
3180 /* 4 bytes pad/reserved - must be zero */
3181 SIVAL(pdata, 36, 0);
3182 data_len = 40;
3184 /* GID list */
3185 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3186 SBIG_UINT(pdata, data_len,
3187 (uint64_t)conn->server_info->utok.groups[i]);
3188 data_len += 8;
3191 /* SID list */
3192 for (i = 0;
3193 i < conn->server_info->ptok->num_sids; ++i) {
3194 int sid_len = ndr_size_dom_sid(
3195 &conn->server_info->ptok->user_sids[i],
3196 NULL,
3199 sid_linearize(pdata + data_len, sid_len,
3200 &conn->server_info->ptok->user_sids[i]);
3201 data_len += sid_len;
3204 break;
3207 case SMB_MAC_QUERY_FS_INFO:
3209 * Thursby MAC extension... ONLY on NTFS filesystems
3210 * once we do streams then we don't need this
3212 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3213 data_len = 88;
3214 SIVAL(pdata,84,0x100); /* Don't support mac... */
3215 break;
3217 /* drop through */
3218 default:
3219 return NT_STATUS_INVALID_LEVEL;
3222 *ret_data_len = data_len;
3223 return NT_STATUS_OK;
3226 /****************************************************************************
3227 Reply to a TRANS2_QFSINFO (query filesystem info).
3228 ****************************************************************************/
3230 static void call_trans2qfsinfo(connection_struct *conn,
3231 struct smb_request *req,
3232 char **pparams, int total_params,
3233 char **ppdata, int total_data,
3234 unsigned int max_data_bytes)
3236 char *params = *pparams;
3237 uint16_t info_level;
3238 int data_len = 0;
3239 NTSTATUS status;
3241 if (total_params < 2) {
3242 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3243 return;
3246 info_level = SVAL(params,0);
3248 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3249 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3250 DEBUG(0,("call_trans2qfsinfo: encryption required "
3251 "and info level 0x%x sent.\n",
3252 (unsigned int)info_level));
3253 exit_server_cleanly("encryption required "
3254 "on connection");
3255 return;
3259 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3261 status = smbd_do_qfsinfo(conn, req,
3262 info_level,
3263 req->flags2,
3264 max_data_bytes,
3265 ppdata, &data_len);
3266 if (!NT_STATUS_IS_OK(status)) {
3267 reply_nterror(req, status);
3268 return;
3271 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3272 max_data_bytes);
3274 DEBUG( 4, ( "%s info_level = %d\n",
3275 smb_fn_name(req->cmd), info_level) );
3277 return;
3280 /****************************************************************************
3281 Reply to a TRANS2_SETFSINFO (set filesystem info).
3282 ****************************************************************************/
3284 static void call_trans2setfsinfo(connection_struct *conn,
3285 struct smb_request *req,
3286 char **pparams, int total_params,
3287 char **ppdata, int total_data,
3288 unsigned int max_data_bytes)
3290 char *pdata = *ppdata;
3291 char *params = *pparams;
3292 uint16 info_level;
3294 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3296 /* */
3297 if (total_params < 4) {
3298 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3299 total_params));
3300 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3301 return;
3304 info_level = SVAL(params,2);
3306 if (IS_IPC(conn)) {
3307 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3308 info_level != SMB_SET_CIFS_UNIX_INFO) {
3309 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3310 "info level (0x%x) on IPC$.\n",
3311 (unsigned int)info_level));
3312 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3313 return;
3317 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3318 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3319 DEBUG(0,("call_trans2setfsinfo: encryption required "
3320 "and info level 0x%x sent.\n",
3321 (unsigned int)info_level));
3322 exit_server_cleanly("encryption required "
3323 "on connection");
3324 return;
3328 switch(info_level) {
3329 case SMB_SET_CIFS_UNIX_INFO:
3331 uint16 client_unix_major;
3332 uint16 client_unix_minor;
3333 uint32 client_unix_cap_low;
3334 uint32 client_unix_cap_high;
3336 if (!lp_unix_extensions()) {
3337 reply_nterror(req,
3338 NT_STATUS_INVALID_LEVEL);
3339 return;
3342 /* There should be 12 bytes of capabilities set. */
3343 if (total_data < 8) {
3344 reply_nterror(
3345 req,
3346 NT_STATUS_INVALID_PARAMETER);
3347 return;
3349 client_unix_major = SVAL(pdata,0);
3350 client_unix_minor = SVAL(pdata,2);
3351 client_unix_cap_low = IVAL(pdata,4);
3352 client_unix_cap_high = IVAL(pdata,8);
3353 /* Just print these values for now. */
3354 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3355 cap_low = 0x%x, cap_high = 0x%x\n",
3356 (unsigned int)client_unix_major,
3357 (unsigned int)client_unix_minor,
3358 (unsigned int)client_unix_cap_low,
3359 (unsigned int)client_unix_cap_high ));
3361 /* Here is where we must switch to posix pathname processing... */
3362 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3363 lp_set_posix_pathnames();
3364 mangle_change_to_posix();
3367 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3368 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3369 /* Client that knows how to do posix locks,
3370 * but not posix open/mkdir operations. Set a
3371 * default type for read/write checks. */
3373 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3376 break;
3379 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3381 NTSTATUS status;
3382 size_t param_len = 0;
3383 size_t data_len = total_data;
3385 if (!lp_unix_extensions()) {
3386 reply_nterror(
3387 req,
3388 NT_STATUS_INVALID_LEVEL);
3389 return;
3392 if (lp_smb_encrypt(SNUM(conn)) == false) {
3393 reply_nterror(
3394 req,
3395 NT_STATUS_NOT_SUPPORTED);
3396 return;
3399 DEBUG( 4,("call_trans2setfsinfo: "
3400 "request transport encryption.\n"));
3402 status = srv_request_encryption_setup(conn,
3403 (unsigned char **)ppdata,
3404 &data_len,
3405 (unsigned char **)pparams,
3406 &param_len);
3408 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3409 !NT_STATUS_IS_OK(status)) {
3410 reply_nterror(req, status);
3411 return;
3414 send_trans2_replies(conn, req,
3415 *pparams,
3416 param_len,
3417 *ppdata,
3418 data_len,
3419 max_data_bytes);
3421 if (NT_STATUS_IS_OK(status)) {
3422 /* Server-side transport
3423 * encryption is now *on*. */
3424 status = srv_encryption_start(conn);
3425 if (!NT_STATUS_IS_OK(status)) {
3426 exit_server_cleanly(
3427 "Failure in setting "
3428 "up encrypted transport");
3431 return;
3434 case SMB_FS_QUOTA_INFORMATION:
3436 files_struct *fsp = NULL;
3437 SMB_NTQUOTA_STRUCT quotas;
3439 ZERO_STRUCT(quotas);
3441 /* access check */
3442 if ((conn->server_info->utok.uid != sec_initial_uid())
3443 ||!CAN_WRITE(conn)) {
3444 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3445 lp_servicename(SNUM(conn)),
3446 conn->server_info->unix_name));
3447 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3448 return;
3451 /* note: normaly there're 48 bytes,
3452 * but we didn't use the last 6 bytes for now
3453 * --metze
3455 fsp = file_fsp(req, SVAL(params,0));
3457 if (!check_fsp_ntquota_handle(conn, req,
3458 fsp)) {
3459 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3460 reply_nterror(
3461 req, NT_STATUS_INVALID_HANDLE);
3462 return;
3465 if (total_data < 42) {
3466 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3467 total_data));
3468 reply_nterror(
3469 req,
3470 NT_STATUS_INVALID_PARAMETER);
3471 return;
3474 /* unknown_1 24 NULL bytes in pdata*/
3476 /* the soft quotas 8 bytes (uint64_t)*/
3477 quotas.softlim = (uint64_t)IVAL(pdata,24);
3478 #ifdef LARGE_SMB_OFF_T
3479 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3480 #else /* LARGE_SMB_OFF_T */
3481 if ((IVAL(pdata,28) != 0)&&
3482 ((quotas.softlim != 0xFFFFFFFF)||
3483 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3484 /* more than 32 bits? */
3485 reply_nterror(
3486 req,
3487 NT_STATUS_INVALID_PARAMETER);
3488 return;
3490 #endif /* LARGE_SMB_OFF_T */
3492 /* the hard quotas 8 bytes (uint64_t)*/
3493 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3494 #ifdef LARGE_SMB_OFF_T
3495 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3496 #else /* LARGE_SMB_OFF_T */
3497 if ((IVAL(pdata,36) != 0)&&
3498 ((quotas.hardlim != 0xFFFFFFFF)||
3499 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3500 /* more than 32 bits? */
3501 reply_nterror(
3502 req,
3503 NT_STATUS_INVALID_PARAMETER);
3504 return;
3506 #endif /* LARGE_SMB_OFF_T */
3508 /* quota_flags 2 bytes **/
3509 quotas.qflags = SVAL(pdata,40);
3511 /* unknown_2 6 NULL bytes follow*/
3513 /* now set the quotas */
3514 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3515 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3516 reply_nterror(req, map_nt_error_from_unix(errno));
3517 return;
3520 break;
3522 default:
3523 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3524 info_level));
3525 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3526 return;
3527 break;
3531 * sending this reply works fine,
3532 * but I'm not sure it's the same
3533 * like windows do...
3534 * --metze
3536 reply_outbuf(req, 10, 0);
3539 #if defined(HAVE_POSIX_ACLS)
3540 /****************************************************************************
3541 Utility function to count the number of entries in a POSIX acl.
3542 ****************************************************************************/
3544 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3546 unsigned int ace_count = 0;
3547 int entry_id = SMB_ACL_FIRST_ENTRY;
3548 SMB_ACL_ENTRY_T entry;
3550 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3551 /* get_next... */
3552 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3553 entry_id = SMB_ACL_NEXT_ENTRY;
3555 ace_count++;
3557 return ace_count;
3560 /****************************************************************************
3561 Utility function to marshall a POSIX acl into wire format.
3562 ****************************************************************************/
3564 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3566 int entry_id = SMB_ACL_FIRST_ENTRY;
3567 SMB_ACL_ENTRY_T entry;
3569 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3570 SMB_ACL_TAG_T tagtype;
3571 SMB_ACL_PERMSET_T permset;
3572 unsigned char perms = 0;
3573 unsigned int own_grp;
3575 /* get_next... */
3576 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3577 entry_id = SMB_ACL_NEXT_ENTRY;
3580 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3581 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3582 return False;
3585 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3586 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3587 return False;
3590 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3591 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3592 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3594 SCVAL(pdata,1,perms);
3596 switch (tagtype) {
3597 case SMB_ACL_USER_OBJ:
3598 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3599 own_grp = (unsigned int)pst->st_ex_uid;
3600 SIVAL(pdata,2,own_grp);
3601 SIVAL(pdata,6,0);
3602 break;
3603 case SMB_ACL_USER:
3605 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3606 if (!puid) {
3607 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3608 return False;
3610 own_grp = (unsigned int)*puid;
3611 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3612 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3613 SIVAL(pdata,2,own_grp);
3614 SIVAL(pdata,6,0);
3615 break;
3617 case SMB_ACL_GROUP_OBJ:
3618 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3619 own_grp = (unsigned int)pst->st_ex_gid;
3620 SIVAL(pdata,2,own_grp);
3621 SIVAL(pdata,6,0);
3622 break;
3623 case SMB_ACL_GROUP:
3625 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3626 if (!pgid) {
3627 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3628 return False;
3630 own_grp = (unsigned int)*pgid;
3631 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3632 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3633 SIVAL(pdata,2,own_grp);
3634 SIVAL(pdata,6,0);
3635 break;
3637 case SMB_ACL_MASK:
3638 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3639 SIVAL(pdata,2,0xFFFFFFFF);
3640 SIVAL(pdata,6,0xFFFFFFFF);
3641 break;
3642 case SMB_ACL_OTHER:
3643 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3644 SIVAL(pdata,2,0xFFFFFFFF);
3645 SIVAL(pdata,6,0xFFFFFFFF);
3646 break;
3647 default:
3648 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3649 return False;
3651 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3654 return True;
3656 #endif
3658 /****************************************************************************
3659 Store the FILE_UNIX_BASIC info.
3660 ****************************************************************************/
3662 static char *store_file_unix_basic(connection_struct *conn,
3663 char *pdata,
3664 files_struct *fsp,
3665 const SMB_STRUCT_STAT *psbuf)
3667 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3668 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3670 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3671 pdata += 8;
3673 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3674 pdata += 8;
3676 put_long_date_timespec(pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3677 put_long_date_timespec(pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3678 put_long_date_timespec(pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3679 pdata += 24;
3681 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3682 SIVAL(pdata,4,0);
3683 pdata += 8;
3685 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3686 SIVAL(pdata,4,0);
3687 pdata += 8;
3689 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3690 pdata += 4;
3692 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3693 SIVAL(pdata,4,0);
3694 pdata += 8;
3696 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3697 SIVAL(pdata,4,0);
3698 pdata += 8;
3700 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3701 pdata += 8;
3703 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3704 SIVAL(pdata,4,0);
3705 pdata += 8;
3707 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3708 SIVAL(pdata,4,0);
3709 pdata += 8;
3711 return pdata;
3714 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3715 * the chflags(2) (or equivalent) flags.
3717 * XXX: this really should be behind the VFS interface. To do this, we would
3718 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3719 * Each VFS module could then implement its own mapping as appropriate for the
3720 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3722 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3723 info2_flags_map[] =
3725 #ifdef UF_NODUMP
3726 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3727 #endif
3729 #ifdef UF_IMMUTABLE
3730 { UF_IMMUTABLE, EXT_IMMUTABLE },
3731 #endif
3733 #ifdef UF_APPEND
3734 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3735 #endif
3737 #ifdef UF_HIDDEN
3738 { UF_HIDDEN, EXT_HIDDEN },
3739 #endif
3741 /* Do not remove. We need to guarantee that this array has at least one
3742 * entry to build on HP-UX.
3744 { 0, 0 }
3748 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3749 uint32 *smb_fflags, uint32 *smb_fmask)
3751 int i;
3753 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3754 *smb_fmask |= info2_flags_map[i].smb_fflag;
3755 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3756 *smb_fflags |= info2_flags_map[i].smb_fflag;
3761 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3762 const uint32 smb_fflags,
3763 const uint32 smb_fmask,
3764 int *stat_fflags)
3766 uint32 max_fmask = 0;
3767 int i;
3769 *stat_fflags = psbuf->st_ex_flags;
3771 /* For each flags requested in smb_fmask, check the state of the
3772 * corresponding flag in smb_fflags and set or clear the matching
3773 * stat flag.
3776 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3777 max_fmask |= info2_flags_map[i].smb_fflag;
3778 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3779 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3780 *stat_fflags |= info2_flags_map[i].stat_fflag;
3781 } else {
3782 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3787 /* If smb_fmask is asking to set any bits that are not supported by
3788 * our flag mappings, we should fail.
3790 if ((smb_fmask & max_fmask) != smb_fmask) {
3791 return False;
3794 return True;
3798 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3799 * of file flags and birth (create) time.
3801 static char *store_file_unix_basic_info2(connection_struct *conn,
3802 char *pdata,
3803 files_struct *fsp,
3804 const SMB_STRUCT_STAT *psbuf)
3806 uint32 file_flags = 0;
3807 uint32 flags_mask = 0;
3809 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3811 /* Create (birth) time 64 bit */
3812 put_long_date_timespec(pdata, psbuf->st_ex_btime);
3813 pdata += 8;
3815 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3816 SIVAL(pdata, 0, file_flags); /* flags */
3817 SIVAL(pdata, 4, flags_mask); /* mask */
3818 pdata += 8;
3820 return pdata;
3823 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3824 const struct stream_struct *streams,
3825 char *data,
3826 unsigned int max_data_bytes,
3827 unsigned int *data_size)
3829 unsigned int i;
3830 unsigned int ofs = 0;
3832 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3833 unsigned int next_offset;
3834 size_t namelen;
3835 smb_ucs2_t *namebuf;
3837 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3838 streams[i].name, &namelen) ||
3839 namelen <= 2)
3841 return NT_STATUS_INVALID_PARAMETER;
3845 * name_buf is now null-terminated, we need to marshall as not
3846 * terminated
3849 namelen -= 2;
3851 SIVAL(data, ofs+4, namelen);
3852 SOFF_T(data, ofs+8, streams[i].size);
3853 SOFF_T(data, ofs+16, streams[i].alloc_size);
3854 memcpy(data+ofs+24, namebuf, namelen);
3855 TALLOC_FREE(namebuf);
3857 next_offset = ofs + 24 + namelen;
3859 if (i == num_streams-1) {
3860 SIVAL(data, ofs, 0);
3862 else {
3863 unsigned int align = ndr_align_size(next_offset, 8);
3865 memset(data+next_offset, 0, align);
3866 next_offset += align;
3868 SIVAL(data, ofs, next_offset - ofs);
3869 ofs = next_offset;
3872 ofs = next_offset;
3875 *data_size = ofs;
3877 return NT_STATUS_OK;
3880 /****************************************************************************
3881 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3882 ****************************************************************************/
3884 static void call_trans2qpipeinfo(connection_struct *conn,
3885 struct smb_request *req,
3886 unsigned int tran_call,
3887 char **pparams, int total_params,
3888 char **ppdata, int total_data,
3889 unsigned int max_data_bytes)
3891 char *params = *pparams;
3892 char *pdata = *ppdata;
3893 unsigned int data_size = 0;
3894 unsigned int param_size = 2;
3895 uint16 info_level;
3896 files_struct *fsp;
3898 if (!params) {
3899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3900 return;
3903 if (total_params < 4) {
3904 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3905 return;
3908 fsp = file_fsp(req, SVAL(params,0));
3909 if (!fsp_is_np(fsp)) {
3910 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3911 return;
3914 info_level = SVAL(params,2);
3916 *pparams = (char *)SMB_REALLOC(*pparams,2);
3917 if (*pparams == NULL) {
3918 reply_nterror(req, NT_STATUS_NO_MEMORY);
3919 return;
3921 params = *pparams;
3922 SSVAL(params,0,0);
3923 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3924 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3925 if (*ppdata == NULL ) {
3926 reply_nterror(req, NT_STATUS_NO_MEMORY);
3927 return;
3929 pdata = *ppdata;
3931 switch (info_level) {
3932 case SMB_FILE_STANDARD_INFORMATION:
3933 memset(pdata,0,24);
3934 SOFF_T(pdata,0,4096LL);
3935 SIVAL(pdata,16,1);
3936 SIVAL(pdata,20,1);
3937 data_size = 24;
3938 break;
3940 default:
3941 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3942 return;
3945 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3946 max_data_bytes);
3948 return;
3951 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3952 TALLOC_CTX *mem_ctx,
3953 uint16_t info_level,
3954 files_struct *fsp,
3955 const struct smb_filename *smb_fname,
3956 bool delete_pending,
3957 struct timespec write_time_ts,
3958 bool ms_dfs_link,
3959 struct ea_list *ea_list,
3960 int lock_data_count,
3961 char *lock_data,
3962 uint16_t flags2,
3963 unsigned int max_data_bytes,
3964 char **ppdata,
3965 unsigned int *pdata_size)
3967 char *pdata = *ppdata;
3968 char *dstart, *dend;
3969 unsigned int data_size;
3970 struct timespec create_time_ts, mtime_ts, atime_ts;
3971 time_t create_time, mtime, atime;
3972 SMB_STRUCT_STAT sbuf;
3973 char *p;
3974 char *base_name;
3975 char *dos_fname;
3976 int mode;
3977 int nlink;
3978 NTSTATUS status;
3979 uint64_t file_size = 0;
3980 uint64_t pos = 0;
3981 uint64_t allocation_size = 0;
3982 uint64_t file_index = 0;
3983 uint32_t access_mask = 0;
3985 sbuf = smb_fname->st;
3987 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3988 return NT_STATUS_INVALID_LEVEL;
3991 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
3992 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
3993 info_level, max_data_bytes));
3995 if (ms_dfs_link) {
3996 mode = dos_mode_msdfs(conn, smb_fname);
3997 } else {
3998 mode = dos_mode(conn, smb_fname);
4000 if (!mode)
4001 mode = FILE_ATTRIBUTE_NORMAL;
4003 nlink = sbuf.st_ex_nlink;
4005 if (nlink && (mode&aDIR)) {
4006 nlink = 1;
4009 if ((nlink > 0) && delete_pending) {
4010 nlink -= 1;
4013 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4014 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4015 if (*ppdata == NULL) {
4016 return NT_STATUS_NO_MEMORY;
4018 pdata = *ppdata;
4019 dstart = pdata;
4020 dend = dstart + data_size - 1;
4022 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4023 update_stat_ex_mtime(&sbuf, write_time_ts);
4026 create_time_ts = sbuf.st_ex_btime;
4027 mtime_ts = sbuf.st_ex_mtime;
4028 atime_ts = sbuf.st_ex_atime;
4030 if (lp_dos_filetime_resolution(SNUM(conn))) {
4031 dos_filetime_timespec(&create_time_ts);
4032 dos_filetime_timespec(&mtime_ts);
4033 dos_filetime_timespec(&atime_ts);
4036 create_time = convert_timespec_to_time_t(create_time_ts);
4037 mtime = convert_timespec_to_time_t(mtime_ts);
4038 atime = convert_timespec_to_time_t(atime_ts);
4040 p = strrchr_m(smb_fname->base_name,'/');
4041 if (!p)
4042 base_name = smb_fname->base_name;
4043 else
4044 base_name = p+1;
4046 /* NT expects the name to be in an exact form of the *full*
4047 filename. See the trans2 torture test */
4048 if (ISDOT(base_name)) {
4049 dos_fname = talloc_strdup(mem_ctx, "\\");
4050 if (!dos_fname) {
4051 return NT_STATUS_NO_MEMORY;
4053 } else {
4054 dos_fname = talloc_asprintf(mem_ctx,
4055 "\\%s",
4056 smb_fname->base_name);
4057 if (!dos_fname) {
4058 return NT_STATUS_NO_MEMORY;
4060 if (is_ntfs_stream_smb_fname(smb_fname)) {
4061 dos_fname = talloc_asprintf(dos_fname, "%s",
4062 smb_fname->stream_name);
4063 if (!dos_fname) {
4064 return NT_STATUS_NO_MEMORY;
4068 string_replace(dos_fname, '/', '\\');
4071 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, &sbuf);
4073 if (!fsp) {
4074 /* Do we have this path open ? */
4075 files_struct *fsp1;
4076 struct file_id fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4077 fsp1 = file_find_di_first(fileid);
4078 if (fsp1 && fsp1->initial_allocation_size) {
4079 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4083 if (!(mode & aDIR)) {
4084 file_size = get_file_size_stat(&sbuf);
4087 if (fsp) {
4088 pos = fsp->fh->position_information;
4091 if (fsp) {
4092 access_mask = fsp->access_mask;
4093 } else {
4094 /* GENERIC_EXECUTE mapping from Windows */
4095 access_mask = 0x12019F;
4098 /* This should be an index number - looks like
4099 dev/ino to me :-)
4101 I think this causes us to fail the IFSKIT
4102 BasicFileInformationTest. -tpot */
4103 file_index = ((sbuf.st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4104 file_index |= ((uint64_t)((sbuf.st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4106 switch (info_level) {
4107 case SMB_INFO_STANDARD:
4108 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4109 data_size = 22;
4110 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4111 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4112 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4113 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4114 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4115 SSVAL(pdata,l1_attrFile,mode);
4116 break;
4118 case SMB_INFO_QUERY_EA_SIZE:
4120 unsigned int ea_size =
4121 estimate_ea_size(conn, fsp,
4122 smb_fname->base_name);
4123 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4124 data_size = 26;
4125 srv_put_dos_date2(pdata,0,create_time);
4126 srv_put_dos_date2(pdata,4,atime);
4127 srv_put_dos_date2(pdata,8,mtime); /* write time */
4128 SIVAL(pdata,12,(uint32)file_size);
4129 SIVAL(pdata,16,(uint32)allocation_size);
4130 SSVAL(pdata,20,mode);
4131 SIVAL(pdata,22,ea_size);
4132 break;
4135 case SMB_INFO_IS_NAME_VALID:
4136 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4137 if (fsp) {
4138 /* os/2 needs this ? really ?*/
4139 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4141 /* This is only reached for qpathinfo */
4142 data_size = 0;
4143 break;
4145 case SMB_INFO_QUERY_EAS_FROM_LIST:
4147 size_t total_ea_len = 0;
4148 struct ea_list *ea_file_list = NULL;
4150 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4152 ea_file_list =
4153 get_ea_list_from_file(mem_ctx, conn, fsp,
4154 smb_fname->base_name,
4155 &total_ea_len);
4156 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4158 if (!ea_list || (total_ea_len > data_size)) {
4159 data_size = 4;
4160 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4161 break;
4164 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4165 break;
4168 case SMB_INFO_QUERY_ALL_EAS:
4170 /* We have data_size bytes to put EA's into. */
4171 size_t total_ea_len = 0;
4173 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4175 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4176 smb_fname->base_name,
4177 &total_ea_len);
4178 if (!ea_list || (total_ea_len > data_size)) {
4179 data_size = 4;
4180 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4181 break;
4184 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4185 break;
4188 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4190 /* We have data_size bytes to put EA's into. */
4191 size_t total_ea_len = 0;
4192 struct ea_list *ea_file_list = NULL;
4194 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4196 /*TODO: add filtering and index handling */
4198 ea_file_list =
4199 get_ea_list_from_file(mem_ctx, conn, fsp,
4200 smb_fname->base_name,
4201 &total_ea_len);
4202 if (!ea_file_list) {
4203 return NT_STATUS_NO_EAS_ON_FILE;
4206 status = fill_ea_chained_buffer(mem_ctx,
4207 pdata,
4208 data_size,
4209 &data_size,
4210 conn, ea_file_list);
4211 if (!NT_STATUS_IS_OK(status)) {
4212 return status;
4214 break;
4217 case SMB_FILE_BASIC_INFORMATION:
4218 case SMB_QUERY_FILE_BASIC_INFO:
4220 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4221 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4222 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4223 } else {
4224 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4225 data_size = 40;
4226 SIVAL(pdata,36,0);
4228 put_long_date_timespec(pdata,create_time_ts);
4229 put_long_date_timespec(pdata+8,atime_ts);
4230 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4231 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4232 SIVAL(pdata,32,mode);
4234 DEBUG(5,("SMB_QFBI - "));
4235 DEBUG(5,("create: %s ", ctime(&create_time)));
4236 DEBUG(5,("access: %s ", ctime(&atime)));
4237 DEBUG(5,("write: %s ", ctime(&mtime)));
4238 DEBUG(5,("change: %s ", ctime(&mtime)));
4239 DEBUG(5,("mode: %x\n", mode));
4240 break;
4242 case SMB_FILE_STANDARD_INFORMATION:
4243 case SMB_QUERY_FILE_STANDARD_INFO:
4245 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4246 data_size = 24;
4247 SOFF_T(pdata,0,allocation_size);
4248 SOFF_T(pdata,8,file_size);
4249 SIVAL(pdata,16,nlink);
4250 SCVAL(pdata,20,delete_pending?1:0);
4251 SCVAL(pdata,21,(mode&aDIR)?1:0);
4252 SSVAL(pdata,22,0); /* Padding. */
4253 break;
4255 case SMB_FILE_EA_INFORMATION:
4256 case SMB_QUERY_FILE_EA_INFO:
4258 unsigned int ea_size =
4259 estimate_ea_size(conn, fsp, smb_fname->base_name);
4260 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4261 data_size = 4;
4262 SIVAL(pdata,0,ea_size);
4263 break;
4266 /* Get the 8.3 name - used if NT SMB was negotiated. */
4267 case SMB_QUERY_FILE_ALT_NAME_INFO:
4268 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4270 int len;
4271 char mangled_name[13];
4272 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4273 if (!name_to_8_3(base_name,mangled_name,
4274 True,conn->params)) {
4275 return NT_STATUS_NO_MEMORY;
4277 len = srvstr_push(dstart, flags2,
4278 pdata+4, mangled_name,
4279 PTR_DIFF(dend, pdata+4),
4280 STR_UNICODE);
4281 data_size = 4 + len;
4282 SIVAL(pdata,0,len);
4283 break;
4286 case SMB_QUERY_FILE_NAME_INFO:
4288 int len;
4290 this must be *exactly* right for ACLs on mapped drives to work
4292 len = srvstr_push(dstart, flags2,
4293 pdata+4, dos_fname,
4294 PTR_DIFF(dend, pdata+4),
4295 STR_UNICODE);
4296 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4297 data_size = 4 + len;
4298 SIVAL(pdata,0,len);
4299 break;
4302 case SMB_FILE_ALLOCATION_INFORMATION:
4303 case SMB_QUERY_FILE_ALLOCATION_INFO:
4304 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4305 data_size = 8;
4306 SOFF_T(pdata,0,allocation_size);
4307 break;
4309 case SMB_FILE_END_OF_FILE_INFORMATION:
4310 case SMB_QUERY_FILE_END_OF_FILEINFO:
4311 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4312 data_size = 8;
4313 SOFF_T(pdata,0,file_size);
4314 break;
4316 case SMB_QUERY_FILE_ALL_INFO:
4317 case SMB_FILE_ALL_INFORMATION:
4319 int len;
4320 unsigned int ea_size =
4321 estimate_ea_size(conn, fsp, smb_fname->base_name);
4322 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4323 put_long_date_timespec(pdata,create_time_ts);
4324 put_long_date_timespec(pdata+8,atime_ts);
4325 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4326 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4327 SIVAL(pdata,32,mode);
4328 SIVAL(pdata,36,0); /* padding. */
4329 pdata += 40;
4330 SOFF_T(pdata,0,allocation_size);
4331 SOFF_T(pdata,8,file_size);
4332 SIVAL(pdata,16,nlink);
4333 SCVAL(pdata,20,delete_pending);
4334 SCVAL(pdata,21,(mode&aDIR)?1:0);
4335 SSVAL(pdata,22,0);
4336 pdata += 24;
4337 SIVAL(pdata,0,ea_size);
4338 pdata += 4; /* EA info */
4339 len = srvstr_push(dstart, flags2,
4340 pdata+4, dos_fname,
4341 PTR_DIFF(dend, pdata+4),
4342 STR_UNICODE);
4343 SIVAL(pdata,0,len);
4344 pdata += 4 + len;
4345 data_size = PTR_DIFF(pdata,(*ppdata));
4346 break;
4349 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4351 int len;
4352 unsigned int ea_size =
4353 estimate_ea_size(conn, fsp, smb_fname->base_name);
4354 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4355 put_long_date_timespec(pdata+0x00,create_time_ts);
4356 put_long_date_timespec(pdata+0x08,atime_ts);
4357 put_long_date_timespec(pdata+0x10,mtime_ts); /* write time */
4358 put_long_date_timespec(pdata+0x18,mtime_ts); /* change time */
4359 SIVAL(pdata, 0x20, mode);
4360 SIVAL(pdata, 0x24, 0); /* padding. */
4361 SBVAL(pdata, 0x28, allocation_size);
4362 SBVAL(pdata, 0x30, file_size);
4363 SIVAL(pdata, 0x38, nlink);
4364 SCVAL(pdata, 0x3C, delete_pending);
4365 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4366 SSVAL(pdata, 0x3E, 0); /* padding */
4367 SBVAL(pdata, 0x40, file_index);
4368 SIVAL(pdata, 0x48, ea_size);
4369 SIVAL(pdata, 0x4C, access_mask);
4370 SBVAL(pdata, 0x50, pos);
4371 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4372 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4374 pdata += 0x60;
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;
4385 case SMB_FILE_INTERNAL_INFORMATION:
4387 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4388 SBVAL(pdata, 0, file_index);
4389 data_size = 8;
4390 break;
4392 case SMB_FILE_ACCESS_INFORMATION:
4393 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4394 SIVAL(pdata, 0, access_mask);
4395 data_size = 4;
4396 break;
4398 case SMB_FILE_NAME_INFORMATION:
4399 /* Pathname with leading '\'. */
4401 size_t byte_len;
4402 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4403 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4404 SIVAL(pdata,0,byte_len);
4405 data_size = 4 + byte_len;
4406 break;
4409 case SMB_FILE_DISPOSITION_INFORMATION:
4410 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4411 data_size = 1;
4412 SCVAL(pdata,0,delete_pending);
4413 break;
4415 case SMB_FILE_POSITION_INFORMATION:
4416 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4417 data_size = 8;
4418 SOFF_T(pdata,0,pos);
4419 break;
4421 case SMB_FILE_MODE_INFORMATION:
4422 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4423 SIVAL(pdata,0,mode);
4424 data_size = 4;
4425 break;
4427 case SMB_FILE_ALIGNMENT_INFORMATION:
4428 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4429 SIVAL(pdata,0,0); /* No alignment needed. */
4430 data_size = 4;
4431 break;
4434 * NT4 server just returns "invalid query" to this - if we try
4435 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4436 * want this. JRA.
4438 /* The first statement above is false - verified using Thursby
4439 * client against NT4 -- gcolley.
4441 case SMB_QUERY_FILE_STREAM_INFO:
4442 case SMB_FILE_STREAM_INFORMATION: {
4443 unsigned int num_streams;
4444 struct stream_struct *streams;
4446 DEBUG(10,("smbd_do_qfilepathinfo: "
4447 "SMB_FILE_STREAM_INFORMATION\n"));
4449 if (is_ntfs_stream_smb_fname(smb_fname)) {
4450 return NT_STATUS_INVALID_PARAMETER;
4453 status = SMB_VFS_STREAMINFO(
4454 conn, fsp, smb_fname->base_name, talloc_tos(),
4455 &num_streams, &streams);
4457 if (!NT_STATUS_IS_OK(status)) {
4458 DEBUG(10, ("could not get stream info: %s\n",
4459 nt_errstr(status)));
4460 return status;
4463 status = marshall_stream_info(num_streams, streams,
4464 pdata, max_data_bytes,
4465 &data_size);
4467 if (!NT_STATUS_IS_OK(status)) {
4468 DEBUG(10, ("marshall_stream_info failed: %s\n",
4469 nt_errstr(status)));
4470 return status;
4473 TALLOC_FREE(streams);
4475 break;
4477 case SMB_QUERY_COMPRESSION_INFO:
4478 case SMB_FILE_COMPRESSION_INFORMATION:
4479 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4480 SOFF_T(pdata,0,file_size);
4481 SIVAL(pdata,8,0); /* ??? */
4482 SIVAL(pdata,12,0); /* ??? */
4483 data_size = 16;
4484 break;
4486 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4487 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4488 put_long_date_timespec(pdata,create_time_ts);
4489 put_long_date_timespec(pdata+8,atime_ts);
4490 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4491 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4492 SOFF_T(pdata,32,allocation_size);
4493 SOFF_T(pdata,40,file_size);
4494 SIVAL(pdata,48,mode);
4495 SIVAL(pdata,52,0); /* ??? */
4496 data_size = 56;
4497 break;
4499 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4500 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4501 SIVAL(pdata,0,mode);
4502 SIVAL(pdata,4,0);
4503 data_size = 8;
4504 break;
4507 * CIFS UNIX Extensions.
4510 case SMB_QUERY_FILE_UNIX_BASIC:
4512 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4513 data_size = PTR_DIFF(pdata,(*ppdata));
4516 int i;
4517 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4519 for (i=0; i<100; i++)
4520 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4521 DEBUG(4,("\n"));
4524 break;
4526 case SMB_QUERY_FILE_UNIX_INFO2:
4528 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4529 data_size = PTR_DIFF(pdata,(*ppdata));
4532 int i;
4533 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4535 for (i=0; i<100; i++)
4536 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4537 DEBUG(4,("\n"));
4540 break;
4542 case SMB_QUERY_FILE_UNIX_LINK:
4544 int len;
4545 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4547 if (!buffer) {
4548 return NT_STATUS_NO_MEMORY;
4551 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4552 #ifdef S_ISLNK
4553 if(!S_ISLNK(sbuf.st_ex_mode)) {
4554 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4556 #else
4557 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4558 #endif
4559 len = SMB_VFS_READLINK(conn,
4560 smb_fname->base_name,
4561 buffer, PATH_MAX);
4562 if (len == -1) {
4563 return map_nt_error_from_unix(errno);
4565 buffer[len] = 0;
4566 len = srvstr_push(dstart, flags2,
4567 pdata, buffer,
4568 PTR_DIFF(dend, pdata),
4569 STR_TERMINATE);
4570 pdata += len;
4571 data_size = PTR_DIFF(pdata,(*ppdata));
4573 break;
4576 #if defined(HAVE_POSIX_ACLS)
4577 case SMB_QUERY_POSIX_ACL:
4579 SMB_ACL_T file_acl = NULL;
4580 SMB_ACL_T def_acl = NULL;
4581 uint16 num_file_acls = 0;
4582 uint16 num_def_acls = 0;
4584 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4585 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4586 } else {
4587 file_acl =
4588 SMB_VFS_SYS_ACL_GET_FILE(conn,
4589 smb_fname->base_name,
4590 SMB_ACL_TYPE_ACCESS);
4593 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4594 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4595 "not implemented on "
4596 "filesystem containing %s\n",
4597 smb_fname->base_name));
4598 return NT_STATUS_NOT_IMPLEMENTED;
4601 if (S_ISDIR(sbuf.st_ex_mode)) {
4602 if (fsp && fsp->is_directory) {
4603 def_acl =
4604 SMB_VFS_SYS_ACL_GET_FILE(
4605 conn,
4606 fsp->fsp_name->base_name,
4607 SMB_ACL_TYPE_DEFAULT);
4608 } else {
4609 def_acl =
4610 SMB_VFS_SYS_ACL_GET_FILE(
4611 conn,
4612 smb_fname->base_name,
4613 SMB_ACL_TYPE_DEFAULT);
4615 def_acl = free_empty_sys_acl(conn, def_acl);
4618 num_file_acls = count_acl_entries(conn, file_acl);
4619 num_def_acls = count_acl_entries(conn, def_acl);
4621 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4622 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4623 data_size,
4624 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4625 SMB_POSIX_ACL_HEADER_SIZE) ));
4626 if (file_acl) {
4627 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4629 if (def_acl) {
4630 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4632 return NT_STATUS_BUFFER_TOO_SMALL;
4635 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4636 SSVAL(pdata,2,num_file_acls);
4637 SSVAL(pdata,4,num_def_acls);
4638 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4639 if (file_acl) {
4640 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4642 if (def_acl) {
4643 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4645 return NT_STATUS_INTERNAL_ERROR;
4647 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4648 if (file_acl) {
4649 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4651 if (def_acl) {
4652 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4654 return NT_STATUS_INTERNAL_ERROR;
4657 if (file_acl) {
4658 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4660 if (def_acl) {
4661 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4663 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4664 break;
4666 #endif
4669 case SMB_QUERY_POSIX_LOCK:
4671 uint64_t count;
4672 uint64_t offset;
4673 uint32 lock_pid;
4674 enum brl_type lock_type;
4676 /* We need an open file with a real fd for this. */
4677 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4678 return NT_STATUS_INVALID_LEVEL;
4681 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4682 return NT_STATUS_INVALID_PARAMETER;
4685 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4686 case POSIX_LOCK_TYPE_READ:
4687 lock_type = READ_LOCK;
4688 break;
4689 case POSIX_LOCK_TYPE_WRITE:
4690 lock_type = WRITE_LOCK;
4691 break;
4692 case POSIX_LOCK_TYPE_UNLOCK:
4693 default:
4694 /* There's no point in asking for an unlock... */
4695 return NT_STATUS_INVALID_PARAMETER;
4698 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4699 #if defined(HAVE_LONGLONG)
4700 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4701 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4702 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4703 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4704 #else /* HAVE_LONGLONG */
4705 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4706 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4707 #endif /* HAVE_LONGLONG */
4709 status = query_lock(fsp,
4710 &lock_pid,
4711 &count,
4712 &offset,
4713 &lock_type,
4714 POSIX_LOCK);
4716 if (ERROR_WAS_LOCK_DENIED(status)) {
4717 /* Here we need to report who has it locked... */
4718 data_size = POSIX_LOCK_DATA_SIZE;
4720 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4721 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4722 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4723 #if defined(HAVE_LONGLONG)
4724 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4725 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4726 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4727 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4728 #else /* HAVE_LONGLONG */
4729 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4730 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4731 #endif /* HAVE_LONGLONG */
4733 } else if (NT_STATUS_IS_OK(status)) {
4734 /* For success we just return a copy of what we sent
4735 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4736 data_size = POSIX_LOCK_DATA_SIZE;
4737 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4738 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4739 } else {
4740 return status;
4742 break;
4745 default:
4746 return NT_STATUS_INVALID_LEVEL;
4749 *pdata_size = data_size;
4750 return NT_STATUS_OK;
4753 /****************************************************************************
4754 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4755 file name or file id).
4756 ****************************************************************************/
4758 static void call_trans2qfilepathinfo(connection_struct *conn,
4759 struct smb_request *req,
4760 unsigned int tran_call,
4761 char **pparams, int total_params,
4762 char **ppdata, int total_data,
4763 unsigned int max_data_bytes)
4765 char *params = *pparams;
4766 char *pdata = *ppdata;
4767 uint16 info_level;
4768 unsigned int data_size = 0;
4769 unsigned int param_size = 2;
4770 struct smb_filename *smb_fname = NULL;
4771 bool delete_pending = False;
4772 struct timespec write_time_ts;
4773 files_struct *fsp = NULL;
4774 struct file_id fileid;
4775 struct ea_list *ea_list = NULL;
4776 int lock_data_count = 0;
4777 char *lock_data = NULL;
4778 bool ms_dfs_link = false;
4779 NTSTATUS status = NT_STATUS_OK;
4781 if (!params) {
4782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4783 return;
4786 ZERO_STRUCT(write_time_ts);
4788 if (tran_call == TRANSACT2_QFILEINFO) {
4789 if (total_params < 4) {
4790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4791 return;
4794 if (IS_IPC(conn)) {
4795 call_trans2qpipeinfo(conn, req, tran_call,
4796 pparams, total_params,
4797 ppdata, total_data,
4798 max_data_bytes);
4799 return;
4802 fsp = file_fsp(req, SVAL(params,0));
4803 info_level = SVAL(params,2);
4805 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
4807 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4808 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4809 return;
4812 /* Initial check for valid fsp ptr. */
4813 if (!check_fsp_open(conn, req, fsp)) {
4814 return;
4817 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
4818 &smb_fname);
4819 if (!NT_STATUS_IS_OK(status)) {
4820 reply_nterror(req, status);
4821 return;
4824 if(fsp->fake_file_handle) {
4826 * This is actually for the QUOTA_FAKE_FILE --metze
4829 /* We know this name is ok, it's already passed the checks. */
4831 } else if(fsp->is_directory || fsp->fh->fd == -1) {
4833 * This is actually a QFILEINFO on a directory
4834 * handle (returned from an NT SMB). NT5.0 seems
4835 * to do this call. JRA.
4838 if (INFO_LEVEL_IS_UNIX(info_level)) {
4839 /* Always do lstat for UNIX calls. */
4840 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4841 DEBUG(3,("call_trans2qfilepathinfo: "
4842 "SMB_VFS_LSTAT of %s failed "
4843 "(%s)\n",
4844 smb_fname_str_dbg(smb_fname),
4845 strerror(errno)));
4846 reply_nterror(req,
4847 map_nt_error_from_unix(errno));
4848 return;
4850 } else if (SMB_VFS_STAT(conn, smb_fname)) {
4851 DEBUG(3,("call_trans2qfilepathinfo: "
4852 "SMB_VFS_STAT of %s failed (%s)\n",
4853 smb_fname_str_dbg(smb_fname),
4854 strerror(errno)));
4855 reply_nterror(req,
4856 map_nt_error_from_unix(errno));
4857 return;
4860 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4861 get_file_infos(fileid, &delete_pending, &write_time_ts);
4862 } else {
4864 * Original code - this is an open file.
4866 if (!check_fsp(conn, req, fsp)) {
4867 return;
4870 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
4871 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
4872 fsp->fnum, strerror(errno)));
4873 reply_nterror(req,
4874 map_nt_error_from_unix(errno));
4875 return;
4877 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
4878 get_file_infos(fileid, &delete_pending, &write_time_ts);
4881 } else {
4882 char *fname = NULL;
4884 /* qpathinfo */
4885 if (total_params < 7) {
4886 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4887 return;
4890 info_level = SVAL(params,0);
4892 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
4894 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4895 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4896 return;
4899 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
4900 total_params - 6,
4901 STR_TERMINATE, &status);
4902 if (!NT_STATUS_IS_OK(status)) {
4903 reply_nterror(req, status);
4904 return;
4907 status = filename_convert(req,
4908 conn,
4909 req->flags2 & FLAGS2_DFS_PATHNAMES,
4910 fname,
4912 NULL,
4913 &smb_fname);
4914 if (!NT_STATUS_IS_OK(status)) {
4915 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
4916 reply_botherror(req,
4917 NT_STATUS_PATH_NOT_COVERED,
4918 ERRSRV, ERRbadpath);
4919 return;
4921 reply_nterror(req, status);
4922 return;
4925 /* If this is a stream, check if there is a delete_pending. */
4926 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4927 && is_ntfs_stream_smb_fname(smb_fname)) {
4928 struct smb_filename *smb_fname_base = NULL;
4930 /* Create an smb_filename with stream_name == NULL. */
4931 status =
4932 create_synthetic_smb_fname(talloc_tos(),
4933 smb_fname->base_name,
4934 NULL, NULL,
4935 &smb_fname_base);
4936 if (!NT_STATUS_IS_OK(status)) {
4937 reply_nterror(req, status);
4938 return;
4941 if (INFO_LEVEL_IS_UNIX(info_level)) {
4942 /* Always do lstat for UNIX calls. */
4943 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
4944 DEBUG(3,("call_trans2qfilepathinfo: "
4945 "SMB_VFS_LSTAT of %s failed "
4946 "(%s)\n",
4947 smb_fname_str_dbg(smb_fname_base),
4948 strerror(errno)));
4949 TALLOC_FREE(smb_fname_base);
4950 reply_nterror(req,
4951 map_nt_error_from_unix(errno));
4952 return;
4954 } else {
4955 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
4956 DEBUG(3,("call_trans2qfilepathinfo: "
4957 "fileinfo of %s failed "
4958 "(%s)\n",
4959 smb_fname_str_dbg(smb_fname_base),
4960 strerror(errno)));
4961 TALLOC_FREE(smb_fname_base);
4962 reply_nterror(req,
4963 map_nt_error_from_unix(errno));
4964 return;
4968 fileid = vfs_file_id_from_sbuf(conn,
4969 &smb_fname_base->st);
4970 TALLOC_FREE(smb_fname_base);
4971 get_file_infos(fileid, &delete_pending, NULL);
4972 if (delete_pending) {
4973 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4974 return;
4978 if (INFO_LEVEL_IS_UNIX(info_level)) {
4979 /* Always do lstat for UNIX calls. */
4980 if (SMB_VFS_LSTAT(conn, smb_fname)) {
4981 DEBUG(3,("call_trans2qfilepathinfo: "
4982 "SMB_VFS_LSTAT of %s failed (%s)\n",
4983 smb_fname_str_dbg(smb_fname),
4984 strerror(errno)));
4985 reply_nterror(req,
4986 map_nt_error_from_unix(errno));
4987 return;
4990 } else if (!VALID_STAT(smb_fname->st) &&
4991 SMB_VFS_STAT(conn, smb_fname) &&
4992 (info_level != SMB_INFO_IS_NAME_VALID)) {
4993 ms_dfs_link = check_msdfs_link(conn,
4994 smb_fname->base_name,
4995 &smb_fname->st);
4997 if (!ms_dfs_link) {
4998 DEBUG(3,("call_trans2qfilepathinfo: "
4999 "SMB_VFS_STAT of %s failed (%s)\n",
5000 smb_fname_str_dbg(smb_fname),
5001 strerror(errno)));
5002 reply_nterror(req,
5003 map_nt_error_from_unix(errno));
5004 return;
5008 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5009 get_file_infos(fileid, &delete_pending, &write_time_ts);
5010 if (delete_pending) {
5011 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5012 return;
5016 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5017 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5018 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5020 /* Pull out any data sent here before we realloc. */
5021 switch (info_level) {
5022 case SMB_INFO_QUERY_EAS_FROM_LIST:
5024 /* Pull any EA list from the data portion. */
5025 uint32 ea_size;
5027 if (total_data < 4) {
5028 reply_nterror(
5029 req, NT_STATUS_INVALID_PARAMETER);
5030 return;
5032 ea_size = IVAL(pdata,0);
5034 if (total_data > 0 && ea_size != total_data) {
5035 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5036 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5037 reply_nterror(
5038 req, NT_STATUS_INVALID_PARAMETER);
5039 return;
5042 if (!lp_ea_support(SNUM(conn))) {
5043 reply_doserror(req, ERRDOS,
5044 ERReasnotsupported);
5045 return;
5048 /* Pull out the list of names. */
5049 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5050 if (!ea_list) {
5051 reply_nterror(
5052 req, NT_STATUS_INVALID_PARAMETER);
5053 return;
5055 break;
5058 case SMB_QUERY_POSIX_LOCK:
5060 if (fsp == NULL || fsp->fh->fd == -1) {
5061 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5062 return;
5065 if (total_data != POSIX_LOCK_DATA_SIZE) {
5066 reply_nterror(
5067 req, NT_STATUS_INVALID_PARAMETER);
5068 return;
5071 /* Copy the lock range data. */
5072 lock_data = (char *)TALLOC_MEMDUP(
5073 req, pdata, total_data);
5074 if (!lock_data) {
5075 reply_nterror(req, NT_STATUS_NO_MEMORY);
5076 return;
5078 lock_data_count = total_data;
5080 default:
5081 break;
5084 *pparams = (char *)SMB_REALLOC(*pparams,2);
5085 if (*pparams == NULL) {
5086 reply_nterror(req, NT_STATUS_NO_MEMORY);
5087 return;
5089 params = *pparams;
5090 SSVAL(params,0,0);
5093 * draft-leach-cifs-v1-spec-02.txt
5094 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5095 * says:
5097 * The requested information is placed in the Data portion of the
5098 * transaction response. For the information levels greater than 0x100,
5099 * the transaction response has 1 parameter word which should be
5100 * ignored by the client.
5102 * However Windows only follows this rule for the IS_NAME_VALID call.
5104 switch (info_level) {
5105 case SMB_INFO_IS_NAME_VALID:
5106 param_size = 0;
5107 break;
5110 if ((info_level & 0xFF00) == 0xFF00) {
5112 * We use levels that start with 0xFF00
5113 * internally to represent SMB2 specific levels
5115 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5116 return;
5119 status = smbd_do_qfilepathinfo(conn, req, info_level,
5120 fsp, smb_fname,
5121 delete_pending, write_time_ts,
5122 ms_dfs_link, ea_list,
5123 lock_data_count, lock_data,
5124 req->flags2, max_data_bytes,
5125 ppdata, &data_size);
5126 if (!NT_STATUS_IS_OK(status)) {
5127 reply_nterror(req, status);
5128 return;
5131 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5132 max_data_bytes);
5134 return;
5137 /****************************************************************************
5138 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5139 code.
5140 ****************************************************************************/
5142 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5143 connection_struct *conn,
5144 const struct smb_filename *smb_fname_old,
5145 const struct smb_filename *smb_fname_new)
5147 NTSTATUS status = NT_STATUS_OK;
5149 /* source must already exist. */
5150 if (!VALID_STAT(smb_fname_old->st)) {
5151 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5154 /* Disallow if newname already exists. */
5155 if (VALID_STAT(smb_fname_new->st)) {
5156 return NT_STATUS_OBJECT_NAME_COLLISION;
5159 /* No links from a directory. */
5160 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5161 return NT_STATUS_FILE_IS_A_DIRECTORY;
5164 /* Setting a hardlink to/from a stream isn't currently supported. */
5165 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5166 is_ntfs_stream_smb_fname(smb_fname_new)) {
5167 return NT_STATUS_INVALID_PARAMETER;
5170 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5171 smb_fname_old->base_name, smb_fname_new->base_name));
5173 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5174 smb_fname_new->base_name) != 0) {
5175 status = map_nt_error_from_unix(errno);
5176 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5177 nt_errstr(status), smb_fname_old->base_name,
5178 smb_fname_new->base_name));
5180 return status;
5183 /****************************************************************************
5184 Deal with setting the time from any of the setfilepathinfo functions.
5185 ****************************************************************************/
5187 NTSTATUS smb_set_file_time(connection_struct *conn,
5188 files_struct *fsp,
5189 const struct smb_filename *smb_fname,
5190 struct smb_file_time *ft,
5191 bool setting_write_time)
5193 struct smb_filename *smb_fname_base = NULL;
5194 uint32 action =
5195 FILE_NOTIFY_CHANGE_LAST_ACCESS
5196 |FILE_NOTIFY_CHANGE_LAST_WRITE;
5197 bool set_createtime = false;
5198 bool set_ctime = false;
5199 NTSTATUS status;
5201 if (!VALID_STAT(smb_fname->st)) {
5202 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5205 /* get some defaults (no modifications) if any info is zero or -1. */
5206 if (null_timespec(ft->create_time)) {
5207 ft->create_time = smb_fname->st.st_ex_btime;
5208 } else {
5209 set_createtime = true;
5212 if (null_timespec(ft->ctime)) {
5213 ft->ctime = smb_fname->st.st_ex_ctime;
5214 } else {
5215 set_ctime = true;
5218 if (null_timespec(ft->atime)) {
5219 ft->atime= smb_fname->st.st_ex_atime;
5220 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5223 if (null_timespec(ft->mtime)) {
5224 ft->mtime = smb_fname->st.st_ex_mtime;
5225 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5228 if (!setting_write_time) {
5229 /* ft->mtime comes from change time, not write time. */
5230 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5233 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5234 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5235 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5236 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5237 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5238 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5239 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5240 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5243 * Try and set the times of this file if
5244 * they are different from the current values.
5248 struct timespec mts = smb_fname->st.st_ex_mtime;
5249 struct timespec ats = smb_fname->st.st_ex_atime;
5250 if ((timespec_compare(&ft->atime, &ats) == 0) &&
5251 (timespec_compare(&ft->mtime, &mts) == 0)) {
5252 if (set_createtime || set_ctime) {
5253 notify_fname(conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_LAST_WRITE,
5254 smb_fname->base_name);
5256 return NT_STATUS_OK;
5260 if (setting_write_time) {
5262 * This was a Windows setfileinfo on an open file.
5263 * NT does this a lot. We also need to
5264 * set the time here, as it can be read by
5265 * FindFirst/FindNext and with the patch for bug #2045
5266 * in smbd/fileio.c it ensures that this timestamp is
5267 * kept sticky even after a write. We save the request
5268 * away and will set it on file close and after a write. JRA.
5271 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5272 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5274 if (fsp != NULL) {
5275 if (fsp->base_fsp) {
5276 set_sticky_write_time_fsp(fsp->base_fsp,
5277 ft->mtime);
5278 } else {
5279 set_sticky_write_time_fsp(fsp, ft->mtime);
5281 } else {
5282 set_sticky_write_time_path(
5283 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5284 ft->mtime);
5288 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5290 /* Always call ntimes on the base, even if a stream was passed in. */
5291 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5292 NULL, &smb_fname->st,
5293 &smb_fname_base);
5294 if (!NT_STATUS_IS_OK(status)) {
5295 return status;
5298 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5299 TALLOC_FREE(smb_fname_base);
5300 return map_nt_error_from_unix(errno);
5302 TALLOC_FREE(smb_fname_base);
5304 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5305 smb_fname->base_name);
5306 return NT_STATUS_OK;
5309 /****************************************************************************
5310 Deal with setting the dosmode from any of the setfilepathinfo functions.
5311 ****************************************************************************/
5313 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5314 const struct smb_filename *smb_fname,
5315 uint32 dosmode)
5317 struct smb_filename *smb_fname_base = NULL;
5318 NTSTATUS status;
5320 if (!VALID_STAT(smb_fname->st)) {
5321 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5324 /* Always operate on the base_name, even if a stream was passed in. */
5325 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5326 NULL, &smb_fname->st,
5327 &smb_fname_base);
5328 if (!NT_STATUS_IS_OK(status)) {
5329 return status;
5332 if (dosmode) {
5333 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5334 dosmode |= aDIR;
5335 } else {
5336 dosmode &= ~aDIR;
5340 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5342 /* check the mode isn't different, before changing it */
5343 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5344 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5345 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5346 (unsigned int)dosmode));
5348 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5349 false)) {
5350 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5351 "%s failed (%s)\n",
5352 smb_fname_str_dbg(smb_fname_base),
5353 strerror(errno)));
5354 status = map_nt_error_from_unix(errno);
5355 goto out;
5358 status = NT_STATUS_OK;
5359 out:
5360 TALLOC_FREE(smb_fname_base);
5361 return status;
5364 /****************************************************************************
5365 Deal with setting the size from any of the setfilepathinfo functions.
5366 ****************************************************************************/
5368 static NTSTATUS smb_set_file_size(connection_struct *conn,
5369 struct smb_request *req,
5370 files_struct *fsp,
5371 const struct smb_filename *smb_fname,
5372 const SMB_STRUCT_STAT *psbuf,
5373 SMB_OFF_T size)
5375 NTSTATUS status = NT_STATUS_OK;
5376 struct smb_filename *smb_fname_tmp = NULL;
5377 files_struct *new_fsp = NULL;
5379 if (!VALID_STAT(*psbuf)) {
5380 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5383 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5385 if (size == get_file_size_stat(psbuf)) {
5386 return NT_STATUS_OK;
5389 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5390 smb_fname_str_dbg(smb_fname), (double)size));
5392 if (fsp && fsp->fh->fd != -1) {
5393 /* Handle based call. */
5394 if (vfs_set_filelen(fsp, size) == -1) {
5395 return map_nt_error_from_unix(errno);
5397 trigger_write_time_update_immediate(fsp);
5398 return NT_STATUS_OK;
5401 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5402 if (!NT_STATUS_IS_OK(status)) {
5403 return status;
5406 smb_fname_tmp->st = *psbuf;
5408 status = SMB_VFS_CREATE_FILE(
5409 conn, /* conn */
5410 req, /* req */
5411 0, /* root_dir_fid */
5412 smb_fname_tmp, /* fname */
5413 FILE_WRITE_ATTRIBUTES, /* access_mask */
5414 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5415 FILE_SHARE_DELETE),
5416 FILE_OPEN, /* create_disposition*/
5417 0, /* create_options */
5418 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5419 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5420 0, /* allocation_size */
5421 NULL, /* sd */
5422 NULL, /* ea_list */
5423 &new_fsp, /* result */
5424 NULL); /* pinfo */
5426 TALLOC_FREE(smb_fname_tmp);
5428 if (!NT_STATUS_IS_OK(status)) {
5429 /* NB. We check for open_was_deferred in the caller. */
5430 return status;
5433 if (vfs_set_filelen(new_fsp, size) == -1) {
5434 status = map_nt_error_from_unix(errno);
5435 close_file(req, new_fsp,NORMAL_CLOSE);
5436 return status;
5439 trigger_write_time_update_immediate(new_fsp);
5440 close_file(req, new_fsp,NORMAL_CLOSE);
5441 return NT_STATUS_OK;
5444 /****************************************************************************
5445 Deal with SMB_INFO_SET_EA.
5446 ****************************************************************************/
5448 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5449 const char *pdata,
5450 int total_data,
5451 files_struct *fsp,
5452 const struct smb_filename *smb_fname)
5454 struct ea_list *ea_list = NULL;
5455 TALLOC_CTX *ctx = NULL;
5456 NTSTATUS status = NT_STATUS_OK;
5458 if (total_data < 10) {
5460 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5461 length. They seem to have no effect. Bug #3212. JRA */
5463 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5464 /* We're done. We only get EA info in this call. */
5465 return NT_STATUS_OK;
5468 return NT_STATUS_INVALID_PARAMETER;
5471 if (IVAL(pdata,0) > total_data) {
5472 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5473 IVAL(pdata,0), (unsigned int)total_data));
5474 return NT_STATUS_INVALID_PARAMETER;
5477 ctx = talloc_tos();
5478 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5479 if (!ea_list) {
5480 return NT_STATUS_INVALID_PARAMETER;
5482 status = set_ea(conn, fsp, smb_fname, ea_list);
5484 return status;
5487 /****************************************************************************
5488 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5489 ****************************************************************************/
5491 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5492 const char *pdata,
5493 int total_data,
5494 files_struct *fsp,
5495 const struct smb_filename *smb_fname)
5497 NTSTATUS status = NT_STATUS_OK;
5498 bool delete_on_close;
5499 uint32 dosmode = 0;
5501 if (total_data < 1) {
5502 return NT_STATUS_INVALID_PARAMETER;
5505 if (fsp == NULL) {
5506 return NT_STATUS_INVALID_HANDLE;
5509 delete_on_close = (CVAL(pdata,0) ? True : False);
5510 dosmode = dos_mode(conn, smb_fname);
5512 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5513 "delete_on_close = %u\n",
5514 smb_fname_str_dbg(smb_fname),
5515 (unsigned int)dosmode,
5516 (unsigned int)delete_on_close ));
5518 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5520 if (!NT_STATUS_IS_OK(status)) {
5521 return status;
5524 /* The set is across all open files on this dev/inode pair. */
5525 if (!set_delete_on_close(fsp, delete_on_close,
5526 &conn->server_info->utok)) {
5527 return NT_STATUS_ACCESS_DENIED;
5529 return NT_STATUS_OK;
5532 /****************************************************************************
5533 Deal with SMB_FILE_POSITION_INFORMATION.
5534 ****************************************************************************/
5536 static NTSTATUS smb_file_position_information(connection_struct *conn,
5537 const char *pdata,
5538 int total_data,
5539 files_struct *fsp)
5541 uint64_t position_information;
5543 if (total_data < 8) {
5544 return NT_STATUS_INVALID_PARAMETER;
5547 if (fsp == NULL) {
5548 /* Ignore on pathname based set. */
5549 return NT_STATUS_OK;
5552 position_information = (uint64_t)IVAL(pdata,0);
5553 #ifdef LARGE_SMB_OFF_T
5554 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5555 #else /* LARGE_SMB_OFF_T */
5556 if (IVAL(pdata,4) != 0) {
5557 /* more than 32 bits? */
5558 return NT_STATUS_INVALID_PARAMETER;
5560 #endif /* LARGE_SMB_OFF_T */
5562 DEBUG(10,("smb_file_position_information: Set file position "
5563 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5564 (double)position_information));
5565 fsp->fh->position_information = position_information;
5566 return NT_STATUS_OK;
5569 /****************************************************************************
5570 Deal with SMB_FILE_MODE_INFORMATION.
5571 ****************************************************************************/
5573 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5574 const char *pdata,
5575 int total_data)
5577 uint32 mode;
5579 if (total_data < 4) {
5580 return NT_STATUS_INVALID_PARAMETER;
5582 mode = IVAL(pdata,0);
5583 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5584 return NT_STATUS_INVALID_PARAMETER;
5586 return NT_STATUS_OK;
5589 /****************************************************************************
5590 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5591 ****************************************************************************/
5593 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5594 struct smb_request *req,
5595 const char *pdata,
5596 int total_data,
5597 const struct smb_filename *smb_fname)
5599 char *link_target = NULL;
5600 const char *newname = smb_fname->base_name;
5601 NTSTATUS status = NT_STATUS_OK;
5602 TALLOC_CTX *ctx = talloc_tos();
5604 /* Set a symbolic link. */
5605 /* Don't allow this if follow links is false. */
5607 if (total_data == 0) {
5608 return NT_STATUS_INVALID_PARAMETER;
5611 if (!lp_symlinks(SNUM(conn))) {
5612 return NT_STATUS_ACCESS_DENIED;
5615 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5616 total_data, STR_TERMINATE);
5618 if (!link_target) {
5619 return NT_STATUS_INVALID_PARAMETER;
5622 /* !widelinks forces the target path to be within the share. */
5623 /* This means we can interpret the target as a pathname. */
5624 if (!lp_widelinks(SNUM(conn))) {
5625 char *rel_name = NULL;
5626 char *last_dirp = NULL;
5628 if (*link_target == '/') {
5629 /* No absolute paths allowed. */
5630 return NT_STATUS_ACCESS_DENIED;
5632 rel_name = talloc_strdup(ctx,newname);
5633 if (!rel_name) {
5634 return NT_STATUS_NO_MEMORY;
5636 last_dirp = strrchr_m(rel_name, '/');
5637 if (last_dirp) {
5638 last_dirp[1] = '\0';
5639 } else {
5640 rel_name = talloc_strdup(ctx,"./");
5641 if (!rel_name) {
5642 return NT_STATUS_NO_MEMORY;
5645 rel_name = talloc_asprintf_append(rel_name,
5646 "%s",
5647 link_target);
5648 if (!rel_name) {
5649 return NT_STATUS_NO_MEMORY;
5652 status = check_name(conn, rel_name);
5653 if (!NT_STATUS_IS_OK(status)) {
5654 return status;
5658 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5659 newname, link_target ));
5661 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5662 return map_nt_error_from_unix(errno);
5665 return NT_STATUS_OK;
5668 /****************************************************************************
5669 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5670 ****************************************************************************/
5672 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5673 struct smb_request *req,
5674 const char *pdata, int total_data,
5675 const struct smb_filename *smb_fname_new)
5677 char *oldname = NULL;
5678 struct smb_filename *smb_fname_old = NULL;
5679 TALLOC_CTX *ctx = talloc_tos();
5680 NTSTATUS status = NT_STATUS_OK;
5682 /* Set a hard link. */
5683 if (total_data == 0) {
5684 return NT_STATUS_INVALID_PARAMETER;
5687 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5688 total_data, STR_TERMINATE, &status);
5689 if (!NT_STATUS_IS_OK(status)) {
5690 return status;
5693 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5694 smb_fname_str_dbg(smb_fname_new), oldname));
5696 status = filename_convert(ctx,
5697 conn,
5698 req->flags2 & FLAGS2_DFS_PATHNAMES,
5699 oldname,
5701 NULL,
5702 &smb_fname_old);
5703 if (!NT_STATUS_IS_OK(status)) {
5704 return status;
5707 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5710 /****************************************************************************
5711 Deal with SMB_FILE_RENAME_INFORMATION.
5712 ****************************************************************************/
5714 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5715 struct smb_request *req,
5716 const char *pdata,
5717 int total_data,
5718 files_struct *fsp,
5719 struct smb_filename *smb_fname_src)
5721 bool overwrite;
5722 uint32 root_fid;
5723 uint32 len;
5724 char *newname = NULL;
5725 struct smb_filename *smb_fname_dst = NULL;
5726 bool dest_has_wcard = False;
5727 NTSTATUS status = NT_STATUS_OK;
5728 char *p;
5729 TALLOC_CTX *ctx = talloc_tos();
5731 if (total_data < 13) {
5732 return NT_STATUS_INVALID_PARAMETER;
5735 overwrite = (CVAL(pdata,0) ? True : False);
5736 root_fid = IVAL(pdata,4);
5737 len = IVAL(pdata,8);
5739 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5740 return NT_STATUS_INVALID_PARAMETER;
5743 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5744 len, 0, &status,
5745 &dest_has_wcard);
5746 if (!NT_STATUS_IS_OK(status)) {
5747 return status;
5750 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5751 newname));
5753 status = resolve_dfspath_wcard(ctx, conn,
5754 req->flags2 & FLAGS2_DFS_PATHNAMES,
5755 newname,
5756 &newname,
5757 &dest_has_wcard);
5758 if (!NT_STATUS_IS_OK(status)) {
5759 return status;
5762 /* Check the new name has no '/' characters. */
5763 if (strchr_m(newname, '/')) {
5764 return NT_STATUS_NOT_SUPPORTED;
5767 if (fsp && fsp->base_fsp) {
5768 /* newname must be a stream name. */
5769 if (newname[0] != ':') {
5770 return NT_STATUS_NOT_SUPPORTED;
5773 /* Create an smb_fname to call rename_internals_fsp() with. */
5774 status = create_synthetic_smb_fname(talloc_tos(),
5775 fsp->base_fsp->fsp_name->base_name, newname, NULL,
5776 &smb_fname_dst);
5777 if (!NT_STATUS_IS_OK(status)) {
5778 goto out;
5782 * Set the original last component, since
5783 * rename_internals_fsp() requires it.
5785 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
5786 newname);
5787 if (smb_fname_dst->original_lcomp == NULL) {
5788 status = NT_STATUS_NO_MEMORY;
5789 goto out;
5792 } else {
5794 * Build up an smb_fname_dst based on the filename passed in.
5795 * We basically just strip off the last component, and put on
5796 * the newname instead.
5798 char *base_name = NULL;
5800 /* newname must *not* be a stream name. */
5801 if (newname[0] == ':') {
5802 return NT_STATUS_NOT_SUPPORTED;
5806 * Strip off the last component (filename) of the path passed
5807 * in.
5809 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5810 if (!base_name) {
5811 return NT_STATUS_NO_MEMORY;
5813 p = strrchr_m(base_name, '/');
5814 if (p) {
5815 p[1] = '\0';
5816 } else {
5817 base_name = talloc_strdup(ctx, "./");
5818 if (!base_name) {
5819 return NT_STATUS_NO_MEMORY;
5822 /* Append the new name. */
5823 base_name = talloc_asprintf_append(base_name,
5824 "%s",
5825 newname);
5826 if (!base_name) {
5827 return NT_STATUS_NO_MEMORY;
5830 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
5831 (UCF_SAVE_LCOMP |
5832 (dest_has_wcard ?
5833 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
5834 0)));
5836 /* If an error we expect this to be
5837 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5839 if (!NT_STATUS_IS_OK(status)) {
5840 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5841 status)) {
5842 goto out;
5844 /* Create an smb_fname to call rename_internals_fsp() */
5845 status = create_synthetic_smb_fname(ctx,
5846 base_name, NULL,
5847 NULL,
5848 &smb_fname_dst);
5849 if (!NT_STATUS_IS_OK(status)) {
5850 goto out;
5855 if (fsp) {
5856 DEBUG(10,("smb_file_rename_information: "
5857 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5858 fsp->fnum, fsp_str_dbg(fsp),
5859 smb_fname_str_dbg(smb_fname_dst)));
5860 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
5861 overwrite);
5862 } else {
5863 DEBUG(10,("smb_file_rename_information: "
5864 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5865 smb_fname_str_dbg(smb_fname_src),
5866 smb_fname_str_dbg(smb_fname_dst)));
5867 status = rename_internals(ctx, conn, req, smb_fname_src,
5868 smb_fname_dst, 0, overwrite, false,
5869 dest_has_wcard,
5870 FILE_WRITE_ATTRIBUTES);
5872 out:
5873 TALLOC_FREE(smb_fname_dst);
5874 return status;
5877 /****************************************************************************
5878 Deal with SMB_SET_POSIX_ACL.
5879 ****************************************************************************/
5881 #if defined(HAVE_POSIX_ACLS)
5882 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5883 const char *pdata,
5884 int total_data,
5885 files_struct *fsp,
5886 const struct smb_filename *smb_fname)
5888 uint16 posix_acl_version;
5889 uint16 num_file_acls;
5890 uint16 num_def_acls;
5891 bool valid_file_acls = True;
5892 bool valid_def_acls = True;
5894 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5895 return NT_STATUS_INVALID_PARAMETER;
5897 posix_acl_version = SVAL(pdata,0);
5898 num_file_acls = SVAL(pdata,2);
5899 num_def_acls = SVAL(pdata,4);
5901 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5902 valid_file_acls = False;
5903 num_file_acls = 0;
5906 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5907 valid_def_acls = False;
5908 num_def_acls = 0;
5911 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5912 return NT_STATUS_INVALID_PARAMETER;
5915 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5916 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5917 return NT_STATUS_INVALID_PARAMETER;
5920 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5921 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
5922 (unsigned int)num_file_acls,
5923 (unsigned int)num_def_acls));
5925 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
5926 smb_fname->base_name, num_file_acls,
5927 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5928 return map_nt_error_from_unix(errno);
5931 if (valid_def_acls && !set_unix_posix_default_acl(conn,
5932 smb_fname->base_name, &smb_fname->st, num_def_acls,
5933 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5934 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5935 return map_nt_error_from_unix(errno);
5937 return NT_STATUS_OK;
5939 #endif
5941 /****************************************************************************
5942 Deal with SMB_SET_POSIX_LOCK.
5943 ****************************************************************************/
5945 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5946 struct smb_request *req,
5947 const char *pdata,
5948 int total_data,
5949 files_struct *fsp)
5951 uint64_t count;
5952 uint64_t offset;
5953 uint32 lock_pid;
5954 bool blocking_lock = False;
5955 enum brl_type lock_type;
5957 NTSTATUS status = NT_STATUS_OK;
5959 if (fsp == NULL || fsp->fh->fd == -1) {
5960 return NT_STATUS_INVALID_HANDLE;
5963 if (total_data != POSIX_LOCK_DATA_SIZE) {
5964 return NT_STATUS_INVALID_PARAMETER;
5967 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5968 case POSIX_LOCK_TYPE_READ:
5969 lock_type = READ_LOCK;
5970 break;
5971 case POSIX_LOCK_TYPE_WRITE:
5972 /* Return the right POSIX-mappable error code for files opened read-only. */
5973 if (!fsp->can_write) {
5974 return NT_STATUS_INVALID_HANDLE;
5976 lock_type = WRITE_LOCK;
5977 break;
5978 case POSIX_LOCK_TYPE_UNLOCK:
5979 lock_type = UNLOCK_LOCK;
5980 break;
5981 default:
5982 return NT_STATUS_INVALID_PARAMETER;
5985 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5986 blocking_lock = False;
5987 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5988 blocking_lock = True;
5989 } else {
5990 return NT_STATUS_INVALID_PARAMETER;
5993 if (!lp_blocking_locks(SNUM(conn))) {
5994 blocking_lock = False;
5997 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5998 #if defined(HAVE_LONGLONG)
5999 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6000 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6001 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6002 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6003 #else /* HAVE_LONGLONG */
6004 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6005 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6006 #endif /* HAVE_LONGLONG */
6008 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6009 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6010 fsp_str_dbg(fsp),
6011 (unsigned int)lock_type,
6012 (unsigned int)lock_pid,
6013 (double)count,
6014 (double)offset ));
6016 if (lock_type == UNLOCK_LOCK) {
6017 status = do_unlock(smbd_messaging_context(),
6018 fsp,
6019 lock_pid,
6020 count,
6021 offset,
6022 POSIX_LOCK);
6023 } else {
6024 uint32 block_smbpid;
6026 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6027 fsp,
6028 lock_pid,
6029 count,
6030 offset,
6031 lock_type,
6032 POSIX_LOCK,
6033 blocking_lock,
6034 &status,
6035 &block_smbpid,
6036 NULL);
6038 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6040 * A blocking lock was requested. Package up
6041 * this smb into a queued request and push it
6042 * onto the blocking lock queue.
6044 if(push_blocking_lock_request(br_lck,
6045 req,
6046 fsp,
6047 -1, /* infinite timeout. */
6049 lock_pid,
6050 lock_type,
6051 POSIX_LOCK,
6052 offset,
6053 count,
6054 block_smbpid)) {
6055 TALLOC_FREE(br_lck);
6056 return status;
6059 TALLOC_FREE(br_lck);
6062 return status;
6065 /****************************************************************************
6066 Deal with SMB_SET_FILE_BASIC_INFO.
6067 ****************************************************************************/
6069 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6070 const char *pdata,
6071 int total_data,
6072 files_struct *fsp,
6073 const struct smb_filename *smb_fname)
6075 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6076 struct smb_file_time ft;
6077 uint32 dosmode = 0;
6078 NTSTATUS status = NT_STATUS_OK;
6080 ZERO_STRUCT(ft);
6082 if (total_data < 36) {
6083 return NT_STATUS_INVALID_PARAMETER;
6086 /* Set the attributes */
6087 dosmode = IVAL(pdata,32);
6088 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6089 if (!NT_STATUS_IS_OK(status)) {
6090 return status;
6093 /* create time */
6094 ft.create_time = interpret_long_date(pdata);
6096 /* access time */
6097 ft.atime = interpret_long_date(pdata+8);
6099 /* write time. */
6100 ft.mtime = interpret_long_date(pdata+16);
6102 /* change time. */
6103 ft.ctime = interpret_long_date(pdata+24);
6105 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6106 smb_fname_str_dbg(smb_fname)));
6108 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6109 true);
6112 /****************************************************************************
6113 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6114 ****************************************************************************/
6116 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6117 struct smb_request *req,
6118 const char *pdata,
6119 int total_data,
6120 files_struct *fsp,
6121 struct smb_filename *smb_fname)
6123 uint64_t allocation_size = 0;
6124 NTSTATUS status = NT_STATUS_OK;
6125 files_struct *new_fsp = NULL;
6127 if (!VALID_STAT(smb_fname->st)) {
6128 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6131 if (total_data < 8) {
6132 return NT_STATUS_INVALID_PARAMETER;
6135 allocation_size = (uint64_t)IVAL(pdata,0);
6136 #ifdef LARGE_SMB_OFF_T
6137 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6138 #else /* LARGE_SMB_OFF_T */
6139 if (IVAL(pdata,4) != 0) {
6140 /* more than 32 bits? */
6141 return NT_STATUS_INVALID_PARAMETER;
6143 #endif /* LARGE_SMB_OFF_T */
6145 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6146 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6147 (double)allocation_size));
6149 if (allocation_size) {
6150 allocation_size = smb_roundup(conn, allocation_size);
6153 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6154 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6155 (double)allocation_size));
6157 if (fsp && fsp->fh->fd != -1) {
6158 /* Open file handle. */
6159 /* Only change if needed. */
6160 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6161 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6162 return map_nt_error_from_unix(errno);
6165 /* But always update the time. */
6167 * This is equivalent to a write. Ensure it's seen immediately
6168 * if there are no pending writes.
6170 trigger_write_time_update_immediate(fsp);
6171 return NT_STATUS_OK;
6174 /* Pathname or stat or directory file. */
6175 status = SMB_VFS_CREATE_FILE(
6176 conn, /* conn */
6177 req, /* req */
6178 0, /* root_dir_fid */
6179 smb_fname, /* fname */
6180 FILE_WRITE_DATA, /* access_mask */
6181 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6182 FILE_SHARE_DELETE),
6183 FILE_OPEN, /* create_disposition*/
6184 0, /* create_options */
6185 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6186 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6187 0, /* allocation_size */
6188 NULL, /* sd */
6189 NULL, /* ea_list */
6190 &new_fsp, /* result */
6191 NULL); /* pinfo */
6193 if (!NT_STATUS_IS_OK(status)) {
6194 /* NB. We check for open_was_deferred in the caller. */
6195 return status;
6198 /* Only change if needed. */
6199 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6200 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6201 status = map_nt_error_from_unix(errno);
6202 close_file(req, new_fsp, NORMAL_CLOSE);
6203 return status;
6207 /* Changing the allocation size should set the last mod time. */
6209 * This is equivalent to a write. Ensure it's seen immediately
6210 * if there are no pending writes.
6212 trigger_write_time_update_immediate(new_fsp);
6214 close_file(req, new_fsp, NORMAL_CLOSE);
6215 return NT_STATUS_OK;
6218 /****************************************************************************
6219 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6220 ****************************************************************************/
6222 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6223 struct smb_request *req,
6224 const char *pdata,
6225 int total_data,
6226 files_struct *fsp,
6227 const struct smb_filename *smb_fname)
6229 SMB_OFF_T size;
6231 if (total_data < 8) {
6232 return NT_STATUS_INVALID_PARAMETER;
6235 size = IVAL(pdata,0);
6236 #ifdef LARGE_SMB_OFF_T
6237 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6238 #else /* LARGE_SMB_OFF_T */
6239 if (IVAL(pdata,4) != 0) {
6240 /* more than 32 bits? */
6241 return NT_STATUS_INVALID_PARAMETER;
6243 #endif /* LARGE_SMB_OFF_T */
6244 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6245 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6246 (double)size));
6248 return smb_set_file_size(conn, req,
6249 fsp,
6250 smb_fname,
6251 &smb_fname->st,
6252 size);
6255 /****************************************************************************
6256 Allow a UNIX info mknod.
6257 ****************************************************************************/
6259 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6260 const char *pdata,
6261 int total_data,
6262 const struct smb_filename *smb_fname)
6264 uint32 file_type = IVAL(pdata,56);
6265 #if defined(HAVE_MAKEDEV)
6266 uint32 dev_major = IVAL(pdata,60);
6267 uint32 dev_minor = IVAL(pdata,68);
6268 #endif
6269 SMB_DEV_T dev = (SMB_DEV_T)0;
6270 uint32 raw_unixmode = IVAL(pdata,84);
6271 NTSTATUS status;
6272 mode_t unixmode;
6274 if (total_data < 100) {
6275 return NT_STATUS_INVALID_PARAMETER;
6278 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6279 PERM_NEW_FILE, &unixmode);
6280 if (!NT_STATUS_IS_OK(status)) {
6281 return status;
6284 #if defined(HAVE_MAKEDEV)
6285 dev = makedev(dev_major, dev_minor);
6286 #endif
6288 switch (file_type) {
6289 #if defined(S_IFIFO)
6290 case UNIX_TYPE_FIFO:
6291 unixmode |= S_IFIFO;
6292 break;
6293 #endif
6294 #if defined(S_IFSOCK)
6295 case UNIX_TYPE_SOCKET:
6296 unixmode |= S_IFSOCK;
6297 break;
6298 #endif
6299 #if defined(S_IFCHR)
6300 case UNIX_TYPE_CHARDEV:
6301 unixmode |= S_IFCHR;
6302 break;
6303 #endif
6304 #if defined(S_IFBLK)
6305 case UNIX_TYPE_BLKDEV:
6306 unixmode |= S_IFBLK;
6307 break;
6308 #endif
6309 default:
6310 return NT_STATUS_INVALID_PARAMETER;
6313 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6314 "%.0f mode 0%o for file %s\n", (double)dev,
6315 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6317 /* Ok - do the mknod. */
6318 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6319 return map_nt_error_from_unix(errno);
6322 /* If any of the other "set" calls fail we
6323 * don't want to end up with a half-constructed mknod.
6326 if (lp_inherit_perms(SNUM(conn))) {
6327 char *parent;
6328 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6329 &parent, NULL)) {
6330 return NT_STATUS_NO_MEMORY;
6332 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6333 unixmode);
6334 TALLOC_FREE(parent);
6337 return NT_STATUS_OK;
6340 /****************************************************************************
6341 Deal with SMB_SET_FILE_UNIX_BASIC.
6342 ****************************************************************************/
6344 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6345 struct smb_request *req,
6346 const char *pdata,
6347 int total_data,
6348 files_struct *fsp,
6349 const struct smb_filename *smb_fname)
6351 struct smb_file_time ft;
6352 uint32 raw_unixmode;
6353 mode_t unixmode;
6354 SMB_OFF_T size = 0;
6355 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6356 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6357 NTSTATUS status = NT_STATUS_OK;
6358 bool delete_on_fail = False;
6359 enum perm_type ptype;
6360 files_struct *all_fsps = NULL;
6361 bool modify_mtime = true;
6362 struct file_id id;
6363 SMB_STRUCT_STAT sbuf;
6365 ZERO_STRUCT(ft);
6367 if (total_data < 100) {
6368 return NT_STATUS_INVALID_PARAMETER;
6371 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6372 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6373 size=IVAL(pdata,0); /* first 8 Bytes are size */
6374 #ifdef LARGE_SMB_OFF_T
6375 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6376 #else /* LARGE_SMB_OFF_T */
6377 if (IVAL(pdata,4) != 0) {
6378 /* more than 32 bits? */
6379 return NT_STATUS_INVALID_PARAMETER;
6381 #endif /* LARGE_SMB_OFF_T */
6384 ft.atime = interpret_long_date(pdata+24); /* access_time */
6385 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6386 set_owner = (uid_t)IVAL(pdata,40);
6387 set_grp = (gid_t)IVAL(pdata,48);
6388 raw_unixmode = IVAL(pdata,84);
6390 if (VALID_STAT(smb_fname->st)) {
6391 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6392 ptype = PERM_EXISTING_DIR;
6393 } else {
6394 ptype = PERM_EXISTING_FILE;
6396 } else {
6397 ptype = PERM_NEW_FILE;
6400 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6401 ptype, &unixmode);
6402 if (!NT_STATUS_IS_OK(status)) {
6403 return status;
6406 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6407 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6408 smb_fname_str_dbg(smb_fname), (double)size,
6409 (unsigned int)set_owner, (unsigned int)set_grp,
6410 (int)raw_unixmode));
6412 sbuf = smb_fname->st;
6414 if (!VALID_STAT(sbuf)) {
6415 struct smb_filename *smb_fname_tmp = NULL;
6417 * The only valid use of this is to create character and block
6418 * devices, and named pipes. This is deprecated (IMHO) and
6419 * a new info level should be used for mknod. JRA.
6422 status = smb_unix_mknod(conn,
6423 pdata,
6424 total_data,
6425 smb_fname);
6426 if (!NT_STATUS_IS_OK(status)) {
6427 return status;
6430 status = copy_smb_filename(talloc_tos(), smb_fname,
6431 &smb_fname_tmp);
6432 if (!NT_STATUS_IS_OK(status)) {
6433 return status;
6436 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6437 status = map_nt_error_from_unix(errno);
6438 TALLOC_FREE(smb_fname_tmp);
6439 SMB_VFS_UNLINK(conn, smb_fname);
6440 return status;
6443 sbuf = smb_fname_tmp->st;
6444 TALLOC_FREE(smb_fname_tmp);
6446 /* Ensure we don't try and change anything else. */
6447 raw_unixmode = SMB_MODE_NO_CHANGE;
6448 size = get_file_size_stat(&sbuf);
6449 ft.atime = sbuf.st_ex_atime;
6450 ft.mtime = sbuf.st_ex_mtime;
6452 * We continue here as we might want to change the
6453 * owner uid/gid.
6455 delete_on_fail = True;
6458 #if 1
6459 /* Horrible backwards compatibility hack as an old server bug
6460 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6461 * */
6463 if (!size) {
6464 size = get_file_size_stat(&sbuf);
6466 #endif
6469 * Deal with the UNIX specific mode set.
6472 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6473 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6474 "setting mode 0%o for file %s\n",
6475 (unsigned int)unixmode,
6476 smb_fname_str_dbg(smb_fname)));
6477 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6478 return map_nt_error_from_unix(errno);
6483 * Deal with the UNIX specific uid set.
6486 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6487 (sbuf.st_ex_uid != set_owner)) {
6488 int ret;
6490 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6491 "changing owner %u for path %s\n",
6492 (unsigned int)set_owner,
6493 smb_fname_str_dbg(smb_fname)));
6495 if (S_ISLNK(sbuf.st_ex_mode)) {
6496 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6497 set_owner, (gid_t)-1);
6498 } else {
6499 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6500 set_owner, (gid_t)-1);
6503 if (ret != 0) {
6504 status = map_nt_error_from_unix(errno);
6505 if (delete_on_fail) {
6506 SMB_VFS_UNLINK(conn, smb_fname);
6508 return status;
6513 * Deal with the UNIX specific gid set.
6516 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6517 (sbuf.st_ex_gid != set_grp)) {
6518 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6519 "changing group %u for file %s\n",
6520 (unsigned int)set_owner,
6521 smb_fname_str_dbg(smb_fname)));
6522 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6523 set_grp) != 0) {
6524 status = map_nt_error_from_unix(errno);
6525 if (delete_on_fail) {
6526 SMB_VFS_UNLINK(conn, smb_fname);
6528 return status;
6532 /* Deal with any size changes. */
6534 status = smb_set_file_size(conn, req,
6535 fsp,
6536 smb_fname,
6537 &sbuf,
6538 size);
6539 if (!NT_STATUS_IS_OK(status)) {
6540 return status;
6543 /* Deal with any time changes. */
6544 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6545 /* No change, don't cancel anything. */
6546 return status;
6549 id = vfs_file_id_from_sbuf(conn, &sbuf);
6550 for(all_fsps = file_find_di_first(id); all_fsps;
6551 all_fsps = file_find_di_next(all_fsps)) {
6553 * We're setting the time explicitly for UNIX.
6554 * Cancel any pending changes over all handles.
6556 all_fsps->update_write_time_on_close = false;
6557 TALLOC_FREE(all_fsps->update_write_time_event);
6561 * Override the "setting_write_time"
6562 * parameter here as it almost does what
6563 * we need. Just remember if we modified
6564 * mtime and send the notify ourselves.
6566 if (null_timespec(ft.mtime)) {
6567 modify_mtime = false;
6570 status = smb_set_file_time(conn,
6571 fsp,
6572 smb_fname,
6573 &ft,
6574 false);
6575 if (modify_mtime) {
6576 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6577 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6579 return status;
6582 /****************************************************************************
6583 Deal with SMB_SET_FILE_UNIX_INFO2.
6584 ****************************************************************************/
6586 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6587 struct smb_request *req,
6588 const char *pdata,
6589 int total_data,
6590 files_struct *fsp,
6591 const struct smb_filename *smb_fname)
6593 NTSTATUS status;
6594 uint32 smb_fflags;
6595 uint32 smb_fmask;
6597 if (total_data < 116) {
6598 return NT_STATUS_INVALID_PARAMETER;
6601 /* Start by setting all the fields that are common between UNIX_BASIC
6602 * and UNIX_INFO2.
6604 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6605 fsp, smb_fname);
6606 if (!NT_STATUS_IS_OK(status)) {
6607 return status;
6610 smb_fflags = IVAL(pdata, 108);
6611 smb_fmask = IVAL(pdata, 112);
6613 /* NB: We should only attempt to alter the file flags if the client
6614 * sends a non-zero mask.
6616 if (smb_fmask != 0) {
6617 int stat_fflags = 0;
6619 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6620 smb_fmask, &stat_fflags)) {
6621 /* Client asked to alter a flag we don't understand. */
6622 return NT_STATUS_INVALID_PARAMETER;
6625 if (fsp && fsp->fh->fd != -1) {
6626 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6627 return NT_STATUS_NOT_SUPPORTED;
6628 } else {
6629 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6630 stat_fflags) != 0) {
6631 return map_nt_error_from_unix(errno);
6636 /* XXX: need to add support for changing the create_time here. You
6637 * can do this for paths on Darwin with setattrlist(2). The right way
6638 * to hook this up is probably by extending the VFS utimes interface.
6641 return NT_STATUS_OK;
6644 /****************************************************************************
6645 Create a directory with POSIX semantics.
6646 ****************************************************************************/
6648 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6649 struct smb_request *req,
6650 char **ppdata,
6651 int total_data,
6652 struct smb_filename *smb_fname,
6653 int *pdata_return_size)
6655 NTSTATUS status = NT_STATUS_OK;
6656 uint32 raw_unixmode = 0;
6657 uint32 mod_unixmode = 0;
6658 mode_t unixmode = (mode_t)0;
6659 files_struct *fsp = NULL;
6660 uint16 info_level_return = 0;
6661 int info;
6662 char *pdata = *ppdata;
6664 if (total_data < 18) {
6665 return NT_STATUS_INVALID_PARAMETER;
6668 raw_unixmode = IVAL(pdata,8);
6669 /* Next 4 bytes are not yet defined. */
6671 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6672 PERM_NEW_DIR, &unixmode);
6673 if (!NT_STATUS_IS_OK(status)) {
6674 return status;
6677 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6679 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6680 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6682 status = SMB_VFS_CREATE_FILE(
6683 conn, /* conn */
6684 req, /* req */
6685 0, /* root_dir_fid */
6686 smb_fname, /* fname */
6687 FILE_READ_ATTRIBUTES, /* access_mask */
6688 FILE_SHARE_NONE, /* share_access */
6689 FILE_CREATE, /* create_disposition*/
6690 FILE_DIRECTORY_FILE, /* create_options */
6691 mod_unixmode, /* file_attributes */
6692 0, /* oplock_request */
6693 0, /* allocation_size */
6694 NULL, /* sd */
6695 NULL, /* ea_list */
6696 &fsp, /* result */
6697 &info); /* pinfo */
6699 if (NT_STATUS_IS_OK(status)) {
6700 close_file(req, fsp, NORMAL_CLOSE);
6703 info_level_return = SVAL(pdata,16);
6705 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6706 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6707 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6708 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6709 } else {
6710 *pdata_return_size = 12;
6713 /* Realloc the data size */
6714 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6715 if (*ppdata == NULL) {
6716 *pdata_return_size = 0;
6717 return NT_STATUS_NO_MEMORY;
6719 pdata = *ppdata;
6721 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6722 SSVAL(pdata,2,0); /* No fnum. */
6723 SIVAL(pdata,4,info); /* Was directory created. */
6725 switch (info_level_return) {
6726 case SMB_QUERY_FILE_UNIX_BASIC:
6727 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6728 SSVAL(pdata,10,0); /* Padding. */
6729 store_file_unix_basic(conn, pdata + 12, fsp,
6730 &smb_fname->st);
6731 break;
6732 case SMB_QUERY_FILE_UNIX_INFO2:
6733 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6734 SSVAL(pdata,10,0); /* Padding. */
6735 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6736 &smb_fname->st);
6737 break;
6738 default:
6739 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6740 SSVAL(pdata,10,0); /* Padding. */
6741 break;
6744 return status;
6747 /****************************************************************************
6748 Open/Create a file with POSIX semantics.
6749 ****************************************************************************/
6751 static NTSTATUS smb_posix_open(connection_struct *conn,
6752 struct smb_request *req,
6753 char **ppdata,
6754 int total_data,
6755 struct smb_filename *smb_fname,
6756 int *pdata_return_size)
6758 bool extended_oplock_granted = False;
6759 char *pdata = *ppdata;
6760 uint32 flags = 0;
6761 uint32 wire_open_mode = 0;
6762 uint32 raw_unixmode = 0;
6763 uint32 mod_unixmode = 0;
6764 uint32 create_disp = 0;
6765 uint32 access_mask = 0;
6766 uint32 create_options = 0;
6767 NTSTATUS status = NT_STATUS_OK;
6768 mode_t unixmode = (mode_t)0;
6769 files_struct *fsp = NULL;
6770 int oplock_request = 0;
6771 int info = 0;
6772 uint16 info_level_return = 0;
6774 if (total_data < 18) {
6775 return NT_STATUS_INVALID_PARAMETER;
6778 flags = IVAL(pdata,0);
6779 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6780 if (oplock_request) {
6781 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6784 wire_open_mode = IVAL(pdata,4);
6786 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6787 return smb_posix_mkdir(conn, req,
6788 ppdata,
6789 total_data,
6790 smb_fname,
6791 pdata_return_size);
6794 switch (wire_open_mode & SMB_ACCMODE) {
6795 case SMB_O_RDONLY:
6796 access_mask = FILE_READ_DATA;
6797 break;
6798 case SMB_O_WRONLY:
6799 access_mask = FILE_WRITE_DATA;
6800 break;
6801 case SMB_O_RDWR:
6802 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6803 break;
6804 default:
6805 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6806 (unsigned int)wire_open_mode ));
6807 return NT_STATUS_INVALID_PARAMETER;
6810 wire_open_mode &= ~SMB_ACCMODE;
6812 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6813 create_disp = FILE_CREATE;
6814 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6815 create_disp = FILE_OVERWRITE_IF;
6816 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6817 create_disp = FILE_OPEN_IF;
6818 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6819 create_disp = FILE_OPEN;
6820 } else {
6821 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6822 (unsigned int)wire_open_mode ));
6823 return NT_STATUS_INVALID_PARAMETER;
6826 raw_unixmode = IVAL(pdata,8);
6827 /* Next 4 bytes are not yet defined. */
6829 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6830 (VALID_STAT(smb_fname->st) ?
6831 PERM_EXISTING_FILE : PERM_NEW_FILE),
6832 &unixmode);
6834 if (!NT_STATUS_IS_OK(status)) {
6835 return status;
6838 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6840 if (wire_open_mode & SMB_O_SYNC) {
6841 create_options |= FILE_WRITE_THROUGH;
6843 if (wire_open_mode & SMB_O_APPEND) {
6844 access_mask |= FILE_APPEND_DATA;
6846 if (wire_open_mode & SMB_O_DIRECT) {
6847 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6850 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6851 smb_fname_str_dbg(smb_fname),
6852 (unsigned int)wire_open_mode,
6853 (unsigned int)unixmode ));
6855 status = SMB_VFS_CREATE_FILE(
6856 conn, /* conn */
6857 req, /* req */
6858 0, /* root_dir_fid */
6859 smb_fname, /* fname */
6860 access_mask, /* access_mask */
6861 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6862 FILE_SHARE_DELETE),
6863 create_disp, /* create_disposition*/
6864 FILE_NON_DIRECTORY_FILE, /* create_options */
6865 mod_unixmode, /* file_attributes */
6866 oplock_request, /* oplock_request */
6867 0, /* allocation_size */
6868 NULL, /* sd */
6869 NULL, /* ea_list */
6870 &fsp, /* result */
6871 &info); /* pinfo */
6873 if (!NT_STATUS_IS_OK(status)) {
6874 return status;
6877 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6878 extended_oplock_granted = True;
6881 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6882 extended_oplock_granted = True;
6885 info_level_return = SVAL(pdata,16);
6887 /* Allocate the correct return size. */
6889 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6890 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6891 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6892 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6893 } else {
6894 *pdata_return_size = 12;
6897 /* Realloc the data size */
6898 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6899 if (*ppdata == NULL) {
6900 close_file(req, fsp, ERROR_CLOSE);
6901 *pdata_return_size = 0;
6902 return NT_STATUS_NO_MEMORY;
6904 pdata = *ppdata;
6906 if (extended_oplock_granted) {
6907 if (flags & REQUEST_BATCH_OPLOCK) {
6908 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6909 } else {
6910 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6912 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6913 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6914 } else {
6915 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6918 SSVAL(pdata,2,fsp->fnum);
6919 SIVAL(pdata,4,info); /* Was file created etc. */
6921 switch (info_level_return) {
6922 case SMB_QUERY_FILE_UNIX_BASIC:
6923 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6924 SSVAL(pdata,10,0); /* padding. */
6925 store_file_unix_basic(conn, pdata + 12, fsp,
6926 &smb_fname->st);
6927 break;
6928 case SMB_QUERY_FILE_UNIX_INFO2:
6929 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6930 SSVAL(pdata,10,0); /* padding. */
6931 store_file_unix_basic_info2(conn, pdata + 12, fsp,
6932 &smb_fname->st);
6933 break;
6934 default:
6935 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6936 SSVAL(pdata,10,0); /* padding. */
6937 break;
6939 return NT_STATUS_OK;
6942 /****************************************************************************
6943 Delete a file with POSIX semantics.
6944 ****************************************************************************/
6946 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6947 struct smb_request *req,
6948 const char *pdata,
6949 int total_data,
6950 struct smb_filename *smb_fname)
6952 NTSTATUS status = NT_STATUS_OK;
6953 files_struct *fsp = NULL;
6954 uint16 flags = 0;
6955 char del = 1;
6956 int info = 0;
6957 int create_options = 0;
6958 int i;
6959 struct share_mode_lock *lck = NULL;
6961 if (total_data < 2) {
6962 return NT_STATUS_INVALID_PARAMETER;
6965 flags = SVAL(pdata,0);
6967 if (!VALID_STAT(smb_fname->st)) {
6968 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6971 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6972 !VALID_STAT_OF_DIR(smb_fname->st)) {
6973 return NT_STATUS_NOT_A_DIRECTORY;
6976 DEBUG(10,("smb_posix_unlink: %s %s\n",
6977 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6978 smb_fname_str_dbg(smb_fname)));
6980 if (VALID_STAT_OF_DIR(smb_fname->st)) {
6981 create_options |= FILE_DIRECTORY_FILE;
6984 status = SMB_VFS_CREATE_FILE(
6985 conn, /* conn */
6986 req, /* req */
6987 0, /* root_dir_fid */
6988 smb_fname, /* fname */
6989 DELETE_ACCESS, /* access_mask */
6990 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6991 FILE_SHARE_DELETE),
6992 FILE_OPEN, /* create_disposition*/
6993 create_options, /* create_options */
6994 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6995 0, /* oplock_request */
6996 0, /* allocation_size */
6997 NULL, /* sd */
6998 NULL, /* ea_list */
6999 &fsp, /* result */
7000 &info); /* pinfo */
7002 if (!NT_STATUS_IS_OK(status)) {
7003 return status;
7007 * Don't lie to client. If we can't really delete due to
7008 * non-POSIX opens return SHARING_VIOLATION.
7011 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7012 NULL);
7013 if (lck == NULL) {
7014 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7015 "lock for file %s\n", fsp_str_dbg(fsp)));
7016 close_file(req, fsp, NORMAL_CLOSE);
7017 return NT_STATUS_INVALID_PARAMETER;
7021 * See if others still have the file open. If this is the case, then
7022 * don't delete. If all opens are POSIX delete we can set the delete
7023 * on close disposition.
7025 for (i=0; i<lck->num_share_modes; i++) {
7026 struct share_mode_entry *e = &lck->share_modes[i];
7027 if (is_valid_share_mode_entry(e)) {
7028 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7029 continue;
7031 /* Fail with sharing violation. */
7032 close_file(req, fsp, NORMAL_CLOSE);
7033 TALLOC_FREE(lck);
7034 return NT_STATUS_SHARING_VIOLATION;
7039 * Set the delete on close.
7041 status = smb_set_file_disposition_info(conn,
7042 &del,
7044 fsp,
7045 smb_fname);
7047 if (!NT_STATUS_IS_OK(status)) {
7048 close_file(req, fsp, NORMAL_CLOSE);
7049 TALLOC_FREE(lck);
7050 return status;
7052 TALLOC_FREE(lck);
7053 return close_file(req, fsp, NORMAL_CLOSE);
7056 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7057 struct smb_request *req,
7058 TALLOC_CTX *mem_ctx,
7059 uint16_t info_level,
7060 files_struct *fsp,
7061 struct smb_filename *smb_fname,
7062 char **ppdata, int total_data,
7063 int *ret_data_size)
7065 char *pdata = *ppdata;
7066 NTSTATUS status = NT_STATUS_OK;
7067 int data_return_size = 0;
7069 *ret_data_size = 0;
7071 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7072 return NT_STATUS_INVALID_LEVEL;
7075 if (!CAN_WRITE(conn)) {
7076 /* Allow POSIX opens. The open path will deny
7077 * any non-readonly opens. */
7078 if (info_level != SMB_POSIX_PATH_OPEN) {
7079 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7083 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7084 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7085 fsp ? fsp->fnum : -1, info_level, total_data));
7087 switch (info_level) {
7089 case SMB_INFO_SET_EA:
7091 status = smb_info_set_ea(conn,
7092 pdata,
7093 total_data,
7094 fsp,
7095 smb_fname);
7096 break;
7099 case SMB_SET_FILE_BASIC_INFO:
7100 case SMB_FILE_BASIC_INFORMATION:
7102 status = smb_set_file_basic_info(conn,
7103 pdata,
7104 total_data,
7105 fsp,
7106 smb_fname);
7107 break;
7110 case SMB_FILE_ALLOCATION_INFORMATION:
7111 case SMB_SET_FILE_ALLOCATION_INFO:
7113 status = smb_set_file_allocation_info(conn, req,
7114 pdata,
7115 total_data,
7116 fsp,
7117 smb_fname);
7118 break;
7121 case SMB_FILE_END_OF_FILE_INFORMATION:
7122 case SMB_SET_FILE_END_OF_FILE_INFO:
7124 status = smb_set_file_end_of_file_info(conn, req,
7125 pdata,
7126 total_data,
7127 fsp,
7128 smb_fname);
7129 break;
7132 case SMB_FILE_DISPOSITION_INFORMATION:
7133 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7135 #if 0
7136 /* JRA - We used to just ignore this on a path ?
7137 * Shouldn't this be invalid level on a pathname
7138 * based call ?
7140 if (tran_call != TRANSACT2_SETFILEINFO) {
7141 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7143 #endif
7144 status = smb_set_file_disposition_info(conn,
7145 pdata,
7146 total_data,
7147 fsp,
7148 smb_fname);
7149 break;
7152 case SMB_FILE_POSITION_INFORMATION:
7154 status = smb_file_position_information(conn,
7155 pdata,
7156 total_data,
7157 fsp);
7158 break;
7161 /* From tridge Samba4 :
7162 * MODE_INFORMATION in setfileinfo (I have no
7163 * idea what "mode information" on a file is - it takes a value of 0,
7164 * 2, 4 or 6. What could it be?).
7167 case SMB_FILE_MODE_INFORMATION:
7169 status = smb_file_mode_information(conn,
7170 pdata,
7171 total_data);
7172 break;
7176 * CIFS UNIX extensions.
7179 case SMB_SET_FILE_UNIX_BASIC:
7181 status = smb_set_file_unix_basic(conn, req,
7182 pdata,
7183 total_data,
7184 fsp,
7185 smb_fname);
7186 break;
7189 case SMB_SET_FILE_UNIX_INFO2:
7191 status = smb_set_file_unix_info2(conn, req,
7192 pdata,
7193 total_data,
7194 fsp,
7195 smb_fname);
7196 break;
7199 case SMB_SET_FILE_UNIX_LINK:
7201 if (fsp) {
7202 /* We must have a pathname for this. */
7203 return NT_STATUS_INVALID_LEVEL;
7205 status = smb_set_file_unix_link(conn, req, pdata,
7206 total_data, smb_fname);
7207 break;
7210 case SMB_SET_FILE_UNIX_HLINK:
7212 if (fsp) {
7213 /* We must have a pathname for this. */
7214 return NT_STATUS_INVALID_LEVEL;
7216 status = smb_set_file_unix_hlink(conn, req,
7217 pdata, total_data,
7218 smb_fname);
7219 break;
7222 case SMB_FILE_RENAME_INFORMATION:
7224 status = smb_file_rename_information(conn, req,
7225 pdata, total_data,
7226 fsp, smb_fname);
7227 break;
7230 #if defined(HAVE_POSIX_ACLS)
7231 case SMB_SET_POSIX_ACL:
7233 status = smb_set_posix_acl(conn,
7234 pdata,
7235 total_data,
7236 fsp,
7237 smb_fname);
7238 break;
7240 #endif
7242 case SMB_SET_POSIX_LOCK:
7244 if (!fsp) {
7245 return NT_STATUS_INVALID_LEVEL;
7247 status = smb_set_posix_lock(conn, req,
7248 pdata, total_data, fsp);
7249 break;
7252 case SMB_POSIX_PATH_OPEN:
7254 if (fsp) {
7255 /* We must have a pathname for this. */
7256 return NT_STATUS_INVALID_LEVEL;
7259 status = smb_posix_open(conn, req,
7260 ppdata,
7261 total_data,
7262 smb_fname,
7263 &data_return_size);
7264 break;
7267 case SMB_POSIX_PATH_UNLINK:
7269 if (fsp) {
7270 /* We must have a pathname for this. */
7271 return NT_STATUS_INVALID_LEVEL;
7274 status = smb_posix_unlink(conn, req,
7275 pdata,
7276 total_data,
7277 smb_fname);
7278 break;
7281 default:
7282 return NT_STATUS_INVALID_LEVEL;
7285 if (!NT_STATUS_IS_OK(status)) {
7286 return status;
7289 *ret_data_size = data_return_size;
7290 return NT_STATUS_OK;
7293 /****************************************************************************
7294 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7295 ****************************************************************************/
7297 static void call_trans2setfilepathinfo(connection_struct *conn,
7298 struct smb_request *req,
7299 unsigned int tran_call,
7300 char **pparams, int total_params,
7301 char **ppdata, int total_data,
7302 unsigned int max_data_bytes)
7304 char *params = *pparams;
7305 char *pdata = *ppdata;
7306 uint16 info_level;
7307 struct smb_filename *smb_fname = NULL;
7308 files_struct *fsp = NULL;
7309 NTSTATUS status = NT_STATUS_OK;
7310 int data_return_size = 0;
7312 if (!params) {
7313 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7314 return;
7317 if (tran_call == TRANSACT2_SETFILEINFO) {
7318 if (total_params < 4) {
7319 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7320 return;
7323 fsp = file_fsp(req, SVAL(params,0));
7324 /* Basic check for non-null fsp. */
7325 if (!check_fsp_open(conn, req, fsp)) {
7326 return;
7328 info_level = SVAL(params,2);
7330 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7331 &smb_fname);
7332 if (!NT_STATUS_IS_OK(status)) {
7333 reply_nterror(req, status);
7334 return;
7337 if(fsp->is_directory || fsp->fh->fd == -1) {
7339 * This is actually a SETFILEINFO on a directory
7340 * handle (returned from an NT SMB). NT5.0 seems
7341 * to do this call. JRA.
7343 if (INFO_LEVEL_IS_UNIX(info_level)) {
7344 /* Always do lstat for UNIX calls. */
7345 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7346 DEBUG(3,("call_trans2setfilepathinfo: "
7347 "SMB_VFS_LSTAT of %s failed "
7348 "(%s)\n",
7349 smb_fname_str_dbg(smb_fname),
7350 strerror(errno)));
7351 reply_nterror(req, map_nt_error_from_unix(errno));
7352 return;
7354 } else {
7355 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7356 DEBUG(3,("call_trans2setfilepathinfo: "
7357 "fileinfo of %s failed (%s)\n",
7358 smb_fname_str_dbg(smb_fname),
7359 strerror(errno)));
7360 reply_nterror(req, map_nt_error_from_unix(errno));
7361 return;
7364 } else if (fsp->print_file) {
7366 * Doing a DELETE_ON_CLOSE should cancel a print job.
7368 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7369 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7371 DEBUG(3,("call_trans2setfilepathinfo: "
7372 "Cancelling print job (%s)\n",
7373 fsp_str_dbg(fsp)));
7375 SSVAL(params,0,0);
7376 send_trans2_replies(conn, req, params, 2,
7377 *ppdata, 0,
7378 max_data_bytes);
7379 return;
7380 } else {
7381 reply_doserror(req, ERRDOS, ERRbadpath);
7382 return;
7384 } else {
7386 * Original code - this is an open file.
7388 if (!check_fsp(conn, req, fsp)) {
7389 return;
7392 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7393 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7394 "of fnum %d failed (%s)\n", fsp->fnum,
7395 strerror(errno)));
7396 reply_nterror(req, map_nt_error_from_unix(errno));
7397 return;
7400 } else {
7401 char *fname = NULL;
7403 /* set path info */
7404 if (total_params < 7) {
7405 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7406 return;
7409 info_level = SVAL(params,0);
7410 srvstr_get_path(req, params, req->flags2, &fname, &params[6],
7411 total_params - 6, STR_TERMINATE,
7412 &status);
7413 if (!NT_STATUS_IS_OK(status)) {
7414 reply_nterror(req, status);
7415 return;
7418 status = filename_convert(req, conn,
7419 req->flags2 & FLAGS2_DFS_PATHNAMES,
7420 fname,
7422 NULL,
7423 &smb_fname);
7424 if (!NT_STATUS_IS_OK(status)) {
7425 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7426 reply_botherror(req,
7427 NT_STATUS_PATH_NOT_COVERED,
7428 ERRSRV, ERRbadpath);
7429 return;
7431 reply_nterror(req, status);
7432 return;
7435 if (INFO_LEVEL_IS_UNIX(info_level)) {
7437 * For CIFS UNIX extensions the target name may not exist.
7440 /* Always do lstat for UNIX calls. */
7441 SMB_VFS_LSTAT(conn, smb_fname);
7443 } else if (!VALID_STAT(smb_fname->st) &&
7444 SMB_VFS_STAT(conn, smb_fname)) {
7445 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7446 "%s failed (%s)\n",
7447 smb_fname_str_dbg(smb_fname),
7448 strerror(errno)));
7449 reply_nterror(req, map_nt_error_from_unix(errno));
7450 return;
7454 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7455 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7456 fsp ? fsp->fnum : -1, info_level,total_data));
7458 /* Realloc the parameter size */
7459 *pparams = (char *)SMB_REALLOC(*pparams,2);
7460 if (*pparams == NULL) {
7461 reply_nterror(req, NT_STATUS_NO_MEMORY);
7462 return;
7464 params = *pparams;
7466 SSVAL(params,0,0);
7468 status = smbd_do_setfilepathinfo(conn, req, req,
7469 info_level,
7470 fsp,
7471 smb_fname,
7472 ppdata, total_data,
7473 &data_return_size);
7474 if (!NT_STATUS_IS_OK(status)) {
7475 if (open_was_deferred(req->mid)) {
7476 /* We have re-scheduled this call. */
7477 return;
7479 if (blocking_lock_was_deferred(req->mid)) {
7480 /* We have re-scheduled this call. */
7481 return;
7483 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7484 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7485 ERRSRV, ERRbadpath);
7486 return;
7488 if (info_level == SMB_POSIX_PATH_OPEN) {
7489 reply_openerror(req, status);
7490 return;
7493 reply_nterror(req, status);
7494 return;
7497 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7498 max_data_bytes);
7500 return;
7503 /****************************************************************************
7504 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7505 ****************************************************************************/
7507 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7508 char **pparams, int total_params,
7509 char **ppdata, int total_data,
7510 unsigned int max_data_bytes)
7512 struct smb_filename *smb_dname = NULL;
7513 char *params = *pparams;
7514 char *pdata = *ppdata;
7515 char *directory = NULL;
7516 NTSTATUS status = NT_STATUS_OK;
7517 struct ea_list *ea_list = NULL;
7518 TALLOC_CTX *ctx = talloc_tos();
7520 if (!CAN_WRITE(conn)) {
7521 reply_doserror(req, ERRSRV, ERRaccess);
7522 return;
7525 if (total_params < 5) {
7526 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7527 return;
7530 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7531 total_params - 4, STR_TERMINATE,
7532 &status);
7533 if (!NT_STATUS_IS_OK(status)) {
7534 reply_nterror(req, status);
7535 return;
7538 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7540 status = filename_convert(ctx,
7541 conn,
7542 req->flags2 & FLAGS2_DFS_PATHNAMES,
7543 directory,
7545 NULL,
7546 &smb_dname);
7548 if (!NT_STATUS_IS_OK(status)) {
7549 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7550 reply_botherror(req,
7551 NT_STATUS_PATH_NOT_COVERED,
7552 ERRSRV, ERRbadpath);
7553 return;
7555 reply_nterror(req, status);
7556 return;
7559 /* Any data in this call is an EA list. */
7560 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7561 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7562 goto out;
7566 * OS/2 workplace shell seems to send SET_EA requests of "null"
7567 * length (4 bytes containing IVAL 4).
7568 * They seem to have no effect. Bug #3212. JRA.
7571 if (total_data != 4) {
7572 if (total_data < 10) {
7573 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7574 goto out;
7577 if (IVAL(pdata,0) > total_data) {
7578 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7579 IVAL(pdata,0), (unsigned int)total_data));
7580 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7581 goto out;
7584 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7585 total_data - 4);
7586 if (!ea_list) {
7587 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7588 goto out;
7591 /* If total_data == 4 Windows doesn't care what values
7592 * are placed in that field, it just ignores them.
7593 * The System i QNTC IBM SMB client puts bad values here,
7594 * so ignore them. */
7596 status = create_directory(conn, req, smb_dname);
7598 if (!NT_STATUS_IS_OK(status)) {
7599 reply_nterror(req, status);
7600 goto out;
7603 /* Try and set any given EA. */
7604 if (ea_list) {
7605 status = set_ea(conn, NULL, smb_dname, ea_list);
7606 if (!NT_STATUS_IS_OK(status)) {
7607 reply_nterror(req, status);
7608 goto out;
7612 /* Realloc the parameter and data sizes */
7613 *pparams = (char *)SMB_REALLOC(*pparams,2);
7614 if(*pparams == NULL) {
7615 reply_nterror(req, NT_STATUS_NO_MEMORY);
7616 goto out;
7618 params = *pparams;
7620 SSVAL(params,0,0);
7622 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7624 out:
7625 TALLOC_FREE(smb_dname);
7626 return;
7629 /****************************************************************************
7630 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7631 We don't actually do this - we just send a null response.
7632 ****************************************************************************/
7634 static void call_trans2findnotifyfirst(connection_struct *conn,
7635 struct smb_request *req,
7636 char **pparams, int total_params,
7637 char **ppdata, int total_data,
7638 unsigned int max_data_bytes)
7640 char *params = *pparams;
7641 uint16 info_level;
7643 if (total_params < 6) {
7644 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7645 return;
7648 info_level = SVAL(params,4);
7649 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7651 switch (info_level) {
7652 case 1:
7653 case 2:
7654 break;
7655 default:
7656 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7657 return;
7660 /* Realloc the parameter and data sizes */
7661 *pparams = (char *)SMB_REALLOC(*pparams,6);
7662 if (*pparams == NULL) {
7663 reply_nterror(req, NT_STATUS_NO_MEMORY);
7664 return;
7666 params = *pparams;
7668 SSVAL(params,0,fnf_handle);
7669 SSVAL(params,2,0); /* No changes */
7670 SSVAL(params,4,0); /* No EA errors */
7672 fnf_handle++;
7674 if(fnf_handle == 0)
7675 fnf_handle = 257;
7677 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7679 return;
7682 /****************************************************************************
7683 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7684 changes). Currently this does nothing.
7685 ****************************************************************************/
7687 static void call_trans2findnotifynext(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;
7695 DEBUG(3,("call_trans2findnotifynext\n"));
7697 /* Realloc the parameter and data sizes */
7698 *pparams = (char *)SMB_REALLOC(*pparams,4);
7699 if (*pparams == NULL) {
7700 reply_nterror(req, NT_STATUS_NO_MEMORY);
7701 return;
7703 params = *pparams;
7705 SSVAL(params,0,0); /* No changes */
7706 SSVAL(params,2,0); /* No EA errors */
7708 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7710 return;
7713 /****************************************************************************
7714 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7715 ****************************************************************************/
7717 static void call_trans2getdfsreferral(connection_struct *conn,
7718 struct smb_request *req,
7719 char **pparams, int total_params,
7720 char **ppdata, int total_data,
7721 unsigned int max_data_bytes)
7723 char *params = *pparams;
7724 char *pathname = NULL;
7725 int reply_size = 0;
7726 int max_referral_level;
7727 NTSTATUS status = NT_STATUS_OK;
7728 TALLOC_CTX *ctx = talloc_tos();
7730 DEBUG(10,("call_trans2getdfsreferral\n"));
7732 if (total_params < 3) {
7733 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7734 return;
7737 max_referral_level = SVAL(params,0);
7739 if(!lp_host_msdfs()) {
7740 reply_doserror(req, ERRDOS, ERRbadfunc);
7741 return;
7744 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7745 total_params - 2, STR_TERMINATE);
7746 if (!pathname) {
7747 reply_nterror(req, NT_STATUS_NOT_FOUND);
7748 return;
7750 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7751 ppdata,&status)) < 0) {
7752 reply_nterror(req, status);
7753 return;
7756 SSVAL(req->inbuf, smb_flg2,
7757 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7758 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7760 return;
7763 #define LMCAT_SPL 0x53
7764 #define LMFUNC_GETJOBID 0x60
7766 /****************************************************************************
7767 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7768 ****************************************************************************/
7770 static void call_trans2ioctl(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 *pdata = *ppdata;
7777 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7779 /* check for an invalid fid before proceeding */
7781 if (!fsp) {
7782 reply_doserror(req, ERRDOS, ERRbadfid);
7783 return;
7786 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7787 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7788 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7789 if (*ppdata == NULL) {
7790 reply_nterror(req, NT_STATUS_NO_MEMORY);
7791 return;
7793 pdata = *ppdata;
7795 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7796 CAN ACCEPT THIS IN UNICODE. JRA. */
7798 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7799 srvstr_push(pdata, req->flags2, pdata + 2,
7800 global_myname(), 15,
7801 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7802 srvstr_push(pdata, req->flags2, pdata+18,
7803 lp_servicename(SNUM(conn)), 13,
7804 STR_ASCII|STR_TERMINATE); /* Service name */
7805 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7806 max_data_bytes);
7807 return;
7810 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7811 reply_doserror(req, ERRSRV, ERRerror);
7814 /****************************************************************************
7815 Reply to a SMBfindclose (stop trans2 directory search).
7816 ****************************************************************************/
7818 void reply_findclose(struct smb_request *req)
7820 int dptr_num;
7822 START_PROFILE(SMBfindclose);
7824 if (req->wct < 1) {
7825 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7826 END_PROFILE(SMBfindclose);
7827 return;
7830 dptr_num = SVALS(req->vwv+0, 0);
7832 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7834 dptr_close(&dptr_num);
7836 reply_outbuf(req, 0, 0);
7838 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7840 END_PROFILE(SMBfindclose);
7841 return;
7844 /****************************************************************************
7845 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7846 ****************************************************************************/
7848 void reply_findnclose(struct smb_request *req)
7850 int dptr_num;
7852 START_PROFILE(SMBfindnclose);
7854 if (req->wct < 1) {
7855 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7856 END_PROFILE(SMBfindnclose);
7857 return;
7860 dptr_num = SVAL(req->vwv+0, 0);
7862 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7864 /* We never give out valid handles for a
7865 findnotifyfirst - so any dptr_num is ok here.
7866 Just ignore it. */
7868 reply_outbuf(req, 0, 0);
7870 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7872 END_PROFILE(SMBfindnclose);
7873 return;
7876 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7877 struct trans_state *state)
7879 if (Protocol >= PROTOCOL_NT1) {
7880 req->flags2 |= 0x40; /* IS_LONG_NAME */
7881 SSVAL(req->inbuf,smb_flg2,req->flags2);
7884 if (conn->encrypt_level == Required && !req->encrypted) {
7885 if (state->call != TRANSACT2_QFSINFO &&
7886 state->call != TRANSACT2_SETFSINFO) {
7887 DEBUG(0,("handle_trans2: encryption required "
7888 "with call 0x%x\n",
7889 (unsigned int)state->call));
7890 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7891 return;
7895 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7897 /* Now we must call the relevant TRANS2 function */
7898 switch(state->call) {
7899 case TRANSACT2_OPEN:
7901 START_PROFILE(Trans2_open);
7902 call_trans2open(conn, req,
7903 &state->param, state->total_param,
7904 &state->data, state->total_data,
7905 state->max_data_return);
7906 END_PROFILE(Trans2_open);
7907 break;
7910 case TRANSACT2_FINDFIRST:
7912 START_PROFILE(Trans2_findfirst);
7913 call_trans2findfirst(conn, req,
7914 &state->param, state->total_param,
7915 &state->data, state->total_data,
7916 state->max_data_return);
7917 END_PROFILE(Trans2_findfirst);
7918 break;
7921 case TRANSACT2_FINDNEXT:
7923 START_PROFILE(Trans2_findnext);
7924 call_trans2findnext(conn, req,
7925 &state->param, state->total_param,
7926 &state->data, state->total_data,
7927 state->max_data_return);
7928 END_PROFILE(Trans2_findnext);
7929 break;
7932 case TRANSACT2_QFSINFO:
7934 START_PROFILE(Trans2_qfsinfo);
7935 call_trans2qfsinfo(conn, req,
7936 &state->param, state->total_param,
7937 &state->data, state->total_data,
7938 state->max_data_return);
7939 END_PROFILE(Trans2_qfsinfo);
7940 break;
7943 case TRANSACT2_SETFSINFO:
7945 START_PROFILE(Trans2_setfsinfo);
7946 call_trans2setfsinfo(conn, req,
7947 &state->param, state->total_param,
7948 &state->data, state->total_data,
7949 state->max_data_return);
7950 END_PROFILE(Trans2_setfsinfo);
7951 break;
7954 case TRANSACT2_QPATHINFO:
7955 case TRANSACT2_QFILEINFO:
7957 START_PROFILE(Trans2_qpathinfo);
7958 call_trans2qfilepathinfo(conn, req, state->call,
7959 &state->param, state->total_param,
7960 &state->data, state->total_data,
7961 state->max_data_return);
7962 END_PROFILE(Trans2_qpathinfo);
7963 break;
7966 case TRANSACT2_SETPATHINFO:
7967 case TRANSACT2_SETFILEINFO:
7969 START_PROFILE(Trans2_setpathinfo);
7970 call_trans2setfilepathinfo(conn, req, state->call,
7971 &state->param, state->total_param,
7972 &state->data, state->total_data,
7973 state->max_data_return);
7974 END_PROFILE(Trans2_setpathinfo);
7975 break;
7978 case TRANSACT2_FINDNOTIFYFIRST:
7980 START_PROFILE(Trans2_findnotifyfirst);
7981 call_trans2findnotifyfirst(conn, req,
7982 &state->param, state->total_param,
7983 &state->data, state->total_data,
7984 state->max_data_return);
7985 END_PROFILE(Trans2_findnotifyfirst);
7986 break;
7989 case TRANSACT2_FINDNOTIFYNEXT:
7991 START_PROFILE(Trans2_findnotifynext);
7992 call_trans2findnotifynext(conn, req,
7993 &state->param, state->total_param,
7994 &state->data, state->total_data,
7995 state->max_data_return);
7996 END_PROFILE(Trans2_findnotifynext);
7997 break;
8000 case TRANSACT2_MKDIR:
8002 START_PROFILE(Trans2_mkdir);
8003 call_trans2mkdir(conn, req,
8004 &state->param, state->total_param,
8005 &state->data, state->total_data,
8006 state->max_data_return);
8007 END_PROFILE(Trans2_mkdir);
8008 break;
8011 case TRANSACT2_GET_DFS_REFERRAL:
8013 START_PROFILE(Trans2_get_dfs_referral);
8014 call_trans2getdfsreferral(conn, req,
8015 &state->param, state->total_param,
8016 &state->data, state->total_data,
8017 state->max_data_return);
8018 END_PROFILE(Trans2_get_dfs_referral);
8019 break;
8022 case TRANSACT2_IOCTL:
8024 START_PROFILE(Trans2_ioctl);
8025 call_trans2ioctl(conn, req,
8026 &state->param, state->total_param,
8027 &state->data, state->total_data,
8028 state->max_data_return);
8029 END_PROFILE(Trans2_ioctl);
8030 break;
8033 default:
8034 /* Error in request */
8035 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8036 reply_doserror(req, ERRSRV,ERRerror);
8040 /****************************************************************************
8041 Reply to a SMBtrans2.
8042 ****************************************************************************/
8044 void reply_trans2(struct smb_request *req)
8046 connection_struct *conn = req->conn;
8047 unsigned int dsoff;
8048 unsigned int dscnt;
8049 unsigned int psoff;
8050 unsigned int pscnt;
8051 unsigned int tran_call;
8052 struct trans_state *state;
8053 NTSTATUS result;
8055 START_PROFILE(SMBtrans2);
8057 if (req->wct < 14) {
8058 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8059 END_PROFILE(SMBtrans2);
8060 return;
8063 dsoff = SVAL(req->vwv+12, 0);
8064 dscnt = SVAL(req->vwv+11, 0);
8065 psoff = SVAL(req->vwv+10, 0);
8066 pscnt = SVAL(req->vwv+9, 0);
8067 tran_call = SVAL(req->vwv+14, 0);
8069 result = allow_new_trans(conn->pending_trans, req->mid);
8070 if (!NT_STATUS_IS_OK(result)) {
8071 DEBUG(2, ("Got invalid trans2 request: %s\n",
8072 nt_errstr(result)));
8073 reply_nterror(req, result);
8074 END_PROFILE(SMBtrans2);
8075 return;
8078 if (IS_IPC(conn)) {
8079 switch (tran_call) {
8080 /* List the allowed trans2 calls on IPC$ */
8081 case TRANSACT2_OPEN:
8082 case TRANSACT2_GET_DFS_REFERRAL:
8083 case TRANSACT2_QFILEINFO:
8084 case TRANSACT2_QFSINFO:
8085 case TRANSACT2_SETFSINFO:
8086 break;
8087 default:
8088 reply_doserror(req, ERRSRV, ERRaccess);
8089 END_PROFILE(SMBtrans2);
8090 return;
8094 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8095 DEBUG(0, ("talloc failed\n"));
8096 reply_nterror(req, NT_STATUS_NO_MEMORY);
8097 END_PROFILE(SMBtrans2);
8098 return;
8101 state->cmd = SMBtrans2;
8103 state->mid = req->mid;
8104 state->vuid = req->vuid;
8105 state->setup_count = SVAL(req->vwv+13, 0);
8106 state->setup = NULL;
8107 state->total_param = SVAL(req->vwv+0, 0);
8108 state->param = NULL;
8109 state->total_data = SVAL(req->vwv+1, 0);
8110 state->data = NULL;
8111 state->max_param_return = SVAL(req->vwv+2, 0);
8112 state->max_data_return = SVAL(req->vwv+3, 0);
8113 state->max_setup_return = SVAL(req->vwv+4, 0);
8114 state->close_on_completion = BITSETW(req->vwv+5, 0);
8115 state->one_way = BITSETW(req->vwv+5, 1);
8117 state->call = tran_call;
8119 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8120 is so as a sanity check */
8121 if (state->setup_count != 1) {
8123 * Need to have rc=0 for ioctl to get job id for OS/2.
8124 * Network printing will fail if function is not successful.
8125 * Similar function in reply.c will be used if protocol
8126 * is LANMAN1.0 instead of LM1.2X002.
8127 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8128 * outbuf doesn't have to be set(only job id is used).
8130 if ( (state->setup_count == 4)
8131 && (tran_call == TRANSACT2_IOCTL)
8132 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8133 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8134 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8135 } else {
8136 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8137 DEBUG(2,("Transaction is %d\n",tran_call));
8138 TALLOC_FREE(state);
8139 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8140 END_PROFILE(SMBtrans2);
8141 return;
8145 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8146 goto bad_param;
8148 if (state->total_data) {
8150 if (trans_oob(state->total_data, 0, dscnt)
8151 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8152 goto bad_param;
8155 /* Can't use talloc here, the core routines do realloc on the
8156 * params and data. */
8157 state->data = (char *)SMB_MALLOC(state->total_data);
8158 if (state->data == NULL) {
8159 DEBUG(0,("reply_trans2: data malloc fail for %u "
8160 "bytes !\n", (unsigned int)state->total_data));
8161 TALLOC_FREE(state);
8162 reply_nterror(req, NT_STATUS_NO_MEMORY);
8163 END_PROFILE(SMBtrans2);
8164 return;
8167 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8170 if (state->total_param) {
8172 if (trans_oob(state->total_param, 0, pscnt)
8173 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8174 goto bad_param;
8177 /* Can't use talloc here, the core routines do realloc on the
8178 * params and data. */
8179 state->param = (char *)SMB_MALLOC(state->total_param);
8180 if (state->param == NULL) {
8181 DEBUG(0,("reply_trans: param malloc fail for %u "
8182 "bytes !\n", (unsigned int)state->total_param));
8183 SAFE_FREE(state->data);
8184 TALLOC_FREE(state);
8185 reply_nterror(req, NT_STATUS_NO_MEMORY);
8186 END_PROFILE(SMBtrans2);
8187 return;
8190 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8193 state->received_data = dscnt;
8194 state->received_param = pscnt;
8196 if ((state->received_param == state->total_param) &&
8197 (state->received_data == state->total_data)) {
8199 handle_trans2(conn, req, state);
8201 SAFE_FREE(state->data);
8202 SAFE_FREE(state->param);
8203 TALLOC_FREE(state);
8204 END_PROFILE(SMBtrans2);
8205 return;
8208 DLIST_ADD(conn->pending_trans, state);
8210 /* We need to send an interim response then receive the rest
8211 of the parameter/data bytes */
8212 reply_outbuf(req, 0, 0);
8213 show_msg((char *)req->outbuf);
8214 END_PROFILE(SMBtrans2);
8215 return;
8217 bad_param:
8219 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8220 SAFE_FREE(state->data);
8221 SAFE_FREE(state->param);
8222 TALLOC_FREE(state);
8223 END_PROFILE(SMBtrans2);
8224 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8228 /****************************************************************************
8229 Reply to a SMBtranss2
8230 ****************************************************************************/
8232 void reply_transs2(struct smb_request *req)
8234 connection_struct *conn = req->conn;
8235 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8236 struct trans_state *state;
8238 START_PROFILE(SMBtranss2);
8240 show_msg((char *)req->inbuf);
8242 if (req->wct < 8) {
8243 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8244 END_PROFILE(SMBtranss2);
8245 return;
8248 for (state = conn->pending_trans; state != NULL;
8249 state = state->next) {
8250 if (state->mid == req->mid) {
8251 break;
8255 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8257 END_PROFILE(SMBtranss2);
8258 return;
8261 /* Revise state->total_param and state->total_data in case they have
8262 changed downwards */
8264 if (SVAL(req->vwv+0, 0) < state->total_param)
8265 state->total_param = SVAL(req->vwv+0, 0);
8266 if (SVAL(req->vwv+1, 0) < state->total_data)
8267 state->total_data = SVAL(req->vwv+1, 0);
8269 pcnt = SVAL(req->vwv+2, 0);
8270 poff = SVAL(req->vwv+3, 0);
8271 pdisp = SVAL(req->vwv+4, 0);
8273 dcnt = SVAL(req->vwv+5, 0);
8274 doff = SVAL(req->vwv+6, 0);
8275 ddisp = SVAL(req->vwv+7, 0);
8277 state->received_param += pcnt;
8278 state->received_data += dcnt;
8280 if ((state->received_data > state->total_data) ||
8281 (state->received_param > state->total_param))
8282 goto bad_param;
8284 if (pcnt) {
8285 if (trans_oob(state->total_param, pdisp, pcnt)
8286 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8287 goto bad_param;
8289 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8292 if (dcnt) {
8293 if (trans_oob(state->total_data, ddisp, dcnt)
8294 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8295 goto bad_param;
8297 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8300 if ((state->received_param < state->total_param) ||
8301 (state->received_data < state->total_data)) {
8302 END_PROFILE(SMBtranss2);
8303 return;
8306 handle_trans2(conn, req, state);
8308 DLIST_REMOVE(conn->pending_trans, state);
8309 SAFE_FREE(state->data);
8310 SAFE_FREE(state->param);
8311 TALLOC_FREE(state);
8313 END_PROFILE(SMBtranss2);
8314 return;
8316 bad_param:
8318 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8319 DLIST_REMOVE(conn->pending_trans, state);
8320 SAFE_FREE(state->data);
8321 SAFE_FREE(state->param);
8322 TALLOC_FREE(state);
8323 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8324 END_PROFILE(SMBtranss2);
8325 return;