Fix bug #6421 - POSIX read-only open fails on read-only shares.
[Samba.git] / source3 / smbd / trans2.c
blob931b7df4bca29a66258dd9959a62169e2aa9498f
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"
30 extern enum protocol_types Protocol;
32 #define DIR_ENTRY_SAFETY_MARGIN 4096
34 static char *store_file_unix_basic(connection_struct *conn,
35 char *pdata,
36 files_struct *fsp,
37 const SMB_STRUCT_STAT *psbuf);
39 static char *store_file_unix_basic_info2(connection_struct *conn,
40 char *pdata,
41 files_struct *fsp,
42 const SMB_STRUCT_STAT *psbuf);
44 /********************************************************************
45 Roundup a value to the nearest allocation roundup size boundary.
46 Only do this for Windows clients.
47 ********************************************************************/
49 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
51 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
53 /* Only roundup for Windows clients. */
54 enum remote_arch_types ra_type = get_remote_arch();
55 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
56 val = SMB_ROUNDUP(val,rval);
58 return val;
61 /****************************************************************************
62 Utility functions for dealing with extended attributes.
63 ****************************************************************************/
65 /****************************************************************************
66 Refuse to allow clients to overwrite our private xattrs.
67 ****************************************************************************/
69 static bool samba_private_attr_name(const char *unix_ea_name)
71 static const char * const prohibited_ea_names[] = {
72 SAMBA_POSIX_INHERITANCE_EA_NAME,
73 SAMBA_XATTR_DOS_ATTRIB,
74 NULL
77 int i;
79 for (i = 0; prohibited_ea_names[i]; i++) {
80 if (strequal( prohibited_ea_names[i], unix_ea_name))
81 return true;
83 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
84 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
85 return true;
87 return false;
90 /****************************************************************************
91 Get one EA value. Fill in a struct ea_struct.
92 ****************************************************************************/
94 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
95 files_struct *fsp, const char *fname,
96 const char *ea_name, struct ea_struct *pea)
98 /* Get the value of this xattr. Max size is 64k. */
99 size_t attr_size = 256;
100 char *val = NULL;
101 ssize_t sizeret;
103 again:
105 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
106 if (!val) {
107 return NT_STATUS_NO_MEMORY;
110 if (fsp && fsp->fh->fd != -1) {
111 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
112 } else {
113 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
116 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
117 attr_size = 65536;
118 goto again;
121 if (sizeret == -1) {
122 return map_nt_error_from_unix(errno);
125 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
126 dump_data(10, (uint8 *)val, sizeret);
128 pea->flags = 0;
129 if (strnequal(ea_name, "user.", 5)) {
130 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
131 } else {
132 pea->name = talloc_strdup(mem_ctx, ea_name);
134 if (pea->name == NULL) {
135 TALLOC_FREE(val);
136 return NT_STATUS_NO_MEMORY;
138 pea->value.data = (unsigned char *)val;
139 pea->value.length = (size_t)sizeret;
140 return NT_STATUS_OK;
143 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
144 files_struct *fsp, const char *fname,
145 char ***pnames, size_t *pnum_names)
147 /* Get a list of all xattrs. Max namesize is 64k. */
148 size_t ea_namelist_size = 1024;
149 char *ea_namelist = NULL;
151 char *p;
152 char **names, **tmp;
153 size_t num_names;
154 ssize_t sizeret = -1;
156 if (!lp_ea_support(SNUM(conn))) {
157 *pnames = NULL;
158 *pnum_names = 0;
159 return NT_STATUS_OK;
163 * TALLOC the result early to get the talloc hierarchy right.
166 names = TALLOC_ARRAY(mem_ctx, char *, 1);
167 if (names == NULL) {
168 DEBUG(0, ("talloc failed\n"));
169 return NT_STATUS_NO_MEMORY;
172 while (ea_namelist_size <= 65536) {
174 ea_namelist = TALLOC_REALLOC_ARRAY(
175 names, ea_namelist, char, ea_namelist_size);
176 if (ea_namelist == NULL) {
177 DEBUG(0, ("talloc failed\n"));
178 TALLOC_FREE(names);
179 return NT_STATUS_NO_MEMORY;
182 if (fsp && fsp->fh->fd != -1) {
183 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
184 ea_namelist_size);
185 } else {
186 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
187 ea_namelist_size);
190 if ((sizeret == -1) && (errno == ERANGE)) {
191 ea_namelist_size *= 2;
193 else {
194 break;
198 if (sizeret == -1) {
199 TALLOC_FREE(names);
200 return map_nt_error_from_unix(errno);
203 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
204 (unsigned int)sizeret));
206 if (sizeret == 0) {
207 TALLOC_FREE(names);
208 *pnames = NULL;
209 *pnum_names = 0;
210 return NT_STATUS_OK;
214 * Ensure the result is 0-terminated
217 if (ea_namelist[sizeret-1] != '\0') {
218 TALLOC_FREE(names);
219 return NT_STATUS_INTERNAL_ERROR;
223 * count the names
225 num_names = 0;
227 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
228 num_names += 1;
231 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
232 if (tmp == NULL) {
233 DEBUG(0, ("talloc failed\n"));
234 TALLOC_FREE(names);
235 return NT_STATUS_NO_MEMORY;
238 names = tmp;
239 num_names = 0;
241 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
242 names[num_names++] = p;
245 *pnames = names;
246 *pnum_names = num_names;
247 return NT_STATUS_OK;
250 /****************************************************************************
251 Return a linked list of the total EA's. Plus the total size
252 ****************************************************************************/
254 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
255 const char *fname, size_t *pea_total_len)
257 /* Get a list of all xattrs. Max namesize is 64k. */
258 size_t i, num_names;
259 char **names;
260 struct ea_list *ea_list_head = NULL;
261 NTSTATUS status;
263 *pea_total_len = 0;
265 if (!lp_ea_support(SNUM(conn))) {
266 return NULL;
269 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
270 &names, &num_names);
272 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
273 return NULL;
276 for (i=0; i<num_names; i++) {
277 struct ea_list *listp;
278 fstring dos_ea_name;
280 if (strnequal(names[i], "system.", 7)
281 || samba_private_attr_name(names[i]))
282 continue;
284 listp = TALLOC_P(mem_ctx, struct ea_list);
285 if (listp == NULL) {
286 return NULL;
289 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
290 fname, names[i],
291 &listp->ea))) {
292 return NULL;
295 push_ascii_fstring(dos_ea_name, listp->ea.name);
297 *pea_total_len +=
298 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
300 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
301 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
302 (unsigned int)listp->ea.value.length));
304 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
308 /* Add on 4 for total length. */
309 if (*pea_total_len) {
310 *pea_total_len += 4;
313 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
314 (unsigned int)*pea_total_len));
316 return ea_list_head;
319 /****************************************************************************
320 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
321 that was filled.
322 ****************************************************************************/
324 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
325 connection_struct *conn, struct ea_list *ea_list)
327 unsigned int ret_data_size = 4;
328 char *p = pdata;
330 SMB_ASSERT(total_data_size >= 4);
332 if (!lp_ea_support(SNUM(conn))) {
333 SIVAL(pdata,4,0);
334 return 4;
337 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
338 size_t dos_namelen;
339 fstring dos_ea_name;
340 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
341 dos_namelen = strlen(dos_ea_name);
342 if (dos_namelen > 255 || dos_namelen == 0) {
343 break;
345 if (ea_list->ea.value.length > 65535) {
346 break;
348 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
349 break;
352 /* We know we have room. */
353 SCVAL(p,0,ea_list->ea.flags);
354 SCVAL(p,1,dos_namelen);
355 SSVAL(p,2,ea_list->ea.value.length);
356 fstrcpy(p+4, dos_ea_name);
357 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
359 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
360 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
363 ret_data_size = PTR_DIFF(p, pdata);
364 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
365 SIVAL(pdata,0,ret_data_size);
366 return ret_data_size;
369 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
371 size_t total_ea_len = 0;
372 TALLOC_CTX *mem_ctx = NULL;
374 if (!lp_ea_support(SNUM(conn))) {
375 return 0;
377 mem_ctx = talloc_tos();
378 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
379 return total_ea_len;
382 /****************************************************************************
383 Ensure the EA name is case insensitive by matching any existing EA name.
384 ****************************************************************************/
386 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
388 size_t total_ea_len;
389 TALLOC_CTX *mem_ctx = talloc_tos();
390 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
392 for (; ea_list; ea_list = ea_list->next) {
393 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
394 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
395 &unix_ea_name[5], ea_list->ea.name));
396 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
397 break;
402 /****************************************************************************
403 Set or delete an extended attribute.
404 ****************************************************************************/
406 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
408 if (!lp_ea_support(SNUM(conn))) {
409 return NT_STATUS_EAS_NOT_SUPPORTED;
412 for (;ea_list; ea_list = ea_list->next) {
413 int ret;
414 fstring unix_ea_name;
416 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
417 fstrcat(unix_ea_name, ea_list->ea.name);
419 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
421 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
423 if (samba_private_attr_name(unix_ea_name)) {
424 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
425 return NT_STATUS_ACCESS_DENIED;
428 if (ea_list->ea.value.length == 0) {
429 /* Remove the attribute. */
430 if (fsp && (fsp->fh->fd != -1)) {
431 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
432 unix_ea_name, fsp->fsp_name));
433 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
434 } else {
435 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
436 unix_ea_name, fname));
437 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
439 #ifdef ENOATTR
440 /* Removing a non existent attribute always succeeds. */
441 if (ret == -1 && errno == ENOATTR) {
442 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
443 unix_ea_name));
444 ret = 0;
446 #endif
447 } else {
448 if (fsp && (fsp->fh->fd != -1)) {
449 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
450 unix_ea_name, fsp->fsp_name));
451 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
452 ea_list->ea.value.data, ea_list->ea.value.length, 0);
453 } else {
454 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
455 unix_ea_name, fname));
456 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
457 ea_list->ea.value.data, ea_list->ea.value.length, 0);
461 if (ret == -1) {
462 #ifdef ENOTSUP
463 if (errno == ENOTSUP) {
464 return NT_STATUS_EAS_NOT_SUPPORTED;
466 #endif
467 return map_nt_error_from_unix(errno);
471 return NT_STATUS_OK;
473 /****************************************************************************
474 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
475 ****************************************************************************/
477 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
479 struct ea_list *ea_list_head = NULL;
480 size_t converted_size, offset = 0;
482 while (offset + 2 < data_size) {
483 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
484 unsigned int namelen = CVAL(pdata,offset);
486 offset++; /* Go past the namelen byte. */
488 /* integer wrap paranioa. */
489 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
490 (offset > data_size) || (namelen > data_size) ||
491 (offset + namelen >= data_size)) {
492 break;
494 /* Ensure the name is null terminated. */
495 if (pdata[offset + namelen] != '\0') {
496 return NULL;
498 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
499 &converted_size)) {
500 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
501 "failed: %s", strerror(errno)));
503 if (!eal->ea.name) {
504 return NULL;
507 offset += (namelen + 1); /* Go past the name + terminating zero. */
508 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
509 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
512 return ea_list_head;
515 /****************************************************************************
516 Read one EA list entry from the buffer.
517 ****************************************************************************/
519 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
521 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
522 uint16 val_len;
523 unsigned int namelen;
524 size_t converted_size;
526 if (!eal) {
527 return NULL;
530 if (data_size < 6) {
531 return NULL;
534 eal->ea.flags = CVAL(pdata,0);
535 namelen = CVAL(pdata,1);
536 val_len = SVAL(pdata,2);
538 if (4 + namelen + 1 + val_len > data_size) {
539 return NULL;
542 /* Ensure the name is null terminated. */
543 if (pdata[namelen + 4] != '\0') {
544 return NULL;
546 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
547 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
548 strerror(errno)));
550 if (!eal->ea.name) {
551 return NULL;
554 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
555 if (!eal->ea.value.data) {
556 return NULL;
559 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
561 /* Ensure we're null terminated just in case we print the value. */
562 eal->ea.value.data[val_len] = '\0';
563 /* But don't count the null. */
564 eal->ea.value.length--;
566 if (pbytes_used) {
567 *pbytes_used = 4 + namelen + 1 + val_len;
570 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
571 dump_data(10, eal->ea.value.data, eal->ea.value.length);
573 return eal;
576 /****************************************************************************
577 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
578 ****************************************************************************/
580 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
582 struct ea_list *ea_list_head = NULL;
583 size_t offset = 0;
584 size_t bytes_used = 0;
586 while (offset < data_size) {
587 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
589 if (!eal) {
590 return NULL;
593 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
594 offset += bytes_used;
597 return ea_list_head;
600 /****************************************************************************
601 Count the total EA size needed.
602 ****************************************************************************/
604 static size_t ea_list_size(struct ea_list *ealist)
606 fstring dos_ea_name;
607 struct ea_list *listp;
608 size_t ret = 0;
610 for (listp = ealist; listp; listp = listp->next) {
611 push_ascii_fstring(dos_ea_name, listp->ea.name);
612 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
614 /* Add on 4 for total length. */
615 if (ret) {
616 ret += 4;
619 return ret;
622 /****************************************************************************
623 Return a union of EA's from a file list and a list of names.
624 The TALLOC context for the two lists *MUST* be identical as we steal
625 memory from one list to add to another. JRA.
626 ****************************************************************************/
628 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
630 struct ea_list *nlistp, *flistp;
632 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
633 for (flistp = file_list; flistp; flistp = flistp->next) {
634 if (strequal(nlistp->ea.name, flistp->ea.name)) {
635 break;
639 if (flistp) {
640 /* Copy the data from this entry. */
641 nlistp->ea.flags = flistp->ea.flags;
642 nlistp->ea.value = flistp->ea.value;
643 } else {
644 /* Null entry. */
645 nlistp->ea.flags = 0;
646 ZERO_STRUCT(nlistp->ea.value);
650 *total_ea_len = ea_list_size(name_list);
651 return name_list;
654 /****************************************************************************
655 Send the required number of replies back.
656 We assume all fields other than the data fields are
657 set correctly for the type of call.
658 HACK ! Always assumes smb_setup field is zero.
659 ****************************************************************************/
661 void send_trans2_replies(connection_struct *conn,
662 struct smb_request *req,
663 const char *params,
664 int paramsize,
665 const char *pdata,
666 int datasize,
667 int max_data_bytes)
669 /* As we are using a protocol > LANMAN1 then the max_send
670 variable must have been set in the sessetupX call.
671 This takes precedence over the max_xmit field in the
672 global struct. These different max_xmit variables should
673 be merged as this is now too confusing */
675 int data_to_send = datasize;
676 int params_to_send = paramsize;
677 int useable_space;
678 const char *pp = params;
679 const char *pd = pdata;
680 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
681 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
682 int data_alignment_offset = 0;
683 bool overflow = False;
685 /* Modify the data_to_send and datasize and set the error if
686 we're trying to send more than max_data_bytes. We still send
687 the part of the packet(s) that fit. Strange, but needed
688 for OS/2. */
690 if (max_data_bytes > 0 && datasize > max_data_bytes) {
691 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
692 max_data_bytes, datasize ));
693 datasize = data_to_send = max_data_bytes;
694 overflow = True;
697 /* If there genuinely are no parameters or data to send just send the empty packet */
699 if(params_to_send == 0 && data_to_send == 0) {
700 reply_outbuf(req, 10, 0);
701 show_msg((char *)req->outbuf);
702 return;
705 /* When sending params and data ensure that both are nicely aligned */
706 /* Only do this alignment when there is also data to send - else
707 can cause NT redirector problems. */
709 if (((params_to_send % 4) != 0) && (data_to_send != 0))
710 data_alignment_offset = 4 - (params_to_send % 4);
712 /* Space is bufsize minus Netbios over TCP header minus SMB header */
713 /* The alignment_offset is to align the param bytes on an even byte
714 boundary. NT 4.0 Beta needs this to work correctly. */
716 useable_space = max_send - (smb_size
717 + 2 * 10 /* wct */
718 + alignment_offset
719 + data_alignment_offset);
721 if (useable_space < 0) {
722 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
723 "= %d!!!", useable_space));
724 exit_server_cleanly("send_trans2_replies: Not enough space");
727 while (params_to_send || data_to_send) {
728 /* Calculate whether we will totally or partially fill this packet */
730 total_sent_thistime = params_to_send + data_to_send;
732 /* We can never send more than useable_space */
734 * Note that 'useable_space' does not include the alignment offsets,
735 * but we must include the alignment offsets in the calculation of
736 * the length of the data we send over the wire, as the alignment offsets
737 * are sent here. Fix from Marc_Jacobsen@hp.com.
740 total_sent_thistime = MIN(total_sent_thistime, useable_space);
742 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
743 + data_alignment_offset);
746 * We might have SMBtrans2s in req which was transferred to
747 * the outbuf, fix that.
749 SCVAL(req->outbuf, smb_com, SMBtrans2);
751 /* Set total params and data to be sent */
752 SSVAL(req->outbuf,smb_tprcnt,paramsize);
753 SSVAL(req->outbuf,smb_tdrcnt,datasize);
755 /* Calculate how many parameters and data we can fit into
756 * this packet. Parameters get precedence
759 params_sent_thistime = MIN(params_to_send,useable_space);
760 data_sent_thistime = useable_space - params_sent_thistime;
761 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
763 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
765 /* smb_proff is the offset from the start of the SMB header to the
766 parameter bytes, however the first 4 bytes of outbuf are
767 the Netbios over TCP header. Thus use smb_base() to subtract
768 them from the calculation */
770 SSVAL(req->outbuf,smb_proff,
771 ((smb_buf(req->outbuf)+alignment_offset)
772 - smb_base(req->outbuf)));
774 if(params_sent_thistime == 0)
775 SSVAL(req->outbuf,smb_prdisp,0);
776 else
777 /* Absolute displacement of param bytes sent in this packet */
778 SSVAL(req->outbuf,smb_prdisp,pp - params);
780 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
781 if(data_sent_thistime == 0) {
782 SSVAL(req->outbuf,smb_droff,0);
783 SSVAL(req->outbuf,smb_drdisp, 0);
784 } else {
785 /* The offset of the data bytes is the offset of the
786 parameter bytes plus the number of parameters being sent this time */
787 SSVAL(req->outbuf, smb_droff,
788 ((smb_buf(req->outbuf)+alignment_offset)
789 - smb_base(req->outbuf))
790 + params_sent_thistime + data_alignment_offset);
791 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
794 /* Initialize the padding for alignment */
796 if (alignment_offset != 0) {
797 memset(smb_buf(req->outbuf), 0, alignment_offset);
800 /* Copy the param bytes into the packet */
802 if(params_sent_thistime) {
803 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
804 params_sent_thistime);
807 /* Copy in the data bytes */
808 if(data_sent_thistime) {
809 if (data_alignment_offset != 0) {
810 memset((smb_buf(req->outbuf)+alignment_offset+
811 params_sent_thistime), 0,
812 data_alignment_offset);
814 memcpy(smb_buf(req->outbuf)+alignment_offset
815 +params_sent_thistime+data_alignment_offset,
816 pd,data_sent_thistime);
819 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
820 params_sent_thistime, data_sent_thistime, useable_space));
821 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
822 params_to_send, data_to_send, paramsize, datasize));
824 if (overflow) {
825 error_packet_set((char *)req->outbuf,
826 ERRDOS,ERRbufferoverflow,
827 STATUS_BUFFER_OVERFLOW,
828 __LINE__,__FILE__);
831 /* Send the packet */
832 show_msg((char *)req->outbuf);
833 if (!srv_send_smb(smbd_server_fd(),
834 (char *)req->outbuf,
835 IS_CONN_ENCRYPTED(conn),
836 &req->pcd))
837 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
839 TALLOC_FREE(req->outbuf);
841 pp += params_sent_thistime;
842 pd += data_sent_thistime;
844 params_to_send -= params_sent_thistime;
845 data_to_send -= data_sent_thistime;
847 /* Sanity check */
848 if(params_to_send < 0 || data_to_send < 0) {
849 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
850 params_to_send, data_to_send));
851 return;
855 return;
858 /****************************************************************************
859 Reply to a TRANSACT2_OPEN.
860 ****************************************************************************/
862 static void call_trans2open(connection_struct *conn,
863 struct smb_request *req,
864 char **pparams, int total_params,
865 char **ppdata, int total_data,
866 unsigned int max_data_bytes)
868 char *params = *pparams;
869 char *pdata = *ppdata;
870 int deny_mode;
871 int32 open_attr;
872 bool oplock_request;
873 #if 0
874 bool return_additional_info;
875 int16 open_sattr;
876 time_t open_time;
877 #endif
878 int open_ofun;
879 uint32 open_size;
880 char *pname;
881 char *fname = NULL;
882 SMB_OFF_T size=0;
883 int fattr=0,mtime=0;
884 SMB_INO_T inode = 0;
885 SMB_STRUCT_STAT sbuf;
886 int smb_action = 0;
887 files_struct *fsp;
888 struct ea_list *ea_list = NULL;
889 uint16 flags = 0;
890 NTSTATUS status;
891 uint32 access_mask;
892 uint32 share_mode;
893 uint32 create_disposition;
894 uint32 create_options = 0;
895 TALLOC_CTX *ctx = talloc_tos();
897 SET_STAT_INVALID(sbuf);
900 * Ensure we have enough parameters to perform the operation.
903 if (total_params < 29) {
904 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
905 return;
908 flags = SVAL(params, 0);
909 deny_mode = SVAL(params, 2);
910 open_attr = SVAL(params,6);
911 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
912 if (oplock_request) {
913 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
916 #if 0
917 return_additional_info = BITSETW(params,0);
918 open_sattr = SVAL(params, 4);
919 open_time = make_unix_date3(params+8);
920 #endif
921 open_ofun = SVAL(params,12);
922 open_size = IVAL(params,14);
923 pname = &params[28];
925 if (IS_IPC(conn)) {
926 reply_doserror(req, ERRSRV, ERRaccess);
927 return;
930 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
931 total_params - 28, STR_TERMINATE,
932 &status);
933 if (!NT_STATUS_IS_OK(status)) {
934 reply_nterror(req, status);
935 return;
938 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
939 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
940 (unsigned int)open_ofun, open_size));
942 if (open_ofun == 0) {
943 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
944 return;
947 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
948 &access_mask,
949 &share_mode,
950 &create_disposition,
951 &create_options)) {
952 reply_doserror(req, ERRDOS, ERRbadaccess);
953 return;
956 /* Any data in this call is an EA list. */
957 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
958 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
959 return;
962 if (total_data != 4) {
963 if (total_data < 10) {
964 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
965 return;
968 if (IVAL(pdata,0) > total_data) {
969 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
970 IVAL(pdata,0), (unsigned int)total_data));
971 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
972 return;
975 ea_list = read_ea_list(talloc_tos(), pdata + 4,
976 total_data - 4);
977 if (!ea_list) {
978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
979 return;
981 } else if (IVAL(pdata,0) != 4) {
982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
983 return;
986 status = SMB_VFS_CREATE_FILE(
987 conn, /* conn */
988 req, /* req */
989 0, /* root_dir_fid */
990 fname, /* fname */
991 CFF_DOS_PATH, /* create_file_flags */
992 access_mask, /* access_mask */
993 share_mode, /* share_access */
994 create_disposition, /* create_disposition*/
995 create_options, /* create_options */
996 open_attr, /* file_attributes */
997 oplock_request, /* oplock_request */
998 open_size, /* allocation_size */
999 NULL, /* sd */
1000 ea_list, /* ea_list */
1001 &fsp, /* result */
1002 &smb_action, /* pinfo */
1003 &sbuf); /* psbuf */
1005 if (!NT_STATUS_IS_OK(status)) {
1006 if (open_was_deferred(req->mid)) {
1007 /* We have re-scheduled this call. */
1008 return;
1010 reply_openerror(req, status);
1011 return;
1014 size = get_file_size_stat(&sbuf);
1015 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1016 mtime = sbuf.st_mtime;
1017 inode = sbuf.st_ino;
1018 if (fattr & aDIR) {
1019 close_file(req, fsp, ERROR_CLOSE);
1020 reply_doserror(req, ERRDOS,ERRnoaccess);
1021 return;
1024 /* Realloc the size of parameters and data we will return */
1025 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1026 if(*pparams == NULL ) {
1027 reply_nterror(req, NT_STATUS_NO_MEMORY);
1028 return;
1030 params = *pparams;
1032 SSVAL(params,0,fsp->fnum);
1033 SSVAL(params,2,fattr);
1034 srv_put_dos_date2(params,4, mtime);
1035 SIVAL(params,8, (uint32)size);
1036 SSVAL(params,12,deny_mode);
1037 SSVAL(params,14,0); /* open_type - file or directory. */
1038 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1040 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1041 smb_action |= EXTENDED_OPLOCK_GRANTED;
1044 SSVAL(params,18,smb_action);
1047 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1049 SIVAL(params,20,inode);
1050 SSVAL(params,24,0); /* Padding. */
1051 if (flags & 8) {
1052 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1053 SIVAL(params, 26, ea_size);
1054 } else {
1055 SIVAL(params, 26, 0);
1058 /* Send the required number of replies */
1059 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1062 /*********************************************************
1063 Routine to check if a given string matches exactly.
1064 as a special case a mask of "." does NOT match. That
1065 is required for correct wildcard semantics
1066 Case can be significant or not.
1067 **********************************************************/
1069 static bool exact_match(connection_struct *conn,
1070 const char *str,
1071 const char *mask)
1073 if (mask[0] == '.' && mask[1] == 0)
1074 return False;
1075 if (dptr_has_wild(conn->dirptr)) {
1076 return False;
1078 if (conn->case_sensitive)
1079 return strcmp(str,mask)==0;
1080 else
1081 return StrCaseCmp(str,mask) == 0;
1084 /****************************************************************************
1085 Return the filetype for UNIX extensions.
1086 ****************************************************************************/
1088 static uint32 unix_filetype(mode_t mode)
1090 if(S_ISREG(mode))
1091 return UNIX_TYPE_FILE;
1092 else if(S_ISDIR(mode))
1093 return UNIX_TYPE_DIR;
1094 #ifdef S_ISLNK
1095 else if(S_ISLNK(mode))
1096 return UNIX_TYPE_SYMLINK;
1097 #endif
1098 #ifdef S_ISCHR
1099 else if(S_ISCHR(mode))
1100 return UNIX_TYPE_CHARDEV;
1101 #endif
1102 #ifdef S_ISBLK
1103 else if(S_ISBLK(mode))
1104 return UNIX_TYPE_BLKDEV;
1105 #endif
1106 #ifdef S_ISFIFO
1107 else if(S_ISFIFO(mode))
1108 return UNIX_TYPE_FIFO;
1109 #endif
1110 #ifdef S_ISSOCK
1111 else if(S_ISSOCK(mode))
1112 return UNIX_TYPE_SOCKET;
1113 #endif
1115 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1116 return UNIX_TYPE_UNKNOWN;
1119 /****************************************************************************
1120 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1121 ****************************************************************************/
1123 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1125 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1126 SMB_STRUCT_STAT *psbuf,
1127 uint32 perms,
1128 enum perm_type ptype,
1129 mode_t *ret_perms)
1131 mode_t ret = 0;
1133 if (perms == SMB_MODE_NO_CHANGE) {
1134 if (!VALID_STAT(*psbuf)) {
1135 return NT_STATUS_INVALID_PARAMETER;
1136 } else {
1137 *ret_perms = psbuf->st_mode;
1138 return NT_STATUS_OK;
1142 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1143 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1144 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1145 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1146 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1147 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1148 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1149 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1150 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1151 #ifdef S_ISVTX
1152 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1153 #endif
1154 #ifdef S_ISGID
1155 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1156 #endif
1157 #ifdef S_ISUID
1158 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1159 #endif
1161 switch (ptype) {
1162 case PERM_NEW_FILE:
1163 /* Apply mode mask */
1164 ret &= lp_create_mask(SNUM(conn));
1165 /* Add in force bits */
1166 ret |= lp_force_create_mode(SNUM(conn));
1167 break;
1168 case PERM_NEW_DIR:
1169 ret &= lp_dir_mask(SNUM(conn));
1170 /* Add in force bits */
1171 ret |= lp_force_dir_mode(SNUM(conn));
1172 break;
1173 case PERM_EXISTING_FILE:
1174 /* Apply mode mask */
1175 ret &= lp_security_mask(SNUM(conn));
1176 /* Add in force bits */
1177 ret |= lp_force_security_mode(SNUM(conn));
1178 break;
1179 case PERM_EXISTING_DIR:
1180 /* Apply mode mask */
1181 ret &= lp_dir_security_mask(SNUM(conn));
1182 /* Add in force bits */
1183 ret |= lp_force_dir_security_mode(SNUM(conn));
1184 break;
1187 *ret_perms = ret;
1188 return NT_STATUS_OK;
1191 /****************************************************************************
1192 Needed to show the msdfs symlinks as directories. Modifies psbuf
1193 to be a directory if it's a msdfs link.
1194 ****************************************************************************/
1196 static bool check_msdfs_link(connection_struct *conn,
1197 const char *pathname,
1198 SMB_STRUCT_STAT *psbuf)
1200 int saved_errno = errno;
1201 if(lp_host_msdfs() &&
1202 lp_msdfs_root(SNUM(conn)) &&
1203 is_msdfs_link(conn, pathname, psbuf)) {
1205 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1206 "as a directory\n",
1207 pathname));
1208 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1209 errno = saved_errno;
1210 return true;
1212 errno = saved_errno;
1213 return false;
1217 /****************************************************************************
1218 Get a level dependent lanman2 dir entry.
1219 ****************************************************************************/
1221 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1222 connection_struct *conn,
1223 uint16 flags2,
1224 const char *path_mask,
1225 uint32 dirtype,
1226 int info_level,
1227 int requires_resume_key,
1228 bool dont_descend,
1229 bool ask_sharemode,
1230 char **ppdata,
1231 char *base_data,
1232 char *end_data,
1233 int space_remaining,
1234 bool *out_of_space,
1235 bool *got_exact_match,
1236 int *last_entry_off,
1237 struct ea_list *name_list)
1239 char *dname;
1240 bool found = False;
1241 SMB_STRUCT_STAT sbuf;
1242 const char *mask = NULL;
1243 char *pathreal = NULL;
1244 char *fname = NULL;
1245 char *p, *q, *pdata = *ppdata;
1246 uint32 reskey=0;
1247 long prev_dirpos=0;
1248 uint32 mode=0;
1249 SMB_OFF_T file_size = 0;
1250 uint64_t allocation_size = 0;
1251 uint32 len;
1252 struct timespec mdate_ts, adate_ts, create_date_ts;
1253 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1254 char *nameptr;
1255 char *last_entry_ptr;
1256 bool was_8_3;
1257 uint32 nt_extmode; /* Used for NT connections instead of mode */
1258 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1259 bool check_mangled_names = lp_manglednames(conn->params);
1260 char mangled_name[13]; /* mangled 8.3 name. */
1262 *out_of_space = False;
1263 *got_exact_match = False;
1265 ZERO_STRUCT(mdate_ts);
1266 ZERO_STRUCT(adate_ts);
1267 ZERO_STRUCT(create_date_ts);
1269 if (!conn->dirptr) {
1270 return(False);
1273 p = strrchr_m(path_mask,'/');
1274 if(p != NULL) {
1275 if(p[1] == '\0') {
1276 mask = talloc_strdup(ctx,"*.*");
1277 } else {
1278 mask = p+1;
1280 } else {
1281 mask = path_mask;
1284 while (!found) {
1285 bool got_match;
1286 bool ms_dfs_link = False;
1288 /* Needed if we run out of space */
1289 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1290 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1293 * Due to bugs in NT client redirectors we are not using
1294 * resume keys any more - set them to zero.
1295 * Check out the related comments in findfirst/findnext.
1296 * JRA.
1299 reskey = 0;
1301 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1302 (long)conn->dirptr,curr_dirpos));
1304 if (!dname) {
1305 return(False);
1309 * fname may get mangled, dname is never mangled.
1310 * Whenever we're accessing the filesystem we use
1311 * pathreal which is composed from dname.
1314 pathreal = NULL;
1315 fname = dname;
1317 /* Mangle fname if it's an illegal name. */
1318 if (mangle_must_mangle(dname,conn->params)) {
1319 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1320 TALLOC_FREE(fname);
1321 continue; /* Error - couldn't mangle. */
1323 fname = talloc_strdup(ctx, mangled_name);
1324 if (!fname) {
1325 return False;
1329 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1330 got_match = mask_match(fname, mask, conn->case_sensitive);
1333 if(!got_match && check_mangled_names &&
1334 !mangle_is_8_3(fname, False, conn->params)) {
1336 * It turns out that NT matches wildcards against
1337 * both long *and* short names. This may explain some
1338 * of the wildcard wierdness from old DOS clients
1339 * that some people have been seeing.... JRA.
1341 /* Force the mangling into 8.3. */
1342 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1343 TALLOC_FREE(fname);
1344 continue; /* Error - couldn't mangle. */
1347 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1348 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1352 if (got_match) {
1353 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1355 if (dont_descend && !isdots) {
1356 TALLOC_FREE(fname);
1357 continue;
1360 if (needslash) {
1361 pathreal = NULL;
1362 pathreal = talloc_asprintf(ctx,
1363 "%s/%s",
1364 conn->dirpath,
1365 dname);
1366 } else {
1367 pathreal = talloc_asprintf(ctx,
1368 "%s%s",
1369 conn->dirpath,
1370 dname);
1373 if (!pathreal) {
1374 TALLOC_FREE(fname);
1375 return False;
1378 if (INFO_LEVEL_IS_UNIX(info_level)) {
1379 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1380 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1381 pathreal,strerror(errno)));
1382 TALLOC_FREE(pathreal);
1383 TALLOC_FREE(fname);
1384 continue;
1386 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1387 /* Needed to show the msdfs symlinks as
1388 * directories */
1390 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1391 if (!ms_dfs_link) {
1392 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1393 pathreal,strerror(errno)));
1394 TALLOC_FREE(pathreal);
1395 TALLOC_FREE(fname);
1396 continue;
1400 if (ms_dfs_link) {
1401 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1402 } else {
1403 mode = dos_mode(conn,pathreal,&sbuf);
1406 if (!dir_check_ftype(conn,mode,dirtype)) {
1407 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1408 TALLOC_FREE(pathreal);
1409 TALLOC_FREE(fname);
1410 continue;
1413 if (!(mode & aDIR)) {
1414 file_size = get_file_size_stat(&sbuf);
1416 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1418 mdate_ts = get_mtimespec(&sbuf);
1419 adate_ts = get_atimespec(&sbuf);
1420 create_date_ts = get_create_timespec(&sbuf,
1421 lp_fake_dir_create_times(SNUM(conn)));
1423 if (ask_sharemode) {
1424 struct timespec write_time_ts;
1425 struct file_id fileid;
1427 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1428 get_file_infos(fileid, NULL, &write_time_ts);
1429 if (!null_timespec(write_time_ts)) {
1430 mdate_ts = write_time_ts;
1434 if (lp_dos_filetime_resolution(SNUM(conn))) {
1435 dos_filetime_timespec(&create_date_ts);
1436 dos_filetime_timespec(&mdate_ts);
1437 dos_filetime_timespec(&adate_ts);
1440 create_date = convert_timespec_to_time_t(create_date_ts);
1441 mdate = convert_timespec_to_time_t(mdate_ts);
1442 adate = convert_timespec_to_time_t(adate_ts);
1444 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1445 pathreal,fname));
1447 found = True;
1449 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1452 if (!found)
1453 TALLOC_FREE(fname);
1456 p = pdata;
1457 last_entry_ptr = p;
1459 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1461 switch (info_level) {
1462 case SMB_FIND_INFO_STANDARD:
1463 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1464 if(requires_resume_key) {
1465 SIVAL(p,0,reskey);
1466 p += 4;
1468 srv_put_dos_date2(p,0,create_date);
1469 srv_put_dos_date2(p,4,adate);
1470 srv_put_dos_date2(p,8,mdate);
1471 SIVAL(p,12,(uint32)file_size);
1472 SIVAL(p,16,(uint32)allocation_size);
1473 SSVAL(p,20,mode);
1474 p += 23;
1475 nameptr = p;
1476 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1477 p += ucs2_align(base_data, p, 0);
1479 len = srvstr_push(base_data, flags2, p,
1480 fname, PTR_DIFF(end_data, p),
1481 STR_TERMINATE);
1482 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1483 if (len > 2) {
1484 SCVAL(nameptr, -1, len - 2);
1485 } else {
1486 SCVAL(nameptr, -1, 0);
1488 } else {
1489 if (len > 1) {
1490 SCVAL(nameptr, -1, len - 1);
1491 } else {
1492 SCVAL(nameptr, -1, 0);
1495 p += len;
1496 break;
1498 case SMB_FIND_EA_SIZE:
1499 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1500 if(requires_resume_key) {
1501 SIVAL(p,0,reskey);
1502 p += 4;
1504 srv_put_dos_date2(p,0,create_date);
1505 srv_put_dos_date2(p,4,adate);
1506 srv_put_dos_date2(p,8,mdate);
1507 SIVAL(p,12,(uint32)file_size);
1508 SIVAL(p,16,(uint32)allocation_size);
1509 SSVAL(p,20,mode);
1511 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1512 SIVAL(p,22,ea_size); /* Extended attributes */
1514 p += 27;
1515 nameptr = p - 1;
1516 len = srvstr_push(base_data, flags2,
1517 p, fname, PTR_DIFF(end_data, p),
1518 STR_TERMINATE | STR_NOALIGN);
1519 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1520 if (len > 2) {
1521 len -= 2;
1522 } else {
1523 len = 0;
1525 } else {
1526 if (len > 1) {
1527 len -= 1;
1528 } else {
1529 len = 0;
1532 SCVAL(nameptr,0,len);
1533 p += len;
1534 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1535 break;
1537 case SMB_FIND_EA_LIST:
1539 struct ea_list *file_list = NULL;
1540 size_t ea_len = 0;
1542 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1543 if (!name_list) {
1544 return False;
1546 if(requires_resume_key) {
1547 SIVAL(p,0,reskey);
1548 p += 4;
1550 srv_put_dos_date2(p,0,create_date);
1551 srv_put_dos_date2(p,4,adate);
1552 srv_put_dos_date2(p,8,mdate);
1553 SIVAL(p,12,(uint32)file_size);
1554 SIVAL(p,16,(uint32)allocation_size);
1555 SSVAL(p,20,mode);
1556 p += 22; /* p now points to the EA area. */
1558 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1559 name_list = ea_list_union(name_list, file_list, &ea_len);
1561 /* We need to determine if this entry will fit in the space available. */
1562 /* Max string size is 255 bytes. */
1563 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1564 /* Move the dirptr back to prev_dirpos */
1565 dptr_SeekDir(conn->dirptr, prev_dirpos);
1566 *out_of_space = True;
1567 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1568 return False; /* Not finished - just out of space */
1571 /* Push the ea_data followed by the name. */
1572 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1573 nameptr = p;
1574 len = srvstr_push(base_data, flags2,
1575 p + 1, fname, PTR_DIFF(end_data, p+1),
1576 STR_TERMINATE | STR_NOALIGN);
1577 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1578 if (len > 2) {
1579 len -= 2;
1580 } else {
1581 len = 0;
1583 } else {
1584 if (len > 1) {
1585 len -= 1;
1586 } else {
1587 len = 0;
1590 SCVAL(nameptr,0,len);
1591 p += len + 1;
1592 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1593 break;
1596 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1597 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1598 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1599 p += 4;
1600 SIVAL(p,0,reskey); p += 4;
1601 put_long_date_timespec(p,create_date_ts); p += 8;
1602 put_long_date_timespec(p,adate_ts); p += 8;
1603 put_long_date_timespec(p,mdate_ts); p += 8;
1604 put_long_date_timespec(p,mdate_ts); p += 8;
1605 SOFF_T(p,0,file_size); p += 8;
1606 SOFF_T(p,0,allocation_size); p += 8;
1607 SIVAL(p,0,nt_extmode); p += 4;
1608 q = p; p += 4; /* q is placeholder for name length. */
1610 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1611 SIVAL(p,0,ea_size); /* Extended attributes */
1612 p += 4;
1614 /* Clear the short name buffer. This is
1615 * IMPORTANT as not doing so will trigger
1616 * a Win2k client bug. JRA.
1618 if (!was_8_3 && check_mangled_names) {
1619 if (!name_to_8_3(fname,mangled_name,True,
1620 conn->params)) {
1621 /* Error - mangle failed ! */
1622 memset(mangled_name,'\0',12);
1624 mangled_name[12] = 0;
1625 len = srvstr_push(base_data, flags2,
1626 p+2, mangled_name, 24,
1627 STR_UPPER|STR_UNICODE);
1628 if (len < 24) {
1629 memset(p + 2 + len,'\0',24 - len);
1631 SSVAL(p, 0, len);
1632 } else {
1633 memset(p,'\0',26);
1635 p += 2 + 24;
1636 len = srvstr_push(base_data, flags2, p,
1637 fname, PTR_DIFF(end_data, p),
1638 STR_TERMINATE_ASCII);
1639 SIVAL(q,0,len);
1640 p += len;
1641 SIVAL(p,0,0); /* Ensure any padding is null. */
1642 len = PTR_DIFF(p, pdata);
1643 len = (len + 3) & ~3;
1644 SIVAL(pdata,0,len);
1645 p = pdata + len;
1646 break;
1648 case SMB_FIND_FILE_DIRECTORY_INFO:
1649 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1650 p += 4;
1651 SIVAL(p,0,reskey); p += 4;
1652 put_long_date_timespec(p,create_date_ts); p += 8;
1653 put_long_date_timespec(p,adate_ts); p += 8;
1654 put_long_date_timespec(p,mdate_ts); p += 8;
1655 put_long_date_timespec(p,mdate_ts); p += 8;
1656 SOFF_T(p,0,file_size); p += 8;
1657 SOFF_T(p,0,allocation_size); p += 8;
1658 SIVAL(p,0,nt_extmode); p += 4;
1659 len = srvstr_push(base_data, flags2,
1660 p + 4, fname, PTR_DIFF(end_data, p+4),
1661 STR_TERMINATE_ASCII);
1662 SIVAL(p,0,len);
1663 p += 4 + len;
1664 SIVAL(p,0,0); /* Ensure any padding is null. */
1665 len = PTR_DIFF(p, pdata);
1666 len = (len + 3) & ~3;
1667 SIVAL(pdata,0,len);
1668 p = pdata + len;
1669 break;
1671 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1672 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1673 p += 4;
1674 SIVAL(p,0,reskey); p += 4;
1675 put_long_date_timespec(p,create_date_ts); p += 8;
1676 put_long_date_timespec(p,adate_ts); p += 8;
1677 put_long_date_timespec(p,mdate_ts); p += 8;
1678 put_long_date_timespec(p,mdate_ts); p += 8;
1679 SOFF_T(p,0,file_size); p += 8;
1680 SOFF_T(p,0,allocation_size); p += 8;
1681 SIVAL(p,0,nt_extmode); p += 4;
1682 q = p; p += 4; /* q is placeholder for name length. */
1684 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1685 SIVAL(p,0,ea_size); /* Extended attributes */
1686 p +=4;
1688 len = srvstr_push(base_data, flags2, p,
1689 fname, PTR_DIFF(end_data, p),
1690 STR_TERMINATE_ASCII);
1691 SIVAL(q, 0, len);
1692 p += len;
1694 SIVAL(p,0,0); /* Ensure any padding is null. */
1695 len = PTR_DIFF(p, pdata);
1696 len = (len + 3) & ~3;
1697 SIVAL(pdata,0,len);
1698 p = pdata + len;
1699 break;
1701 case SMB_FIND_FILE_NAMES_INFO:
1702 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1703 p += 4;
1704 SIVAL(p,0,reskey); p += 4;
1705 p += 4;
1706 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1707 acl on a dir (tridge) */
1708 len = srvstr_push(base_data, flags2, p,
1709 fname, PTR_DIFF(end_data, p),
1710 STR_TERMINATE_ASCII);
1711 SIVAL(p, -4, len);
1712 p += len;
1713 SIVAL(p,0,0); /* Ensure any padding is null. */
1714 len = PTR_DIFF(p, pdata);
1715 len = (len + 3) & ~3;
1716 SIVAL(pdata,0,len);
1717 p = pdata + len;
1718 break;
1720 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1721 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1722 p += 4;
1723 SIVAL(p,0,reskey); p += 4;
1724 put_long_date_timespec(p,create_date_ts); p += 8;
1725 put_long_date_timespec(p,adate_ts); p += 8;
1726 put_long_date_timespec(p,mdate_ts); p += 8;
1727 put_long_date_timespec(p,mdate_ts); p += 8;
1728 SOFF_T(p,0,file_size); p += 8;
1729 SOFF_T(p,0,allocation_size); p += 8;
1730 SIVAL(p,0,nt_extmode); p += 4;
1731 q = p; p += 4; /* q is placeholder for name length. */
1733 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1734 SIVAL(p,0,ea_size); /* Extended attributes */
1735 p +=4;
1737 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1738 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1739 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1740 len = srvstr_push(base_data, flags2, p,
1741 fname, PTR_DIFF(end_data, p),
1742 STR_TERMINATE_ASCII);
1743 SIVAL(q, 0, len);
1744 p += len;
1745 SIVAL(p,0,0); /* Ensure any padding is null. */
1746 len = PTR_DIFF(p, pdata);
1747 len = (len + 3) & ~3;
1748 SIVAL(pdata,0,len);
1749 p = pdata + len;
1750 break;
1752 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1753 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1754 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1755 p += 4;
1756 SIVAL(p,0,reskey); p += 4;
1757 put_long_date_timespec(p,create_date_ts); p += 8;
1758 put_long_date_timespec(p,adate_ts); p += 8;
1759 put_long_date_timespec(p,mdate_ts); p += 8;
1760 put_long_date_timespec(p,mdate_ts); p += 8;
1761 SOFF_T(p,0,file_size); p += 8;
1762 SOFF_T(p,0,allocation_size); p += 8;
1763 SIVAL(p,0,nt_extmode); p += 4;
1764 q = p; p += 4; /* q is placeholder for name length */
1766 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1767 SIVAL(p,0,ea_size); /* Extended attributes */
1768 p +=4;
1770 /* Clear the short name buffer. This is
1771 * IMPORTANT as not doing so will trigger
1772 * a Win2k client bug. JRA.
1774 if (!was_8_3 && check_mangled_names) {
1775 if (!name_to_8_3(fname,mangled_name,True,
1776 conn->params)) {
1777 /* Error - mangle failed ! */
1778 memset(mangled_name,'\0',12);
1780 mangled_name[12] = 0;
1781 len = srvstr_push(base_data, flags2,
1782 p+2, mangled_name, 24,
1783 STR_UPPER|STR_UNICODE);
1784 SSVAL(p, 0, len);
1785 if (len < 24) {
1786 memset(p + 2 + len,'\0',24 - len);
1788 SSVAL(p, 0, len);
1789 } else {
1790 memset(p,'\0',26);
1792 p += 26;
1793 SSVAL(p,0,0); p += 2; /* Reserved ? */
1794 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1795 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1796 len = srvstr_push(base_data, flags2, p,
1797 fname, PTR_DIFF(end_data, p),
1798 STR_TERMINATE_ASCII);
1799 SIVAL(q,0,len);
1800 p += len;
1801 SIVAL(p,0,0); /* Ensure any padding is null. */
1802 len = PTR_DIFF(p, pdata);
1803 len = (len + 3) & ~3;
1804 SIVAL(pdata,0,len);
1805 p = pdata + len;
1806 break;
1808 /* CIFS UNIX Extension. */
1810 case SMB_FIND_FILE_UNIX:
1811 case SMB_FIND_FILE_UNIX_INFO2:
1812 p+= 4;
1813 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1815 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1817 if (info_level == SMB_FIND_FILE_UNIX) {
1818 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1819 p = store_file_unix_basic(conn, p,
1820 NULL, &sbuf);
1821 len = srvstr_push(base_data, flags2, p,
1822 fname, PTR_DIFF(end_data, p),
1823 STR_TERMINATE);
1824 } else {
1825 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1826 p = store_file_unix_basic_info2(conn, p,
1827 NULL, &sbuf);
1828 nameptr = p;
1829 p += 4;
1830 len = srvstr_push(base_data, flags2, p, fname,
1831 PTR_DIFF(end_data, p), 0);
1832 SIVAL(nameptr, 0, len);
1835 p += len;
1836 SIVAL(p,0,0); /* Ensure any padding is null. */
1838 len = PTR_DIFF(p, pdata);
1839 len = (len + 3) & ~3;
1840 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1841 p = pdata + len;
1842 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1844 break;
1846 default:
1847 TALLOC_FREE(fname);
1848 return(False);
1851 TALLOC_FREE(fname);
1852 if (PTR_DIFF(p,pdata) > space_remaining) {
1853 /* Move the dirptr back to prev_dirpos */
1854 dptr_SeekDir(conn->dirptr, prev_dirpos);
1855 *out_of_space = True;
1856 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1857 return False; /* Not finished - just out of space */
1860 /* Setup the last entry pointer, as an offset from base_data */
1861 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1862 /* Advance the data pointer to the next slot */
1863 *ppdata = p;
1865 return(found);
1868 /****************************************************************************
1869 Reply to a TRANS2_FINDFIRST.
1870 ****************************************************************************/
1872 static void call_trans2findfirst(connection_struct *conn,
1873 struct smb_request *req,
1874 char **pparams, int total_params,
1875 char **ppdata, int total_data,
1876 unsigned int max_data_bytes)
1878 /* We must be careful here that we don't return more than the
1879 allowed number of data bytes. If this means returning fewer than
1880 maxentries then so be it. We assume that the redirector has
1881 enough room for the fixed number of parameter bytes it has
1882 requested. */
1883 char *params = *pparams;
1884 char *pdata = *ppdata;
1885 char *data_end;
1886 uint32 dirtype;
1887 int maxentries;
1888 uint16 findfirst_flags;
1889 bool close_after_first;
1890 bool close_if_end;
1891 bool requires_resume_key;
1892 int info_level;
1893 char *directory = NULL;
1894 char *mask = NULL;
1895 char *p;
1896 int last_entry_off=0;
1897 int dptr_num = -1;
1898 int numentries = 0;
1899 int i;
1900 bool finished = False;
1901 bool dont_descend = False;
1902 bool out_of_space = False;
1903 int space_remaining;
1904 bool mask_contains_wcard = False;
1905 SMB_STRUCT_STAT sbuf;
1906 struct ea_list *ea_list = NULL;
1907 NTSTATUS ntstatus = NT_STATUS_OK;
1908 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1909 TALLOC_CTX *ctx = talloc_tos();
1911 if (total_params < 13) {
1912 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1913 return;
1916 dirtype = SVAL(params,0);
1917 maxentries = SVAL(params,2);
1918 findfirst_flags = SVAL(params,4);
1919 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1920 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1921 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1922 info_level = SVAL(params,6);
1924 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1925 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1926 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1927 info_level, max_data_bytes));
1929 if (!maxentries) {
1930 /* W2K3 seems to treat zero as 1. */
1931 maxentries = 1;
1934 switch (info_level) {
1935 case SMB_FIND_INFO_STANDARD:
1936 case SMB_FIND_EA_SIZE:
1937 case SMB_FIND_EA_LIST:
1938 case SMB_FIND_FILE_DIRECTORY_INFO:
1939 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1940 case SMB_FIND_FILE_NAMES_INFO:
1941 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1942 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1943 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1944 break;
1945 case SMB_FIND_FILE_UNIX:
1946 case SMB_FIND_FILE_UNIX_INFO2:
1947 /* Always use filesystem for UNIX mtime query. */
1948 ask_sharemode = false;
1949 if (!lp_unix_extensions()) {
1950 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1951 return;
1953 break;
1954 default:
1955 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1956 return;
1959 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1960 params+12, total_params - 12,
1961 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1962 if (!NT_STATUS_IS_OK(ntstatus)) {
1963 reply_nterror(req, ntstatus);
1964 return;
1967 ntstatus = resolve_dfspath_wcard(ctx, conn,
1968 req->flags2 & FLAGS2_DFS_PATHNAMES,
1969 directory,
1970 &directory,
1971 &mask_contains_wcard);
1972 if (!NT_STATUS_IS_OK(ntstatus)) {
1973 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1974 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1975 ERRSRV, ERRbadpath);
1976 return;
1978 reply_nterror(req, ntstatus);
1979 return;
1982 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1983 if (!NT_STATUS_IS_OK(ntstatus)) {
1984 reply_nterror(req, ntstatus);
1985 return;
1988 ntstatus = check_name(conn, directory);
1989 if (!NT_STATUS_IS_OK(ntstatus)) {
1990 reply_nterror(req, ntstatus);
1991 return;
1994 p = strrchr_m(directory,'/');
1995 if(p == NULL) {
1996 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1997 if((directory[0] == '.') && (directory[1] == '\0')) {
1998 mask = talloc_strdup(ctx,"*");
1999 if (!mask) {
2000 reply_nterror(req, NT_STATUS_NO_MEMORY);
2001 return;
2003 mask_contains_wcard = True;
2005 directory = talloc_strdup(talloc_tos(), "./");
2006 if (!directory) {
2007 reply_nterror(req, NT_STATUS_NO_MEMORY);
2008 return;
2010 } else {
2011 *p = 0;
2014 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2016 if (info_level == SMB_FIND_EA_LIST) {
2017 uint32 ea_size;
2019 if (total_data < 4) {
2020 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2021 return;
2024 ea_size = IVAL(pdata,0);
2025 if (ea_size != total_data) {
2026 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2027 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2029 return;
2032 if (!lp_ea_support(SNUM(conn))) {
2033 reply_doserror(req, ERRDOS, ERReasnotsupported);
2034 return;
2037 /* Pull out the list of names. */
2038 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2039 if (!ea_list) {
2040 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2041 return;
2045 *ppdata = (char *)SMB_REALLOC(
2046 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2047 if(*ppdata == NULL ) {
2048 reply_nterror(req, NT_STATUS_NO_MEMORY);
2049 return;
2051 pdata = *ppdata;
2052 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2054 /* Realloc the params space */
2055 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2056 if (*pparams == NULL) {
2057 reply_nterror(req, NT_STATUS_NO_MEMORY);
2058 return;
2060 params = *pparams;
2062 /* Save the wildcard match and attribs we are using on this directory -
2063 needed as lanman2 assumes these are being saved between calls */
2065 ntstatus = dptr_create(conn,
2066 directory,
2067 False,
2068 True,
2069 req->smbpid,
2070 mask,
2071 mask_contains_wcard,
2072 dirtype,
2073 &conn->dirptr);
2075 if (!NT_STATUS_IS_OK(ntstatus)) {
2076 reply_nterror(req, ntstatus);
2077 return;
2080 dptr_num = dptr_dnum(conn->dirptr);
2081 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2083 /* Initialize per TRANS2_FIND_FIRST operation data */
2084 dptr_init_search_op(conn->dirptr);
2086 /* We don't need to check for VOL here as this is returned by
2087 a different TRANS2 call. */
2089 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2090 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2091 dont_descend = True;
2093 p = pdata;
2094 space_remaining = max_data_bytes;
2095 out_of_space = False;
2097 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2098 bool got_exact_match = False;
2100 /* this is a heuristic to avoid seeking the dirptr except when
2101 absolutely necessary. It allows for a filename of about 40 chars */
2102 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2103 out_of_space = True;
2104 finished = False;
2105 } else {
2106 finished = !get_lanman2_dir_entry(ctx,
2107 conn,
2108 req->flags2,
2109 mask,dirtype,info_level,
2110 requires_resume_key,dont_descend,
2111 ask_sharemode,
2112 &p,pdata,data_end,
2113 space_remaining, &out_of_space,
2114 &got_exact_match,
2115 &last_entry_off, ea_list);
2118 if (finished && out_of_space)
2119 finished = False;
2121 if (!finished && !out_of_space)
2122 numentries++;
2125 * As an optimisation if we know we aren't looking
2126 * for a wildcard name (ie. the name matches the wildcard exactly)
2127 * then we can finish on any (first) match.
2128 * This speeds up large directory searches. JRA.
2131 if(got_exact_match)
2132 finished = True;
2134 /* Ensure space_remaining never goes -ve. */
2135 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2136 space_remaining = 0;
2137 out_of_space = true;
2138 } else {
2139 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2143 /* Check if we can close the dirptr */
2144 if(close_after_first || (finished && close_if_end)) {
2145 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2146 dptr_close(&dptr_num);
2150 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2151 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2152 * the protocol level is less than NT1. Tested with smbclient. JRA.
2153 * This should fix the OS/2 client bug #2335.
2156 if(numentries == 0) {
2157 dptr_close(&dptr_num);
2158 if (Protocol < PROTOCOL_NT1) {
2159 reply_doserror(req, ERRDOS, ERRnofiles);
2160 return;
2161 } else {
2162 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2163 ERRDOS, ERRbadfile);
2164 return;
2168 /* At this point pdata points to numentries directory entries. */
2170 /* Set up the return parameter block */
2171 SSVAL(params,0,dptr_num);
2172 SSVAL(params,2,numentries);
2173 SSVAL(params,4,finished);
2174 SSVAL(params,6,0); /* Never an EA error */
2175 SSVAL(params,8,last_entry_off);
2177 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2178 max_data_bytes);
2180 if ((! *directory) && dptr_path(dptr_num)) {
2181 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2182 if (!directory) {
2183 reply_nterror(req, NT_STATUS_NO_MEMORY);
2187 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2188 smb_fn_name(req->cmd),
2189 mask, directory, dirtype, numentries ) );
2192 * Force a name mangle here to ensure that the
2193 * mask as an 8.3 name is top of the mangled cache.
2194 * The reasons for this are subtle. Don't remove
2195 * this code unless you know what you are doing
2196 * (see PR#13758). JRA.
2199 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2200 char mangled_name[13];
2201 name_to_8_3(mask, mangled_name, True, conn->params);
2204 return;
2207 /****************************************************************************
2208 Reply to a TRANS2_FINDNEXT.
2209 ****************************************************************************/
2211 static void call_trans2findnext(connection_struct *conn,
2212 struct smb_request *req,
2213 char **pparams, int total_params,
2214 char **ppdata, int total_data,
2215 unsigned int max_data_bytes)
2217 /* We must be careful here that we don't return more than the
2218 allowed number of data bytes. If this means returning fewer than
2219 maxentries then so be it. We assume that the redirector has
2220 enough room for the fixed number of parameter bytes it has
2221 requested. */
2222 char *params = *pparams;
2223 char *pdata = *ppdata;
2224 char *data_end;
2225 int dptr_num;
2226 int maxentries;
2227 uint16 info_level;
2228 uint32 resume_key;
2229 uint16 findnext_flags;
2230 bool close_after_request;
2231 bool close_if_end;
2232 bool requires_resume_key;
2233 bool continue_bit;
2234 bool mask_contains_wcard = False;
2235 char *resume_name = NULL;
2236 const char *mask = NULL;
2237 const char *directory = NULL;
2238 char *p = NULL;
2239 uint16 dirtype;
2240 int numentries = 0;
2241 int i, last_entry_off=0;
2242 bool finished = False;
2243 bool dont_descend = False;
2244 bool out_of_space = False;
2245 int space_remaining;
2246 struct ea_list *ea_list = NULL;
2247 NTSTATUS ntstatus = NT_STATUS_OK;
2248 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2249 TALLOC_CTX *ctx = talloc_tos();
2251 if (total_params < 13) {
2252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2253 return;
2256 dptr_num = SVAL(params,0);
2257 maxentries = SVAL(params,2);
2258 info_level = SVAL(params,4);
2259 resume_key = IVAL(params,6);
2260 findnext_flags = SVAL(params,10);
2261 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2262 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2263 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2264 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2266 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2267 params+12,
2268 total_params - 12, STR_TERMINATE, &ntstatus,
2269 &mask_contains_wcard);
2270 if (!NT_STATUS_IS_OK(ntstatus)) {
2271 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2272 complain (it thinks we're asking for the directory above the shared
2273 path or an invalid name). Catch this as the resume name is only compared, never used in
2274 a file access. JRA. */
2275 srvstr_pull_talloc(ctx, params, req->flags2,
2276 &resume_name, params+12,
2277 total_params - 12,
2278 STR_TERMINATE);
2280 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2281 reply_nterror(req, ntstatus);
2282 return;
2286 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2287 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2288 resume_key = %d resume name = %s continue=%d level = %d\n",
2289 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2290 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2292 if (!maxentries) {
2293 /* W2K3 seems to treat zero as 1. */
2294 maxentries = 1;
2297 switch (info_level) {
2298 case SMB_FIND_INFO_STANDARD:
2299 case SMB_FIND_EA_SIZE:
2300 case SMB_FIND_EA_LIST:
2301 case SMB_FIND_FILE_DIRECTORY_INFO:
2302 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2303 case SMB_FIND_FILE_NAMES_INFO:
2304 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2305 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2306 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2307 break;
2308 case SMB_FIND_FILE_UNIX:
2309 case SMB_FIND_FILE_UNIX_INFO2:
2310 /* Always use filesystem for UNIX mtime query. */
2311 ask_sharemode = false;
2312 if (!lp_unix_extensions()) {
2313 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2314 return;
2316 break;
2317 default:
2318 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2319 return;
2322 if (info_level == SMB_FIND_EA_LIST) {
2323 uint32 ea_size;
2325 if (total_data < 4) {
2326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2327 return;
2330 ea_size = IVAL(pdata,0);
2331 if (ea_size != total_data) {
2332 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2333 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2335 return;
2338 if (!lp_ea_support(SNUM(conn))) {
2339 reply_doserror(req, ERRDOS, ERReasnotsupported);
2340 return;
2343 /* Pull out the list of names. */
2344 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2345 if (!ea_list) {
2346 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2347 return;
2351 *ppdata = (char *)SMB_REALLOC(
2352 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2353 if(*ppdata == NULL) {
2354 reply_nterror(req, NT_STATUS_NO_MEMORY);
2355 return;
2358 pdata = *ppdata;
2359 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2361 /* Realloc the params space */
2362 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2363 if(*pparams == NULL ) {
2364 reply_nterror(req, NT_STATUS_NO_MEMORY);
2365 return;
2368 params = *pparams;
2370 /* Check that the dptr is valid */
2371 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2372 reply_doserror(req, ERRDOS, ERRnofiles);
2373 return;
2376 string_set(&conn->dirpath,dptr_path(dptr_num));
2378 /* Get the wildcard mask from the dptr */
2379 if((p = dptr_wcard(dptr_num))== NULL) {
2380 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2381 reply_doserror(req, ERRDOS, ERRnofiles);
2382 return;
2385 mask = p;
2386 directory = conn->dirpath;
2388 /* Get the attr mask from the dptr */
2389 dirtype = dptr_attr(dptr_num);
2391 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2392 dptr_num, mask, dirtype,
2393 (long)conn->dirptr,
2394 dptr_TellDir(conn->dirptr)));
2396 /* Initialize per TRANS2_FIND_NEXT operation data */
2397 dptr_init_search_op(conn->dirptr);
2399 /* We don't need to check for VOL here as this is returned by
2400 a different TRANS2 call. */
2402 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2403 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2404 dont_descend = True;
2406 p = pdata;
2407 space_remaining = max_data_bytes;
2408 out_of_space = False;
2411 * Seek to the correct position. We no longer use the resume key but
2412 * depend on the last file name instead.
2415 if(*resume_name && !continue_bit) {
2416 SMB_STRUCT_STAT st;
2418 long current_pos = 0;
2420 * Remember, name_to_8_3 is called by
2421 * get_lanman2_dir_entry(), so the resume name
2422 * could be mangled. Ensure we check the unmangled name.
2425 if (mangle_is_mangled(resume_name, conn->params)) {
2426 char *new_resume_name = NULL;
2427 mangle_lookup_name_from_8_3(ctx,
2428 resume_name,
2429 &new_resume_name,
2430 conn->params);
2431 if (new_resume_name) {
2432 resume_name = new_resume_name;
2437 * Fix for NT redirector problem triggered by resume key indexes
2438 * changing between directory scans. We now return a resume key of 0
2439 * and instead look for the filename to continue from (also given
2440 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2441 * findfirst/findnext (as is usual) then the directory pointer
2442 * should already be at the correct place.
2445 finished = !dptr_SearchDir(conn->dirptr, resume_name, &current_pos, &st);
2446 } /* end if resume_name && !continue_bit */
2448 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2449 bool got_exact_match = False;
2451 /* this is a heuristic to avoid seeking the dirptr except when
2452 absolutely necessary. It allows for a filename of about 40 chars */
2453 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2454 out_of_space = True;
2455 finished = False;
2456 } else {
2457 finished = !get_lanman2_dir_entry(ctx,
2458 conn,
2459 req->flags2,
2460 mask,dirtype,info_level,
2461 requires_resume_key,dont_descend,
2462 ask_sharemode,
2463 &p,pdata,data_end,
2464 space_remaining, &out_of_space,
2465 &got_exact_match,
2466 &last_entry_off, ea_list);
2469 if (finished && out_of_space)
2470 finished = False;
2472 if (!finished && !out_of_space)
2473 numentries++;
2476 * As an optimisation if we know we aren't looking
2477 * for a wildcard name (ie. the name matches the wildcard exactly)
2478 * then we can finish on any (first) match.
2479 * This speeds up large directory searches. JRA.
2482 if(got_exact_match)
2483 finished = True;
2485 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2488 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2489 smb_fn_name(req->cmd),
2490 mask, directory, dirtype, numentries ) );
2492 /* Check if we can close the dirptr */
2493 if(close_after_request || (finished && close_if_end)) {
2494 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2495 dptr_close(&dptr_num); /* This frees up the saved mask */
2498 /* Set up the return parameter block */
2499 SSVAL(params,0,numentries);
2500 SSVAL(params,2,finished);
2501 SSVAL(params,4,0); /* Never an EA error */
2502 SSVAL(params,6,last_entry_off);
2504 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2505 max_data_bytes);
2507 return;
2510 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2512 E_md4hash(lp_servicename(SNUM(conn)),objid);
2513 return objid;
2516 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2518 SMB_ASSERT(extended_info != NULL);
2520 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2521 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2522 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2523 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2524 #ifdef SAMBA_VERSION_REVISION
2525 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2526 #endif
2527 extended_info->samba_subversion = 0;
2528 #ifdef SAMBA_VERSION_RC_RELEASE
2529 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2530 #else
2531 #ifdef SAMBA_VERSION_PRE_RELEASE
2532 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2533 #endif
2534 #endif
2535 #ifdef SAMBA_VERSION_VENDOR_PATCH
2536 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2537 #endif
2538 extended_info->samba_gitcommitdate = 0;
2539 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2540 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2541 #endif
2543 memset(extended_info->samba_version_string, 0,
2544 sizeof(extended_info->samba_version_string));
2546 snprintf (extended_info->samba_version_string,
2547 sizeof(extended_info->samba_version_string),
2548 "%s", samba_version_string());
2551 /****************************************************************************
2552 Reply to a TRANS2_QFSINFO (query filesystem info).
2553 ****************************************************************************/
2555 static void call_trans2qfsinfo(connection_struct *conn,
2556 struct smb_request *req,
2557 char **pparams, int total_params,
2558 char **ppdata, int total_data,
2559 unsigned int max_data_bytes)
2561 char *pdata, *end_data;
2562 char *params = *pparams;
2563 uint16 info_level;
2564 int data_len, len;
2565 SMB_STRUCT_STAT st;
2566 const char *vname = volume_label(SNUM(conn));
2567 int snum = SNUM(conn);
2568 char *fstype = lp_fstype(SNUM(conn));
2569 uint32 additional_flags = 0;
2571 if (total_params < 2) {
2572 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2573 return;
2576 info_level = SVAL(params,0);
2578 if (IS_IPC(conn)) {
2579 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2580 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2581 "info level (0x%x) on IPC$.\n",
2582 (unsigned int)info_level));
2583 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2584 return;
2588 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2589 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2590 DEBUG(0,("call_trans2qfsinfo: encryption required "
2591 "and info level 0x%x sent.\n",
2592 (unsigned int)info_level));
2593 exit_server_cleanly("encryption required "
2594 "on connection");
2595 return;
2599 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2601 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2602 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2603 reply_doserror(req, ERRSRV, ERRinvdevice);
2604 return;
2607 *ppdata = (char *)SMB_REALLOC(
2608 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2609 if (*ppdata == NULL ) {
2610 reply_nterror(req, NT_STATUS_NO_MEMORY);
2611 return;
2614 pdata = *ppdata;
2615 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2616 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2618 switch (info_level) {
2619 case SMB_INFO_ALLOCATION:
2621 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2622 data_len = 18;
2623 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2624 reply_unixerror(req, ERRHRD, ERRgeneral);
2625 return;
2628 block_size = lp_block_size(snum);
2629 if (bsize < block_size) {
2630 uint64_t factor = block_size/bsize;
2631 bsize = block_size;
2632 dsize /= factor;
2633 dfree /= factor;
2635 if (bsize > block_size) {
2636 uint64_t factor = bsize/block_size;
2637 bsize = block_size;
2638 dsize *= factor;
2639 dfree *= factor;
2641 bytes_per_sector = 512;
2642 sectors_per_unit = bsize/bytes_per_sector;
2644 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2645 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2646 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2648 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2649 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2650 SIVAL(pdata,l1_cUnit,dsize);
2651 SIVAL(pdata,l1_cUnitAvail,dfree);
2652 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2653 break;
2656 case SMB_INFO_VOLUME:
2657 /* Return volume name */
2659 * Add volume serial number - hash of a combination of
2660 * the called hostname and the service name.
2662 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2664 * Win2k3 and previous mess this up by sending a name length
2665 * one byte short. I believe only older clients (OS/2 Win9x) use
2666 * this call so try fixing this by adding a terminating null to
2667 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2669 len = srvstr_push(
2670 pdata, req->flags2,
2671 pdata+l2_vol_szVolLabel, vname,
2672 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2673 STR_NOALIGN|STR_TERMINATE);
2674 SCVAL(pdata,l2_vol_cch,len);
2675 data_len = l2_vol_szVolLabel + len;
2676 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2677 (unsigned)st.st_ctime, len, vname));
2678 break;
2680 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2681 case SMB_FS_ATTRIBUTE_INFORMATION:
2683 additional_flags = 0;
2684 #if defined(HAVE_SYS_QUOTAS)
2685 additional_flags |= FILE_VOLUME_QUOTAS;
2686 #endif
2688 if(lp_nt_acl_support(SNUM(conn))) {
2689 additional_flags |= FILE_PERSISTENT_ACLS;
2692 /* Capabilities are filled in at connection time through STATVFS call */
2693 additional_flags |= conn->fs_capabilities;
2695 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2696 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2697 additional_flags); /* FS ATTRIBUTES */
2699 SIVAL(pdata,4,255); /* Max filename component length */
2700 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2701 and will think we can't do long filenames */
2702 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2703 PTR_DIFF(end_data, pdata+12),
2704 STR_UNICODE);
2705 SIVAL(pdata,8,len);
2706 data_len = 12 + len;
2707 break;
2709 case SMB_QUERY_FS_LABEL_INFO:
2710 case SMB_FS_LABEL_INFORMATION:
2711 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2712 PTR_DIFF(end_data, pdata+4), 0);
2713 data_len = 4 + len;
2714 SIVAL(pdata,0,len);
2715 break;
2717 case SMB_QUERY_FS_VOLUME_INFO:
2718 case SMB_FS_VOLUME_INFORMATION:
2721 * Add volume serial number - hash of a combination of
2722 * the called hostname and the service name.
2724 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2725 (str_checksum(get_local_machine_name())<<16));
2727 /* Max label len is 32 characters. */
2728 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2729 PTR_DIFF(end_data, pdata+18),
2730 STR_UNICODE);
2731 SIVAL(pdata,12,len);
2732 data_len = 18+len;
2734 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2735 (int)strlen(vname),vname, lp_servicename(snum)));
2736 break;
2738 case SMB_QUERY_FS_SIZE_INFO:
2739 case SMB_FS_SIZE_INFORMATION:
2741 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2742 data_len = 24;
2743 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2744 reply_unixerror(req, ERRHRD, ERRgeneral);
2745 return;
2747 block_size = lp_block_size(snum);
2748 if (bsize < block_size) {
2749 uint64_t factor = block_size/bsize;
2750 bsize = block_size;
2751 dsize /= factor;
2752 dfree /= factor;
2754 if (bsize > block_size) {
2755 uint64_t factor = bsize/block_size;
2756 bsize = block_size;
2757 dsize *= factor;
2758 dfree *= factor;
2760 bytes_per_sector = 512;
2761 sectors_per_unit = bsize/bytes_per_sector;
2762 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2763 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2764 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2765 SBIG_UINT(pdata,0,dsize);
2766 SBIG_UINT(pdata,8,dfree);
2767 SIVAL(pdata,16,sectors_per_unit);
2768 SIVAL(pdata,20,bytes_per_sector);
2769 break;
2772 case SMB_FS_FULL_SIZE_INFORMATION:
2774 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2775 data_len = 32;
2776 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2777 reply_unixerror(req, ERRHRD, ERRgeneral);
2778 return;
2780 block_size = lp_block_size(snum);
2781 if (bsize < block_size) {
2782 uint64_t factor = block_size/bsize;
2783 bsize = block_size;
2784 dsize /= factor;
2785 dfree /= factor;
2787 if (bsize > block_size) {
2788 uint64_t factor = bsize/block_size;
2789 bsize = block_size;
2790 dsize *= factor;
2791 dfree *= factor;
2793 bytes_per_sector = 512;
2794 sectors_per_unit = bsize/bytes_per_sector;
2795 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2796 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2797 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2798 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2799 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2800 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2801 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2802 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2803 break;
2806 case SMB_QUERY_FS_DEVICE_INFO:
2807 case SMB_FS_DEVICE_INFORMATION:
2808 data_len = 8;
2809 SIVAL(pdata,0,0); /* dev type */
2810 SIVAL(pdata,4,0); /* characteristics */
2811 break;
2813 #ifdef HAVE_SYS_QUOTAS
2814 case SMB_FS_QUOTA_INFORMATION:
2816 * what we have to send --metze:
2818 * Unknown1: 24 NULL bytes
2819 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2820 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2821 * Quota Flags: 2 byte :
2822 * Unknown3: 6 NULL bytes
2824 * 48 bytes total
2826 * details for Quota Flags:
2828 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2829 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2830 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2831 * 0x0001 Enable Quotas: enable quota for this fs
2835 /* we need to fake up a fsp here,
2836 * because its not send in this call
2838 files_struct fsp;
2839 SMB_NTQUOTA_STRUCT quotas;
2841 ZERO_STRUCT(fsp);
2842 ZERO_STRUCT(quotas);
2844 fsp.conn = conn;
2845 fsp.fnum = -1;
2847 /* access check */
2848 if (conn->server_info->utok.uid != 0) {
2849 DEBUG(0,("set_user_quota: access_denied "
2850 "service [%s] user [%s]\n",
2851 lp_servicename(SNUM(conn)),
2852 conn->server_info->unix_name));
2853 reply_doserror(req, ERRDOS, ERRnoaccess);
2854 return;
2857 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2858 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2859 reply_doserror(req, ERRSRV, ERRerror);
2860 return;
2863 data_len = 48;
2865 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2867 /* Unknown1 24 NULL bytes*/
2868 SBIG_UINT(pdata,0,(uint64_t)0);
2869 SBIG_UINT(pdata,8,(uint64_t)0);
2870 SBIG_UINT(pdata,16,(uint64_t)0);
2872 /* Default Soft Quota 8 bytes */
2873 SBIG_UINT(pdata,24,quotas.softlim);
2875 /* Default Hard Quota 8 bytes */
2876 SBIG_UINT(pdata,32,quotas.hardlim);
2878 /* Quota flag 2 bytes */
2879 SSVAL(pdata,40,quotas.qflags);
2881 /* Unknown3 6 NULL bytes */
2882 SSVAL(pdata,42,0);
2883 SIVAL(pdata,44,0);
2885 break;
2887 #endif /* HAVE_SYS_QUOTAS */
2888 case SMB_FS_OBJECTID_INFORMATION:
2890 unsigned char objid[16];
2891 struct smb_extended_info extended_info;
2892 memcpy(pdata,create_volume_objectid(conn, objid),16);
2893 samba_extended_info_version (&extended_info);
2894 SIVAL(pdata,16,extended_info.samba_magic);
2895 SIVAL(pdata,20,extended_info.samba_version);
2896 SIVAL(pdata,24,extended_info.samba_subversion);
2897 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2898 memcpy(pdata+36,extended_info.samba_version_string,28);
2899 data_len = 64;
2900 break;
2904 * Query the version and capabilities of the CIFS UNIX extensions
2905 * in use.
2908 case SMB_QUERY_CIFS_UNIX_INFO:
2910 bool large_write = lp_min_receive_file_size() &&
2911 !srv_is_signing_active();
2912 bool large_read = !srv_is_signing_active();
2913 int encrypt_caps = 0;
2915 if (!lp_unix_extensions()) {
2916 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2917 return;
2920 switch (conn->encrypt_level) {
2921 case 0:
2922 encrypt_caps = 0;
2923 break;
2924 case 1:
2925 case Auto:
2926 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2927 break;
2928 case Required:
2929 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2930 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2931 large_write = false;
2932 large_read = false;
2933 break;
2936 data_len = 12;
2937 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2938 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2940 /* We have POSIX ACLs, pathname, encryption,
2941 * large read/write, and locking capability. */
2943 SBIG_UINT(pdata,4,((uint64_t)(
2944 CIFS_UNIX_POSIX_ACLS_CAP|
2945 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2946 CIFS_UNIX_FCNTL_LOCKS_CAP|
2947 CIFS_UNIX_EXTATTR_CAP|
2948 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2949 encrypt_caps|
2950 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2951 (large_write ?
2952 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2953 break;
2956 case SMB_QUERY_POSIX_FS_INFO:
2958 int rc;
2959 vfs_statvfs_struct svfs;
2961 if (!lp_unix_extensions()) {
2962 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2963 return;
2966 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2968 if (!rc) {
2969 data_len = 56;
2970 SIVAL(pdata,0,svfs.OptimalTransferSize);
2971 SIVAL(pdata,4,svfs.BlockSize);
2972 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2973 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2974 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2975 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2976 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2977 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2978 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2979 #ifdef EOPNOTSUPP
2980 } else if (rc == EOPNOTSUPP) {
2981 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2982 return;
2983 #endif /* EOPNOTSUPP */
2984 } else {
2985 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2986 reply_doserror(req, ERRSRV, ERRerror);
2987 return;
2989 break;
2992 case SMB_QUERY_POSIX_WHOAMI:
2994 uint32_t flags = 0;
2995 uint32_t sid_bytes;
2996 int i;
2998 if (!lp_unix_extensions()) {
2999 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3000 return;
3003 if (max_data_bytes < 40) {
3004 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3005 return;
3008 /* We ARE guest if global_sid_Builtin_Guests is
3009 * in our list of SIDs.
3011 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3012 conn->server_info->ptok)) {
3013 flags |= SMB_WHOAMI_GUEST;
3016 /* We are NOT guest if global_sid_Authenticated_Users
3017 * is in our list of SIDs.
3019 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3020 conn->server_info->ptok)) {
3021 flags &= ~SMB_WHOAMI_GUEST;
3024 /* NOTE: 8 bytes for UID/GID, irrespective of native
3025 * platform size. This matches
3026 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3028 data_len = 4 /* flags */
3029 + 4 /* flag mask */
3030 + 8 /* uid */
3031 + 8 /* gid */
3032 + 4 /* ngroups */
3033 + 4 /* num_sids */
3034 + 4 /* SID bytes */
3035 + 4 /* pad/reserved */
3036 + (conn->server_info->utok.ngroups * 8)
3037 /* groups list */
3038 + (conn->server_info->ptok->num_sids *
3039 SID_MAX_SIZE)
3040 /* SID list */;
3042 SIVAL(pdata, 0, flags);
3043 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3044 SBIG_UINT(pdata, 8,
3045 (uint64_t)conn->server_info->utok.uid);
3046 SBIG_UINT(pdata, 16,
3047 (uint64_t)conn->server_info->utok.gid);
3050 if (data_len >= max_data_bytes) {
3051 /* Potential overflow, skip the GIDs and SIDs. */
3053 SIVAL(pdata, 24, 0); /* num_groups */
3054 SIVAL(pdata, 28, 0); /* num_sids */
3055 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3056 SIVAL(pdata, 36, 0); /* reserved */
3058 data_len = 40;
3059 break;
3062 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3063 SIVAL(pdata, 28, conn->server_info->num_sids);
3065 /* We walk the SID list twice, but this call is fairly
3066 * infrequent, and I don't expect that it's performance
3067 * sensitive -- jpeach
3069 for (i = 0, sid_bytes = 0;
3070 i < conn->server_info->ptok->num_sids; ++i) {
3071 sid_bytes += ndr_size_dom_sid(
3072 &conn->server_info->ptok->user_sids[i],
3073 NULL,
3077 /* SID list byte count */
3078 SIVAL(pdata, 32, sid_bytes);
3080 /* 4 bytes pad/reserved - must be zero */
3081 SIVAL(pdata, 36, 0);
3082 data_len = 40;
3084 /* GID list */
3085 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3086 SBIG_UINT(pdata, data_len,
3087 (uint64_t)conn->server_info->utok.groups[i]);
3088 data_len += 8;
3091 /* SID list */
3092 for (i = 0;
3093 i < conn->server_info->ptok->num_sids; ++i) {
3094 int sid_len = ndr_size_dom_sid(
3095 &conn->server_info->ptok->user_sids[i],
3096 NULL,
3099 sid_linearize(pdata + data_len, sid_len,
3100 &conn->server_info->ptok->user_sids[i]);
3101 data_len += sid_len;
3104 break;
3107 case SMB_MAC_QUERY_FS_INFO:
3109 * Thursby MAC extension... ONLY on NTFS filesystems
3110 * once we do streams then we don't need this
3112 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3113 data_len = 88;
3114 SIVAL(pdata,84,0x100); /* Don't support mac... */
3115 break;
3117 /* drop through */
3118 default:
3119 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3120 return;
3124 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3125 max_data_bytes);
3127 DEBUG( 4, ( "%s info_level = %d\n",
3128 smb_fn_name(req->cmd), info_level) );
3130 return;
3133 /****************************************************************************
3134 Reply to a TRANS2_SETFSINFO (set filesystem info).
3135 ****************************************************************************/
3137 static void call_trans2setfsinfo(connection_struct *conn,
3138 struct smb_request *req,
3139 char **pparams, int total_params,
3140 char **ppdata, int total_data,
3141 unsigned int max_data_bytes)
3143 char *pdata = *ppdata;
3144 char *params = *pparams;
3145 uint16 info_level;
3147 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3149 /* */
3150 if (total_params < 4) {
3151 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3152 total_params));
3153 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3154 return;
3157 info_level = SVAL(params,2);
3159 if (IS_IPC(conn)) {
3160 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3161 info_level != SMB_SET_CIFS_UNIX_INFO) {
3162 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3163 "info level (0x%x) on IPC$.\n",
3164 (unsigned int)info_level));
3165 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3166 return;
3170 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3171 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3172 DEBUG(0,("call_trans2setfsinfo: encryption required "
3173 "and info level 0x%x sent.\n",
3174 (unsigned int)info_level));
3175 exit_server_cleanly("encryption required "
3176 "on connection");
3177 return;
3181 switch(info_level) {
3182 case SMB_SET_CIFS_UNIX_INFO:
3184 uint16 client_unix_major;
3185 uint16 client_unix_minor;
3186 uint32 client_unix_cap_low;
3187 uint32 client_unix_cap_high;
3189 if (!lp_unix_extensions()) {
3190 reply_nterror(req,
3191 NT_STATUS_INVALID_LEVEL);
3192 return;
3195 /* There should be 12 bytes of capabilities set. */
3196 if (total_data < 8) {
3197 reply_nterror(
3198 req,
3199 NT_STATUS_INVALID_PARAMETER);
3200 return;
3202 client_unix_major = SVAL(pdata,0);
3203 client_unix_minor = SVAL(pdata,2);
3204 client_unix_cap_low = IVAL(pdata,4);
3205 client_unix_cap_high = IVAL(pdata,8);
3206 /* Just print these values for now. */
3207 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3208 cap_low = 0x%x, cap_high = 0x%x\n",
3209 (unsigned int)client_unix_major,
3210 (unsigned int)client_unix_minor,
3211 (unsigned int)client_unix_cap_low,
3212 (unsigned int)client_unix_cap_high ));
3214 /* Here is where we must switch to posix pathname processing... */
3215 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3216 lp_set_posix_pathnames();
3217 mangle_change_to_posix();
3220 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3221 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3222 /* Client that knows how to do posix locks,
3223 * but not posix open/mkdir operations. Set a
3224 * default type for read/write checks. */
3226 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3229 break;
3232 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3234 NTSTATUS status;
3235 size_t param_len = 0;
3236 size_t data_len = total_data;
3238 if (!lp_unix_extensions()) {
3239 reply_nterror(
3240 req,
3241 NT_STATUS_INVALID_LEVEL);
3242 return;
3245 if (lp_smb_encrypt(SNUM(conn)) == false) {
3246 reply_nterror(
3247 req,
3248 NT_STATUS_NOT_SUPPORTED);
3249 return;
3252 DEBUG( 4,("call_trans2setfsinfo: "
3253 "request transport encryption.\n"));
3255 status = srv_request_encryption_setup(conn,
3256 (unsigned char **)ppdata,
3257 &data_len,
3258 (unsigned char **)pparams,
3259 &param_len);
3261 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3262 !NT_STATUS_IS_OK(status)) {
3263 reply_nterror(req, status);
3264 return;
3267 send_trans2_replies(conn, req,
3268 *pparams,
3269 param_len,
3270 *ppdata,
3271 data_len,
3272 max_data_bytes);
3274 if (NT_STATUS_IS_OK(status)) {
3275 /* Server-side transport
3276 * encryption is now *on*. */
3277 status = srv_encryption_start(conn);
3278 if (!NT_STATUS_IS_OK(status)) {
3279 exit_server_cleanly(
3280 "Failure in setting "
3281 "up encrypted transport");
3284 return;
3287 case SMB_FS_QUOTA_INFORMATION:
3289 files_struct *fsp = NULL;
3290 SMB_NTQUOTA_STRUCT quotas;
3292 ZERO_STRUCT(quotas);
3294 /* access check */
3295 if ((conn->server_info->utok.uid != 0)
3296 ||!CAN_WRITE(conn)) {
3297 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3298 lp_servicename(SNUM(conn)),
3299 conn->server_info->unix_name));
3300 reply_doserror(req, ERRSRV, ERRaccess);
3301 return;
3304 /* note: normaly there're 48 bytes,
3305 * but we didn't use the last 6 bytes for now
3306 * --metze
3308 fsp = file_fsp(req, SVAL(params,0));
3310 if (!check_fsp_ntquota_handle(conn, req,
3311 fsp)) {
3312 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3313 reply_nterror(
3314 req, NT_STATUS_INVALID_HANDLE);
3315 return;
3318 if (total_data < 42) {
3319 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3320 total_data));
3321 reply_nterror(
3322 req,
3323 NT_STATUS_INVALID_PARAMETER);
3324 return;
3327 /* unknown_1 24 NULL bytes in pdata*/
3329 /* the soft quotas 8 bytes (uint64_t)*/
3330 quotas.softlim = (uint64_t)IVAL(pdata,24);
3331 #ifdef LARGE_SMB_OFF_T
3332 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3333 #else /* LARGE_SMB_OFF_T */
3334 if ((IVAL(pdata,28) != 0)&&
3335 ((quotas.softlim != 0xFFFFFFFF)||
3336 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3337 /* more than 32 bits? */
3338 reply_nterror(
3339 req,
3340 NT_STATUS_INVALID_PARAMETER);
3341 return;
3343 #endif /* LARGE_SMB_OFF_T */
3345 /* the hard quotas 8 bytes (uint64_t)*/
3346 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3347 #ifdef LARGE_SMB_OFF_T
3348 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3349 #else /* LARGE_SMB_OFF_T */
3350 if ((IVAL(pdata,36) != 0)&&
3351 ((quotas.hardlim != 0xFFFFFFFF)||
3352 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3353 /* more than 32 bits? */
3354 reply_nterror(
3355 req,
3356 NT_STATUS_INVALID_PARAMETER);
3357 return;
3359 #endif /* LARGE_SMB_OFF_T */
3361 /* quota_flags 2 bytes **/
3362 quotas.qflags = SVAL(pdata,40);
3364 /* unknown_2 6 NULL bytes follow*/
3366 /* now set the quotas */
3367 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
3368 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3369 reply_doserror(req, ERRSRV, ERRerror);
3370 return;
3373 break;
3375 default:
3376 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3377 info_level));
3378 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3379 return;
3380 break;
3384 * sending this reply works fine,
3385 * but I'm not sure it's the same
3386 * like windows do...
3387 * --metze
3389 reply_outbuf(req, 10, 0);
3392 #if defined(HAVE_POSIX_ACLS)
3393 /****************************************************************************
3394 Utility function to count the number of entries in a POSIX acl.
3395 ****************************************************************************/
3397 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3399 unsigned int ace_count = 0;
3400 int entry_id = SMB_ACL_FIRST_ENTRY;
3401 SMB_ACL_ENTRY_T entry;
3403 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3404 /* get_next... */
3405 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3406 entry_id = SMB_ACL_NEXT_ENTRY;
3408 ace_count++;
3410 return ace_count;
3413 /****************************************************************************
3414 Utility function to marshall a POSIX acl into wire format.
3415 ****************************************************************************/
3417 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3419 int entry_id = SMB_ACL_FIRST_ENTRY;
3420 SMB_ACL_ENTRY_T entry;
3422 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3423 SMB_ACL_TAG_T tagtype;
3424 SMB_ACL_PERMSET_T permset;
3425 unsigned char perms = 0;
3426 unsigned int own_grp;
3428 /* get_next... */
3429 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3430 entry_id = SMB_ACL_NEXT_ENTRY;
3433 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3434 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3435 return False;
3438 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3439 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3440 return False;
3443 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3444 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3445 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3447 SCVAL(pdata,1,perms);
3449 switch (tagtype) {
3450 case SMB_ACL_USER_OBJ:
3451 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3452 own_grp = (unsigned int)pst->st_uid;
3453 SIVAL(pdata,2,own_grp);
3454 SIVAL(pdata,6,0);
3455 break;
3456 case SMB_ACL_USER:
3458 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3459 if (!puid) {
3460 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3461 return False;
3463 own_grp = (unsigned int)*puid;
3464 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3465 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3466 SIVAL(pdata,2,own_grp);
3467 SIVAL(pdata,6,0);
3468 break;
3470 case SMB_ACL_GROUP_OBJ:
3471 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3472 own_grp = (unsigned int)pst->st_gid;
3473 SIVAL(pdata,2,own_grp);
3474 SIVAL(pdata,6,0);
3475 break;
3476 case SMB_ACL_GROUP:
3478 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3479 if (!pgid) {
3480 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3481 return False;
3483 own_grp = (unsigned int)*pgid;
3484 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3485 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3486 SIVAL(pdata,2,own_grp);
3487 SIVAL(pdata,6,0);
3488 break;
3490 case SMB_ACL_MASK:
3491 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3492 SIVAL(pdata,2,0xFFFFFFFF);
3493 SIVAL(pdata,6,0xFFFFFFFF);
3494 break;
3495 case SMB_ACL_OTHER:
3496 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3497 SIVAL(pdata,2,0xFFFFFFFF);
3498 SIVAL(pdata,6,0xFFFFFFFF);
3499 break;
3500 default:
3501 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3502 return False;
3504 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3507 return True;
3509 #endif
3511 /****************************************************************************
3512 Store the FILE_UNIX_BASIC info.
3513 ****************************************************************************/
3515 static char *store_file_unix_basic(connection_struct *conn,
3516 char *pdata,
3517 files_struct *fsp,
3518 const SMB_STRUCT_STAT *psbuf)
3520 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3521 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3523 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3524 pdata += 8;
3526 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3527 pdata += 8;
3529 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3530 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3531 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3532 pdata += 24;
3534 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3535 SIVAL(pdata,4,0);
3536 pdata += 8;
3538 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3539 SIVAL(pdata,4,0);
3540 pdata += 8;
3542 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3543 pdata += 4;
3545 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3546 SIVAL(pdata,4,0);
3547 pdata += 8;
3549 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3550 SIVAL(pdata,4,0);
3551 pdata += 8;
3553 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3554 pdata += 8;
3556 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3557 SIVAL(pdata,4,0);
3558 pdata += 8;
3560 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3561 SIVAL(pdata,4,0);
3562 pdata += 8;
3564 return pdata;
3567 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3568 * the chflags(2) (or equivalent) flags.
3570 * XXX: this really should be behind the VFS interface. To do this, we would
3571 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3572 * Each VFS module could then implement its own mapping as appropriate for the
3573 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3575 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3576 info2_flags_map[] =
3578 #ifdef UF_NODUMP
3579 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3580 #endif
3582 #ifdef UF_IMMUTABLE
3583 { UF_IMMUTABLE, EXT_IMMUTABLE },
3584 #endif
3586 #ifdef UF_APPEND
3587 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3588 #endif
3590 #ifdef UF_HIDDEN
3591 { UF_HIDDEN, EXT_HIDDEN },
3592 #endif
3594 /* Do not remove. We need to guarantee that this array has at least one
3595 * entry to build on HP-UX.
3597 { 0, 0 }
3601 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3602 uint32 *smb_fflags, uint32 *smb_fmask)
3604 #ifdef HAVE_STAT_ST_FLAGS
3605 int i;
3607 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3608 *smb_fmask |= info2_flags_map[i].smb_fflag;
3609 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3610 *smb_fflags |= info2_flags_map[i].smb_fflag;
3613 #endif /* HAVE_STAT_ST_FLAGS */
3616 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3617 const uint32 smb_fflags,
3618 const uint32 smb_fmask,
3619 int *stat_fflags)
3621 #ifdef HAVE_STAT_ST_FLAGS
3622 uint32 max_fmask = 0;
3623 int i;
3625 *stat_fflags = psbuf->st_flags;
3627 /* For each flags requested in smb_fmask, check the state of the
3628 * corresponding flag in smb_fflags and set or clear the matching
3629 * stat flag.
3632 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3633 max_fmask |= info2_flags_map[i].smb_fflag;
3634 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3635 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3636 *stat_fflags |= info2_flags_map[i].stat_fflag;
3637 } else {
3638 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3643 /* If smb_fmask is asking to set any bits that are not supported by
3644 * our flag mappings, we should fail.
3646 if ((smb_fmask & max_fmask) != smb_fmask) {
3647 return False;
3650 return True;
3651 #else
3652 return False;
3653 #endif /* HAVE_STAT_ST_FLAGS */
3657 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3658 * of file flags and birth (create) time.
3660 static char *store_file_unix_basic_info2(connection_struct *conn,
3661 char *pdata,
3662 files_struct *fsp,
3663 const SMB_STRUCT_STAT *psbuf)
3665 uint32 file_flags = 0;
3666 uint32 flags_mask = 0;
3668 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3670 /* Create (birth) time 64 bit */
3671 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3672 pdata += 8;
3674 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3675 SIVAL(pdata, 0, file_flags); /* flags */
3676 SIVAL(pdata, 4, flags_mask); /* mask */
3677 pdata += 8;
3679 return pdata;
3682 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3683 const struct stream_struct *streams,
3684 char *data,
3685 unsigned int max_data_bytes,
3686 unsigned int *data_size)
3688 unsigned int i;
3689 unsigned int ofs = 0;
3691 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3692 unsigned int next_offset;
3693 size_t namelen;
3694 smb_ucs2_t *namebuf;
3696 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3697 streams[i].name, &namelen) ||
3698 namelen <= 2)
3700 return NT_STATUS_INVALID_PARAMETER;
3704 * name_buf is now null-terminated, we need to marshall as not
3705 * terminated
3708 namelen -= 2;
3710 SIVAL(data, ofs+4, namelen);
3711 SOFF_T(data, ofs+8, streams[i].size);
3712 SOFF_T(data, ofs+16, streams[i].alloc_size);
3713 memcpy(data+ofs+24, namebuf, namelen);
3714 TALLOC_FREE(namebuf);
3716 next_offset = ofs + 24 + namelen;
3718 if (i == num_streams-1) {
3719 SIVAL(data, ofs, 0);
3721 else {
3722 unsigned int align = ndr_align_size(next_offset, 8);
3724 memset(data+next_offset, 0, align);
3725 next_offset += align;
3727 SIVAL(data, ofs, next_offset - ofs);
3728 ofs = next_offset;
3731 ofs = next_offset;
3734 *data_size = ofs;
3736 return NT_STATUS_OK;
3739 /****************************************************************************
3740 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3741 ****************************************************************************/
3743 static void call_trans2qpipeinfo(connection_struct *conn,
3744 struct smb_request *req,
3745 unsigned int tran_call,
3746 char **pparams, int total_params,
3747 char **ppdata, int total_data,
3748 unsigned int max_data_bytes)
3750 char *params = *pparams;
3751 char *pdata = *ppdata;
3752 unsigned int data_size = 0;
3753 unsigned int param_size = 2;
3754 uint16 info_level;
3755 files_struct *fsp;
3757 if (!params) {
3758 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3759 return;
3762 if (total_params < 4) {
3763 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3764 return;
3767 fsp = file_fsp(req, SVAL(params,0));
3768 if (!fsp_is_np(fsp)) {
3769 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3770 return;
3773 info_level = SVAL(params,2);
3775 *pparams = (char *)SMB_REALLOC(*pparams,2);
3776 if (*pparams == NULL) {
3777 reply_nterror(req, NT_STATUS_NO_MEMORY);
3778 return;
3780 params = *pparams;
3781 SSVAL(params,0,0);
3782 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3783 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3784 if (*ppdata == NULL ) {
3785 reply_nterror(req, NT_STATUS_NO_MEMORY);
3786 return;
3788 pdata = *ppdata;
3790 switch (info_level) {
3791 case SMB_FILE_STANDARD_INFORMATION:
3792 memset(pdata,0,24);
3793 SOFF_T(pdata,0,4096LL);
3794 SIVAL(pdata,16,1);
3795 SIVAL(pdata,20,1);
3796 data_size = 24;
3797 break;
3799 default:
3800 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3801 return;
3804 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3805 max_data_bytes);
3807 return;
3810 /****************************************************************************
3811 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3812 file name or file id).
3813 ****************************************************************************/
3815 static void call_trans2qfilepathinfo(connection_struct *conn,
3816 struct smb_request *req,
3817 unsigned int tran_call,
3818 char **pparams, int total_params,
3819 char **ppdata, int total_data,
3820 unsigned int max_data_bytes)
3822 char *params = *pparams;
3823 char *pdata = *ppdata;
3824 char *dstart, *dend;
3825 uint16 info_level;
3826 int mode=0;
3827 int nlink;
3828 SMB_OFF_T file_size=0;
3829 uint64_t allocation_size=0;
3830 unsigned int data_size = 0;
3831 unsigned int param_size = 2;
3832 SMB_STRUCT_STAT sbuf;
3833 char *dos_fname = NULL;
3834 char *fname = NULL;
3835 char *fullpathname;
3836 char *base_name;
3837 char *p;
3838 SMB_OFF_T pos = 0;
3839 bool delete_pending = False;
3840 int len;
3841 time_t create_time, mtime, atime;
3842 struct timespec create_time_ts, mtime_ts, atime_ts;
3843 struct timespec write_time_ts;
3844 files_struct *fsp = NULL;
3845 struct file_id fileid;
3846 struct ea_list *ea_list = NULL;
3847 char *lock_data = NULL;
3848 bool ms_dfs_link = false;
3849 TALLOC_CTX *ctx = talloc_tos();
3851 if (!params) {
3852 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3853 return;
3856 ZERO_STRUCT(sbuf);
3857 ZERO_STRUCT(write_time_ts);
3859 if (tran_call == TRANSACT2_QFILEINFO) {
3860 if (total_params < 4) {
3861 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3862 return;
3865 if (IS_IPC(conn)) {
3866 call_trans2qpipeinfo(conn, req, tran_call,
3867 pparams, total_params,
3868 ppdata, total_data,
3869 max_data_bytes);
3870 return;
3873 fsp = file_fsp(req, SVAL(params,0));
3874 info_level = SVAL(params,2);
3876 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3878 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3879 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3880 return;
3883 /* Initial check for valid fsp ptr. */
3884 if (!check_fsp_open(conn, req, fsp)) {
3885 return;
3888 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3889 if (!fname) {
3890 reply_nterror(req, NT_STATUS_NO_MEMORY);
3891 return;
3894 if(fsp->fake_file_handle) {
3896 * This is actually for the QUOTA_FAKE_FILE --metze
3899 /* We know this name is ok, it's already passed the checks. */
3901 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3903 * This is actually a QFILEINFO on a directory
3904 * handle (returned from an NT SMB). NT5.0 seems
3905 * to do this call. JRA.
3908 if (INFO_LEVEL_IS_UNIX(info_level)) {
3909 /* Always do lstat for UNIX calls. */
3910 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3911 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3912 reply_unixerror(req,ERRDOS,ERRbadpath);
3913 return;
3915 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3916 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3917 reply_unixerror(req, ERRDOS, ERRbadpath);
3918 return;
3921 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3922 get_file_infos(fileid, &delete_pending, &write_time_ts);
3923 } else {
3925 * Original code - this is an open file.
3927 if (!check_fsp(conn, req, fsp)) {
3928 return;
3931 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3932 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3933 reply_unixerror(req, ERRDOS, ERRbadfid);
3934 return;
3936 pos = fsp->fh->position_information;
3937 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3938 get_file_infos(fileid, &delete_pending, &write_time_ts);
3941 } else {
3942 NTSTATUS status = NT_STATUS_OK;
3944 /* qpathinfo */
3945 if (total_params < 7) {
3946 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3947 return;
3950 info_level = SVAL(params,0);
3952 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3954 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3955 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3956 return;
3959 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
3960 total_params - 6,
3961 STR_TERMINATE, &status);
3962 if (!NT_STATUS_IS_OK(status)) {
3963 reply_nterror(req, status);
3964 return;
3967 status = resolve_dfspath(ctx,
3968 conn,
3969 req->flags2 & FLAGS2_DFS_PATHNAMES,
3970 fname,
3971 &fname);
3972 if (!NT_STATUS_IS_OK(status)) {
3973 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3974 reply_botherror(req,
3975 NT_STATUS_PATH_NOT_COVERED,
3976 ERRSRV, ERRbadpath);
3978 reply_nterror(req, status);
3979 return;
3982 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3983 if (!NT_STATUS_IS_OK(status)) {
3984 reply_nterror(req, status);
3985 return;
3987 status = check_name(conn, fname);
3988 if (!NT_STATUS_IS_OK(status)) {
3989 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3990 reply_nterror(req, status);
3991 return;
3994 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3995 && is_ntfs_stream_name(fname)) {
3996 char *base;
3997 SMB_STRUCT_STAT bsbuf;
3999 status = split_ntfs_stream_name(talloc_tos(), fname,
4000 &base, NULL);
4001 if (!NT_STATUS_IS_OK(status)) {
4002 DEBUG(10, ("create_file_unixpath: "
4003 "split_ntfs_stream_name failed: %s\n",
4004 nt_errstr(status)));
4005 reply_nterror(req, status);
4006 return;
4009 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4011 if (INFO_LEVEL_IS_UNIX(info_level)) {
4012 /* Always do lstat for UNIX calls. */
4013 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4014 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4015 reply_unixerror(req,ERRDOS,ERRbadpath);
4016 return;
4018 } else {
4019 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4020 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4021 reply_unixerror(req,ERRDOS,ERRbadpath);
4022 return;
4026 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4027 get_file_infos(fileid, &delete_pending, NULL);
4028 if (delete_pending) {
4029 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4030 return;
4034 if (INFO_LEVEL_IS_UNIX(info_level)) {
4035 /* Always do lstat for UNIX calls. */
4036 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4037 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4038 reply_unixerror(req, ERRDOS, ERRbadpath);
4039 return;
4042 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4043 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4045 if (!ms_dfs_link) {
4046 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4047 reply_unixerror(req, ERRDOS, ERRbadpath);
4048 return;
4052 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4053 get_file_infos(fileid, &delete_pending, &write_time_ts);
4054 if (delete_pending) {
4055 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4056 return;
4060 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4061 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4062 return;
4065 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4066 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4068 p = strrchr_m(fname,'/');
4069 if (!p)
4070 base_name = fname;
4071 else
4072 base_name = p+1;
4074 if (ms_dfs_link) {
4075 mode = dos_mode_msdfs(conn,fname,&sbuf);
4076 } else {
4077 mode = dos_mode(conn,fname,&sbuf);
4079 if (!mode)
4080 mode = FILE_ATTRIBUTE_NORMAL;
4082 nlink = sbuf.st_nlink;
4084 if (nlink && (mode&aDIR)) {
4085 nlink = 1;
4088 if ((nlink > 0) && delete_pending) {
4089 nlink -= 1;
4092 fullpathname = fname;
4093 if (!(mode & aDIR))
4094 file_size = get_file_size_stat(&sbuf);
4096 /* Pull out any data sent here before we realloc. */
4097 switch (info_level) {
4098 case SMB_INFO_QUERY_EAS_FROM_LIST:
4100 /* Pull any EA list from the data portion. */
4101 uint32 ea_size;
4103 if (total_data < 4) {
4104 reply_nterror(
4105 req, NT_STATUS_INVALID_PARAMETER);
4106 return;
4108 ea_size = IVAL(pdata,0);
4110 if (total_data > 0 && ea_size != total_data) {
4111 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4112 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4113 reply_nterror(
4114 req, NT_STATUS_INVALID_PARAMETER);
4115 return;
4118 if (!lp_ea_support(SNUM(conn))) {
4119 reply_doserror(req, ERRDOS,
4120 ERReasnotsupported);
4121 return;
4124 /* Pull out the list of names. */
4125 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4126 if (!ea_list) {
4127 reply_nterror(
4128 req, NT_STATUS_INVALID_PARAMETER);
4129 return;
4131 break;
4134 case SMB_QUERY_POSIX_LOCK:
4136 if (fsp == NULL || fsp->fh->fd == -1) {
4137 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4138 return;
4141 if (total_data != POSIX_LOCK_DATA_SIZE) {
4142 reply_nterror(
4143 req, NT_STATUS_INVALID_PARAMETER);
4144 return;
4147 /* Copy the lock range data. */
4148 lock_data = (char *)TALLOC_MEMDUP(
4149 ctx, pdata, total_data);
4150 if (!lock_data) {
4151 reply_nterror(req, NT_STATUS_NO_MEMORY);
4152 return;
4155 default:
4156 break;
4159 *pparams = (char *)SMB_REALLOC(*pparams,2);
4160 if (*pparams == NULL) {
4161 reply_nterror(req, NT_STATUS_NO_MEMORY);
4162 return;
4164 params = *pparams;
4165 SSVAL(params,0,0);
4166 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4167 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4168 if (*ppdata == NULL ) {
4169 reply_nterror(req, NT_STATUS_NO_MEMORY);
4170 return;
4172 pdata = *ppdata;
4173 dstart = pdata;
4174 dend = dstart + data_size - 1;
4176 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4177 mtime_ts = get_mtimespec(&sbuf);
4178 atime_ts = get_atimespec(&sbuf);
4180 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4182 if (!fsp) {
4183 /* Do we have this path open ? */
4184 files_struct *fsp1;
4185 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4186 fsp1 = file_find_di_first(fileid);
4187 if (fsp1 && fsp1->initial_allocation_size) {
4188 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4192 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4193 mtime_ts = write_time_ts;
4196 if (lp_dos_filetime_resolution(SNUM(conn))) {
4197 dos_filetime_timespec(&create_time_ts);
4198 dos_filetime_timespec(&mtime_ts);
4199 dos_filetime_timespec(&atime_ts);
4202 create_time = convert_timespec_to_time_t(create_time_ts);
4203 mtime = convert_timespec_to_time_t(mtime_ts);
4204 atime = convert_timespec_to_time_t(atime_ts);
4206 /* NT expects the name to be in an exact form of the *full*
4207 filename. See the trans2 torture test */
4208 if (ISDOT(base_name)) {
4209 dos_fname = talloc_strdup(ctx, "\\");
4210 if (!dos_fname) {
4211 reply_nterror(req, NT_STATUS_NO_MEMORY);
4212 return;
4214 } else {
4215 dos_fname = talloc_asprintf(ctx,
4216 "\\%s",
4217 fname);
4218 if (!dos_fname) {
4219 reply_nterror(req, NT_STATUS_NO_MEMORY);
4220 return;
4222 string_replace(dos_fname, '/', '\\');
4225 switch (info_level) {
4226 case SMB_INFO_STANDARD:
4227 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4228 data_size = 22;
4229 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4230 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4231 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4232 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4233 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4234 SSVAL(pdata,l1_attrFile,mode);
4235 break;
4237 case SMB_INFO_QUERY_EA_SIZE:
4239 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4240 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4241 data_size = 26;
4242 srv_put_dos_date2(pdata,0,create_time);
4243 srv_put_dos_date2(pdata,4,atime);
4244 srv_put_dos_date2(pdata,8,mtime); /* write time */
4245 SIVAL(pdata,12,(uint32)file_size);
4246 SIVAL(pdata,16,(uint32)allocation_size);
4247 SSVAL(pdata,20,mode);
4248 SIVAL(pdata,22,ea_size);
4249 break;
4252 case SMB_INFO_IS_NAME_VALID:
4253 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4254 if (tran_call == TRANSACT2_QFILEINFO) {
4255 /* os/2 needs this ? really ?*/
4256 reply_doserror(req, ERRDOS, ERRbadfunc);
4257 return;
4259 data_size = 0;
4260 param_size = 0;
4261 break;
4263 case SMB_INFO_QUERY_EAS_FROM_LIST:
4265 size_t total_ea_len = 0;
4266 struct ea_list *ea_file_list = NULL;
4268 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4270 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4271 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4273 if (!ea_list || (total_ea_len > data_size)) {
4274 data_size = 4;
4275 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4276 break;
4279 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4280 break;
4283 case SMB_INFO_QUERY_ALL_EAS:
4285 /* We have data_size bytes to put EA's into. */
4286 size_t total_ea_len = 0;
4288 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4290 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4291 if (!ea_list || (total_ea_len > data_size)) {
4292 data_size = 4;
4293 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4294 break;
4297 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4298 break;
4301 case SMB_FILE_BASIC_INFORMATION:
4302 case SMB_QUERY_FILE_BASIC_INFO:
4304 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4305 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4306 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4307 } else {
4308 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4309 data_size = 40;
4310 SIVAL(pdata,36,0);
4312 put_long_date_timespec(pdata,create_time_ts);
4313 put_long_date_timespec(pdata+8,atime_ts);
4314 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4315 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4316 SIVAL(pdata,32,mode);
4318 DEBUG(5,("SMB_QFBI - "));
4319 DEBUG(5,("create: %s ", ctime(&create_time)));
4320 DEBUG(5,("access: %s ", ctime(&atime)));
4321 DEBUG(5,("write: %s ", ctime(&mtime)));
4322 DEBUG(5,("change: %s ", ctime(&mtime)));
4323 DEBUG(5,("mode: %x\n", mode));
4324 break;
4326 case SMB_FILE_STANDARD_INFORMATION:
4327 case SMB_QUERY_FILE_STANDARD_INFO:
4329 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4330 data_size = 24;
4331 SOFF_T(pdata,0,allocation_size);
4332 SOFF_T(pdata,8,file_size);
4333 SIVAL(pdata,16,nlink);
4334 SCVAL(pdata,20,delete_pending?1:0);
4335 SCVAL(pdata,21,(mode&aDIR)?1:0);
4336 SSVAL(pdata,22,0); /* Padding. */
4337 break;
4339 case SMB_FILE_EA_INFORMATION:
4340 case SMB_QUERY_FILE_EA_INFO:
4342 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4343 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4344 data_size = 4;
4345 SIVAL(pdata,0,ea_size);
4346 break;
4349 /* Get the 8.3 name - used if NT SMB was negotiated. */
4350 case SMB_QUERY_FILE_ALT_NAME_INFO:
4351 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4353 char mangled_name[13];
4354 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4355 if (!name_to_8_3(base_name,mangled_name,
4356 True,conn->params)) {
4357 reply_nterror(
4358 req,
4359 NT_STATUS_NO_MEMORY);
4361 len = srvstr_push(dstart, req->flags2,
4362 pdata+4, mangled_name,
4363 PTR_DIFF(dend, pdata+4),
4364 STR_UNICODE);
4365 data_size = 4 + len;
4366 SIVAL(pdata,0,len);
4367 break;
4370 case SMB_QUERY_FILE_NAME_INFO:
4372 this must be *exactly* right for ACLs on mapped drives to work
4374 len = srvstr_push(dstart, req->flags2,
4375 pdata+4, dos_fname,
4376 PTR_DIFF(dend, pdata+4),
4377 STR_UNICODE);
4378 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4379 data_size = 4 + len;
4380 SIVAL(pdata,0,len);
4381 break;
4383 case SMB_FILE_ALLOCATION_INFORMATION:
4384 case SMB_QUERY_FILE_ALLOCATION_INFO:
4385 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4386 data_size = 8;
4387 SOFF_T(pdata,0,allocation_size);
4388 break;
4390 case SMB_FILE_END_OF_FILE_INFORMATION:
4391 case SMB_QUERY_FILE_END_OF_FILEINFO:
4392 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4393 data_size = 8;
4394 SOFF_T(pdata,0,file_size);
4395 break;
4397 case SMB_QUERY_FILE_ALL_INFO:
4398 case SMB_FILE_ALL_INFORMATION:
4400 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4401 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4402 put_long_date_timespec(pdata,create_time_ts);
4403 put_long_date_timespec(pdata+8,atime_ts);
4404 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4405 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4406 SIVAL(pdata,32,mode);
4407 SIVAL(pdata,36,0); /* padding. */
4408 pdata += 40;
4409 SOFF_T(pdata,0,allocation_size);
4410 SOFF_T(pdata,8,file_size);
4411 SIVAL(pdata,16,nlink);
4412 SCVAL(pdata,20,delete_pending);
4413 SCVAL(pdata,21,(mode&aDIR)?1:0);
4414 SSVAL(pdata,22,0);
4415 pdata += 24;
4416 SIVAL(pdata,0,ea_size);
4417 pdata += 4; /* EA info */
4418 len = srvstr_push(dstart, req->flags2,
4419 pdata+4, dos_fname,
4420 PTR_DIFF(dend, pdata+4),
4421 STR_UNICODE);
4422 SIVAL(pdata,0,len);
4423 pdata += 4 + len;
4424 data_size = PTR_DIFF(pdata,(*ppdata));
4425 break;
4427 case SMB_FILE_INTERNAL_INFORMATION:
4428 /* This should be an index number - looks like
4429 dev/ino to me :-)
4431 I think this causes us to fail the IFSKIT
4432 BasicFileInformationTest. -tpot */
4434 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4435 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4436 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4437 data_size = 8;
4438 break;
4440 case SMB_FILE_ACCESS_INFORMATION:
4441 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4442 if (fsp) {
4443 SIVAL(pdata,0,fsp->access_mask);
4444 } else {
4445 /* GENERIC_EXECUTE mapping from Windows */
4446 SIVAL(pdata,0,0x12019F);
4448 data_size = 4;
4449 break;
4451 case SMB_FILE_NAME_INFORMATION:
4452 /* Pathname with leading '\'. */
4454 size_t byte_len;
4455 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4456 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4457 SIVAL(pdata,0,byte_len);
4458 data_size = 4 + byte_len;
4459 break;
4462 case SMB_FILE_DISPOSITION_INFORMATION:
4463 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4464 data_size = 1;
4465 SCVAL(pdata,0,delete_pending);
4466 break;
4468 case SMB_FILE_POSITION_INFORMATION:
4469 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4470 data_size = 8;
4471 SOFF_T(pdata,0,pos);
4472 break;
4474 case SMB_FILE_MODE_INFORMATION:
4475 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4476 SIVAL(pdata,0,mode);
4477 data_size = 4;
4478 break;
4480 case SMB_FILE_ALIGNMENT_INFORMATION:
4481 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4482 SIVAL(pdata,0,0); /* No alignment needed. */
4483 data_size = 4;
4484 break;
4487 * NT4 server just returns "invalid query" to this - if we try
4488 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4489 * want this. JRA.
4491 /* The first statement above is false - verified using Thursby
4492 * client against NT4 -- gcolley.
4494 case SMB_QUERY_FILE_STREAM_INFO:
4495 case SMB_FILE_STREAM_INFORMATION: {
4496 unsigned int num_streams;
4497 struct stream_struct *streams;
4498 NTSTATUS status;
4500 DEBUG(10,("call_trans2qfilepathinfo: "
4501 "SMB_FILE_STREAM_INFORMATION\n"));
4503 status = SMB_VFS_STREAMINFO(
4504 conn, fsp, fname, talloc_tos(),
4505 &num_streams, &streams);
4507 if (!NT_STATUS_IS_OK(status)) {
4508 DEBUG(10, ("could not get stream info: %s\n",
4509 nt_errstr(status)));
4510 reply_nterror(req, status);
4511 return;
4514 status = marshall_stream_info(num_streams, streams,
4515 pdata, max_data_bytes,
4516 &data_size);
4518 if (!NT_STATUS_IS_OK(status)) {
4519 DEBUG(10, ("marshall_stream_info failed: %s\n",
4520 nt_errstr(status)));
4521 reply_nterror(req, status);
4522 return;
4525 TALLOC_FREE(streams);
4527 break;
4529 case SMB_QUERY_COMPRESSION_INFO:
4530 case SMB_FILE_COMPRESSION_INFORMATION:
4531 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4532 SOFF_T(pdata,0,file_size);
4533 SIVAL(pdata,8,0); /* ??? */
4534 SIVAL(pdata,12,0); /* ??? */
4535 data_size = 16;
4536 break;
4538 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4539 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4540 put_long_date_timespec(pdata,create_time_ts);
4541 put_long_date_timespec(pdata+8,atime_ts);
4542 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4543 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4544 SOFF_T(pdata,32,allocation_size);
4545 SOFF_T(pdata,40,file_size);
4546 SIVAL(pdata,48,mode);
4547 SIVAL(pdata,52,0); /* ??? */
4548 data_size = 56;
4549 break;
4551 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4552 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4553 SIVAL(pdata,0,mode);
4554 SIVAL(pdata,4,0);
4555 data_size = 8;
4556 break;
4559 * CIFS UNIX Extensions.
4562 case SMB_QUERY_FILE_UNIX_BASIC:
4564 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4565 data_size = PTR_DIFF(pdata,(*ppdata));
4568 int i;
4569 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4571 for (i=0; i<100; i++)
4572 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4573 DEBUG(4,("\n"));
4576 break;
4578 case SMB_QUERY_FILE_UNIX_INFO2:
4580 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4581 data_size = PTR_DIFF(pdata,(*ppdata));
4584 int i;
4585 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4587 for (i=0; i<100; i++)
4588 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4589 DEBUG(4,("\n"));
4592 break;
4594 case SMB_QUERY_FILE_UNIX_LINK:
4596 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4598 if (!buffer) {
4599 reply_nterror(req, NT_STATUS_NO_MEMORY);
4600 return;
4603 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4604 #ifdef S_ISLNK
4605 if(!S_ISLNK(sbuf.st_mode)) {
4606 reply_unixerror(req, ERRSRV,
4607 ERRbadlink);
4608 return;
4610 #else
4611 reply_unixerror(req, ERRDOS, ERRbadlink);
4612 return;
4613 #endif
4614 len = SMB_VFS_READLINK(conn,fullpathname,
4615 buffer, PATH_MAX);
4616 if (len == -1) {
4617 reply_unixerror(req, ERRDOS,
4618 ERRnoaccess);
4619 return;
4621 buffer[len] = 0;
4622 len = srvstr_push(dstart, req->flags2,
4623 pdata, buffer,
4624 PTR_DIFF(dend, pdata),
4625 STR_TERMINATE);
4626 pdata += len;
4627 data_size = PTR_DIFF(pdata,(*ppdata));
4629 break;
4632 #if defined(HAVE_POSIX_ACLS)
4633 case SMB_QUERY_POSIX_ACL:
4635 SMB_ACL_T file_acl = NULL;
4636 SMB_ACL_T def_acl = NULL;
4637 uint16 num_file_acls = 0;
4638 uint16 num_def_acls = 0;
4640 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4641 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4642 } else {
4643 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4646 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4647 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4648 fname ));
4649 reply_nterror(
4650 req,
4651 NT_STATUS_NOT_IMPLEMENTED);
4652 return;
4655 if (S_ISDIR(sbuf.st_mode)) {
4656 if (fsp && fsp->is_directory) {
4657 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4658 } else {
4659 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4661 def_acl = free_empty_sys_acl(conn, def_acl);
4664 num_file_acls = count_acl_entries(conn, file_acl);
4665 num_def_acls = count_acl_entries(conn, def_acl);
4667 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4668 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4669 data_size,
4670 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4671 SMB_POSIX_ACL_HEADER_SIZE) ));
4672 if (file_acl) {
4673 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4675 if (def_acl) {
4676 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4678 reply_nterror(
4679 req,
4680 NT_STATUS_BUFFER_TOO_SMALL);
4681 return;
4684 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4685 SSVAL(pdata,2,num_file_acls);
4686 SSVAL(pdata,4,num_def_acls);
4687 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4688 if (file_acl) {
4689 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4691 if (def_acl) {
4692 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4694 reply_nterror(
4695 req, NT_STATUS_INTERNAL_ERROR);
4696 return;
4698 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4699 if (file_acl) {
4700 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4702 if (def_acl) {
4703 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4705 reply_nterror(
4706 req,
4707 NT_STATUS_INTERNAL_ERROR);
4708 return;
4711 if (file_acl) {
4712 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4714 if (def_acl) {
4715 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4717 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4718 break;
4720 #endif
4723 case SMB_QUERY_POSIX_LOCK:
4725 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4726 uint64_t count;
4727 uint64_t offset;
4728 uint32 lock_pid;
4729 enum brl_type lock_type;
4731 if (total_data != POSIX_LOCK_DATA_SIZE) {
4732 reply_nterror(
4733 req, NT_STATUS_INVALID_PARAMETER);
4734 return;
4737 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4738 case POSIX_LOCK_TYPE_READ:
4739 lock_type = READ_LOCK;
4740 break;
4741 case POSIX_LOCK_TYPE_WRITE:
4742 lock_type = WRITE_LOCK;
4743 break;
4744 case POSIX_LOCK_TYPE_UNLOCK:
4745 default:
4746 /* There's no point in asking for an unlock... */
4747 reply_nterror(
4748 req,
4749 NT_STATUS_INVALID_PARAMETER);
4750 return;
4753 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4754 #if defined(HAVE_LONGLONG)
4755 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4756 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4757 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4758 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4759 #else /* HAVE_LONGLONG */
4760 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4761 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4762 #endif /* HAVE_LONGLONG */
4764 status = query_lock(fsp,
4765 &lock_pid,
4766 &count,
4767 &offset,
4768 &lock_type,
4769 POSIX_LOCK);
4771 if (ERROR_WAS_LOCK_DENIED(status)) {
4772 /* Here we need to report who has it locked... */
4773 data_size = POSIX_LOCK_DATA_SIZE;
4775 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4776 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4777 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4778 #if defined(HAVE_LONGLONG)
4779 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4780 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4781 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4782 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4783 #else /* HAVE_LONGLONG */
4784 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4785 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4786 #endif /* HAVE_LONGLONG */
4788 } else if (NT_STATUS_IS_OK(status)) {
4789 /* For success we just return a copy of what we sent
4790 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4791 data_size = POSIX_LOCK_DATA_SIZE;
4792 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4793 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4794 } else {
4795 reply_nterror(req, status);
4796 return;
4798 break;
4801 default:
4802 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4803 return;
4806 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4807 max_data_bytes);
4809 return;
4812 /****************************************************************************
4813 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4814 code.
4815 ****************************************************************************/
4817 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4818 connection_struct *conn,
4819 const char *oldname_in,
4820 const char *newname_in)
4822 SMB_STRUCT_STAT sbuf1, sbuf2;
4823 char *last_component_oldname = NULL;
4824 char *last_component_newname = NULL;
4825 char *oldname = NULL;
4826 char *newname = NULL;
4827 NTSTATUS status = NT_STATUS_OK;
4829 ZERO_STRUCT(sbuf1);
4830 ZERO_STRUCT(sbuf2);
4832 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4833 &last_component_oldname, &sbuf1);
4834 if (!NT_STATUS_IS_OK(status)) {
4835 return status;
4838 status = check_name(conn, oldname);
4839 if (!NT_STATUS_IS_OK(status)) {
4840 return status;
4843 /* source must already exist. */
4844 if (!VALID_STAT(sbuf1)) {
4845 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4848 status = unix_convert(ctx, conn, newname_in, False, &newname,
4849 &last_component_newname, &sbuf2);
4850 if (!NT_STATUS_IS_OK(status)) {
4851 return status;
4854 status = check_name(conn, newname);
4855 if (!NT_STATUS_IS_OK(status)) {
4856 return status;
4859 /* Disallow if newname already exists. */
4860 if (VALID_STAT(sbuf2)) {
4861 return NT_STATUS_OBJECT_NAME_COLLISION;
4864 /* No links from a directory. */
4865 if (S_ISDIR(sbuf1.st_mode)) {
4866 return NT_STATUS_FILE_IS_A_DIRECTORY;
4869 /* Ensure this is within the share. */
4870 status = check_reduced_name(conn, oldname);
4871 if (!NT_STATUS_IS_OK(status)) {
4872 return status;
4875 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4877 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4878 status = map_nt_error_from_unix(errno);
4879 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4880 nt_errstr(status), newname, oldname));
4883 return status;
4886 /****************************************************************************
4887 Deal with setting the time from any of the setfilepathinfo functions.
4888 ****************************************************************************/
4890 NTSTATUS smb_set_file_time(connection_struct *conn,
4891 files_struct *fsp,
4892 const char *fname,
4893 const SMB_STRUCT_STAT *psbuf,
4894 struct smb_file_time *ft,
4895 bool setting_write_time)
4897 uint32 action =
4898 FILE_NOTIFY_CHANGE_LAST_ACCESS
4899 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4901 if (!VALID_STAT(*psbuf)) {
4902 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4905 /* get some defaults (no modifications) if any info is zero or -1. */
4906 if (null_timespec(ft->atime)) {
4907 ft->atime= get_atimespec(psbuf);
4908 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4911 if (null_timespec(ft->mtime)) {
4912 ft->mtime = get_mtimespec(psbuf);
4913 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4916 if (!setting_write_time) {
4917 /* ft->mtime comes from change time, not write time. */
4918 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4921 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4922 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4923 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4924 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4925 if (!null_timespec(ft->create_time)) {
4926 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4927 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4931 * Try and set the times of this file if
4932 * they are different from the current values.
4936 struct timespec mts = get_mtimespec(psbuf);
4937 struct timespec ats = get_atimespec(psbuf);
4938 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4939 (timespec_compare(&ft->mtime, &mts) == 0)) {
4940 return NT_STATUS_OK;
4944 if (setting_write_time) {
4946 * This was a setfileinfo on an open file.
4947 * NT does this a lot. We also need to
4948 * set the time here, as it can be read by
4949 * FindFirst/FindNext and with the patch for bug #2045
4950 * in smbd/fileio.c it ensures that this timestamp is
4951 * kept sticky even after a write. We save the request
4952 * away and will set it on file close and after a write. JRA.
4955 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4956 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4958 if (fsp != NULL) {
4959 if (fsp->base_fsp) {
4960 set_sticky_write_time_fsp(fsp->base_fsp,
4961 ft->mtime);
4962 } else {
4963 set_sticky_write_time_fsp(fsp, ft->mtime);
4965 } else {
4966 set_sticky_write_time_path(conn, fname,
4967 vfs_file_id_from_sbuf(conn, psbuf),
4968 ft->mtime);
4972 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4974 if (fsp && fsp->base_fsp) {
4975 fname = fsp->base_fsp->fsp_name;
4978 if(file_ntimes(conn, fname, ft)!=0) {
4979 return map_nt_error_from_unix(errno);
4981 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4983 return NT_STATUS_OK;
4986 /****************************************************************************
4987 Deal with setting the dosmode from any of the setfilepathinfo functions.
4988 ****************************************************************************/
4990 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4991 files_struct *fsp,
4992 const char *fname,
4993 SMB_STRUCT_STAT *psbuf,
4994 uint32 dosmode)
4996 if (!VALID_STAT(*psbuf)) {
4997 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5000 if (fsp) {
5001 if (fsp->base_fsp) {
5002 fname = fsp->base_fsp->fsp_name;
5003 } else {
5004 fname = fsp->fsp_name;
5008 if (dosmode) {
5009 if (S_ISDIR(psbuf->st_mode)) {
5010 dosmode |= aDIR;
5011 } else {
5012 dosmode &= ~aDIR;
5016 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5018 /* check the mode isn't different, before changing it */
5019 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5021 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5022 fname, (unsigned int)dosmode ));
5024 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5025 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5026 fname, strerror(errno)));
5027 return map_nt_error_from_unix(errno);
5030 return NT_STATUS_OK;
5033 /****************************************************************************
5034 Deal with setting the size from any of the setfilepathinfo functions.
5035 ****************************************************************************/
5037 static NTSTATUS smb_set_file_size(connection_struct *conn,
5038 struct smb_request *req,
5039 files_struct *fsp,
5040 const char *fname,
5041 SMB_STRUCT_STAT *psbuf,
5042 SMB_OFF_T size)
5044 NTSTATUS status = NT_STATUS_OK;
5045 files_struct *new_fsp = NULL;
5047 if (!VALID_STAT(*psbuf)) {
5048 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5051 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5053 if (size == get_file_size_stat(psbuf)) {
5054 return NT_STATUS_OK;
5057 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5058 fname, (double)size ));
5060 if (fsp && fsp->fh->fd != -1) {
5061 /* Handle based call. */
5062 if (vfs_set_filelen(fsp, size) == -1) {
5063 return map_nt_error_from_unix(errno);
5065 trigger_write_time_update_immediate(fsp);
5066 return NT_STATUS_OK;
5069 status = SMB_VFS_CREATE_FILE(
5070 conn, /* conn */
5071 req, /* req */
5072 0, /* root_dir_fid */
5073 fname, /* fname */
5074 0, /* create_file_flags */
5075 FILE_WRITE_ATTRIBUTES, /* access_mask */
5076 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5077 FILE_SHARE_DELETE),
5078 FILE_OPEN, /* create_disposition*/
5079 0, /* create_options */
5080 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5081 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5082 0, /* allocation_size */
5083 NULL, /* sd */
5084 NULL, /* ea_list */
5085 &new_fsp, /* result */
5086 NULL, /* pinfo */
5087 psbuf); /* psbuf */
5089 if (!NT_STATUS_IS_OK(status)) {
5090 /* NB. We check for open_was_deferred in the caller. */
5091 return status;
5094 if (vfs_set_filelen(new_fsp, size) == -1) {
5095 status = map_nt_error_from_unix(errno);
5096 close_file(req, new_fsp,NORMAL_CLOSE);
5097 return status;
5100 trigger_write_time_update_immediate(new_fsp);
5101 close_file(req, new_fsp,NORMAL_CLOSE);
5102 return NT_STATUS_OK;
5105 /****************************************************************************
5106 Deal with SMB_INFO_SET_EA.
5107 ****************************************************************************/
5109 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5110 const char *pdata,
5111 int total_data,
5112 files_struct *fsp,
5113 const char *fname)
5115 struct ea_list *ea_list = NULL;
5116 TALLOC_CTX *ctx = NULL;
5117 NTSTATUS status = NT_STATUS_OK;
5119 if (total_data < 10) {
5121 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5122 length. They seem to have no effect. Bug #3212. JRA */
5124 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5125 /* We're done. We only get EA info in this call. */
5126 return NT_STATUS_OK;
5129 return NT_STATUS_INVALID_PARAMETER;
5132 if (IVAL(pdata,0) > total_data) {
5133 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5134 IVAL(pdata,0), (unsigned int)total_data));
5135 return NT_STATUS_INVALID_PARAMETER;
5138 ctx = talloc_tos();
5139 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5140 if (!ea_list) {
5141 return NT_STATUS_INVALID_PARAMETER;
5143 status = set_ea(conn, fsp, fname, ea_list);
5145 return status;
5148 /****************************************************************************
5149 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5150 ****************************************************************************/
5152 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5153 const char *pdata,
5154 int total_data,
5155 files_struct *fsp,
5156 const char *fname,
5157 SMB_STRUCT_STAT *psbuf)
5159 NTSTATUS status = NT_STATUS_OK;
5160 bool delete_on_close;
5161 uint32 dosmode = 0;
5163 if (total_data < 1) {
5164 return NT_STATUS_INVALID_PARAMETER;
5167 if (fsp == NULL) {
5168 return NT_STATUS_INVALID_HANDLE;
5171 delete_on_close = (CVAL(pdata,0) ? True : False);
5172 dosmode = dos_mode(conn, fname, psbuf);
5174 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5175 "delete_on_close = %u\n",
5176 fsp->fsp_name,
5177 (unsigned int)dosmode,
5178 (unsigned int)delete_on_close ));
5180 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5182 if (!NT_STATUS_IS_OK(status)) {
5183 return status;
5186 /* The set is across all open files on this dev/inode pair. */
5187 if (!set_delete_on_close(fsp, delete_on_close,
5188 &conn->server_info->utok)) {
5189 return NT_STATUS_ACCESS_DENIED;
5191 return NT_STATUS_OK;
5194 /****************************************************************************
5195 Deal with SMB_FILE_POSITION_INFORMATION.
5196 ****************************************************************************/
5198 static NTSTATUS smb_file_position_information(connection_struct *conn,
5199 const char *pdata,
5200 int total_data,
5201 files_struct *fsp)
5203 uint64_t position_information;
5205 if (total_data < 8) {
5206 return NT_STATUS_INVALID_PARAMETER;
5209 if (fsp == NULL) {
5210 /* Ignore on pathname based set. */
5211 return NT_STATUS_OK;
5214 position_information = (uint64_t)IVAL(pdata,0);
5215 #ifdef LARGE_SMB_OFF_T
5216 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5217 #else /* LARGE_SMB_OFF_T */
5218 if (IVAL(pdata,4) != 0) {
5219 /* more than 32 bits? */
5220 return NT_STATUS_INVALID_PARAMETER;
5222 #endif /* LARGE_SMB_OFF_T */
5224 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5225 fsp->fsp_name, (double)position_information ));
5226 fsp->fh->position_information = position_information;
5227 return NT_STATUS_OK;
5230 /****************************************************************************
5231 Deal with SMB_FILE_MODE_INFORMATION.
5232 ****************************************************************************/
5234 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5235 const char *pdata,
5236 int total_data)
5238 uint32 mode;
5240 if (total_data < 4) {
5241 return NT_STATUS_INVALID_PARAMETER;
5243 mode = IVAL(pdata,0);
5244 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5245 return NT_STATUS_INVALID_PARAMETER;
5247 return NT_STATUS_OK;
5250 /****************************************************************************
5251 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5252 ****************************************************************************/
5254 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5255 struct smb_request *req,
5256 const char *pdata,
5257 int total_data,
5258 const char *fname)
5260 char *link_target = NULL;
5261 const char *newname = fname;
5262 NTSTATUS status = NT_STATUS_OK;
5263 TALLOC_CTX *ctx = talloc_tos();
5265 /* Set a symbolic link. */
5266 /* Don't allow this if follow links is false. */
5268 if (total_data == 0) {
5269 return NT_STATUS_INVALID_PARAMETER;
5272 if (!lp_symlinks(SNUM(conn))) {
5273 return NT_STATUS_ACCESS_DENIED;
5276 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5277 total_data, STR_TERMINATE);
5279 if (!link_target) {
5280 return NT_STATUS_INVALID_PARAMETER;
5283 /* !widelinks forces the target path to be within the share. */
5284 /* This means we can interpret the target as a pathname. */
5285 if (!lp_widelinks(SNUM(conn))) {
5286 char *rel_name = NULL;
5287 char *last_dirp = NULL;
5289 if (*link_target == '/') {
5290 /* No absolute paths allowed. */
5291 return NT_STATUS_ACCESS_DENIED;
5293 rel_name = talloc_strdup(ctx,newname);
5294 if (!rel_name) {
5295 return NT_STATUS_NO_MEMORY;
5297 last_dirp = strrchr_m(rel_name, '/');
5298 if (last_dirp) {
5299 last_dirp[1] = '\0';
5300 } else {
5301 rel_name = talloc_strdup(ctx,"./");
5302 if (!rel_name) {
5303 return NT_STATUS_NO_MEMORY;
5306 rel_name = talloc_asprintf_append(rel_name,
5307 "%s",
5308 link_target);
5309 if (!rel_name) {
5310 return NT_STATUS_NO_MEMORY;
5313 status = check_name(conn, rel_name);
5314 if (!NT_STATUS_IS_OK(status)) {
5315 return status;
5319 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5320 newname, link_target ));
5322 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5323 return map_nt_error_from_unix(errno);
5326 return NT_STATUS_OK;
5329 /****************************************************************************
5330 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5331 ****************************************************************************/
5333 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5334 struct smb_request *req,
5335 const char *pdata, int total_data,
5336 const char *fname)
5338 char *oldname = NULL;
5339 TALLOC_CTX *ctx = talloc_tos();
5340 NTSTATUS status = NT_STATUS_OK;
5342 /* Set a hard link. */
5343 if (total_data == 0) {
5344 return NT_STATUS_INVALID_PARAMETER;
5347 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5348 total_data, STR_TERMINATE, &status);
5349 if (!NT_STATUS_IS_OK(status)) {
5350 return status;
5353 status = resolve_dfspath(ctx, conn,
5354 req->flags2 & FLAGS2_DFS_PATHNAMES,
5355 oldname,
5356 &oldname);
5357 if (!NT_STATUS_IS_OK(status)) {
5358 return status;
5361 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5362 fname, oldname));
5364 return hardlink_internals(ctx, conn, oldname, fname);
5367 /****************************************************************************
5368 Deal with SMB_FILE_RENAME_INFORMATION.
5369 ****************************************************************************/
5371 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5372 struct smb_request *req,
5373 const char *pdata,
5374 int total_data,
5375 files_struct *fsp,
5376 const char *fname)
5378 bool overwrite;
5379 uint32 root_fid;
5380 uint32 len;
5381 char *newname = NULL;
5382 char *base_name = NULL;
5383 bool dest_has_wcard = False;
5384 SMB_STRUCT_STAT sbuf;
5385 char *newname_last_component = NULL;
5386 NTSTATUS status = NT_STATUS_OK;
5387 char *p;
5388 TALLOC_CTX *ctx = talloc_tos();
5390 if (total_data < 13) {
5391 return NT_STATUS_INVALID_PARAMETER;
5394 ZERO_STRUCT(sbuf);
5396 overwrite = (CVAL(pdata,0) ? True : False);
5397 root_fid = IVAL(pdata,4);
5398 len = IVAL(pdata,8);
5400 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5401 return NT_STATUS_INVALID_PARAMETER;
5404 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5405 len, 0, &status,
5406 &dest_has_wcard);
5407 if (!NT_STATUS_IS_OK(status)) {
5408 return status;
5411 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5412 newname));
5414 status = resolve_dfspath_wcard(ctx, conn,
5415 req->flags2 & FLAGS2_DFS_PATHNAMES,
5416 newname,
5417 &newname,
5418 &dest_has_wcard);
5419 if (!NT_STATUS_IS_OK(status)) {
5420 return status;
5423 /* Check the new name has no '/' characters. */
5424 if (strchr_m(newname, '/')) {
5425 return NT_STATUS_NOT_SUPPORTED;
5428 if (fsp && fsp->base_fsp) {
5429 /* newname must be a stream name. */
5430 if (newname[0] != ':') {
5431 return NT_STATUS_NOT_SUPPORTED;
5433 base_name = talloc_asprintf(ctx, "%s%s",
5434 fsp->base_fsp->fsp_name,
5435 newname);
5436 if (!base_name) {
5437 return NT_STATUS_NO_MEMORY;
5439 } else {
5440 /* newname must *not* be a stream name. */
5441 if (is_ntfs_stream_name(newname)) {
5442 return NT_STATUS_NOT_SUPPORTED;
5445 /* Create the base directory. */
5446 base_name = talloc_strdup(ctx, fname);
5447 if (!base_name) {
5448 return NT_STATUS_NO_MEMORY;
5450 p = strrchr_m(base_name, '/');
5451 if (p) {
5452 p[1] = '\0';
5453 } else {
5454 base_name = talloc_strdup(ctx, "./");
5455 if (!base_name) {
5456 return NT_STATUS_NO_MEMORY;
5459 /* Append the new name. */
5460 base_name = talloc_asprintf_append(base_name,
5461 "%s",
5462 newname);
5463 if (!base_name) {
5464 return NT_STATUS_NO_MEMORY;
5467 status = unix_convert(ctx, conn, newname, False,
5468 &newname,
5469 &newname_last_component,
5470 &sbuf);
5472 /* If an error we expect this to be
5473 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5475 if (!NT_STATUS_IS_OK(status)
5476 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5477 status)) {
5478 return status;
5482 if (fsp) {
5483 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5484 fsp->fnum, fsp->fsp_name, base_name ));
5485 status = rename_internals_fsp(conn, fsp, base_name,
5486 newname_last_component, 0,
5487 overwrite);
5488 } else {
5489 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5490 fname, base_name ));
5491 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5492 overwrite, False, dest_has_wcard,
5493 FILE_WRITE_ATTRIBUTES);
5496 return status;
5499 /****************************************************************************
5500 Deal with SMB_SET_POSIX_ACL.
5501 ****************************************************************************/
5503 #if defined(HAVE_POSIX_ACLS)
5504 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5505 const char *pdata,
5506 int total_data,
5507 files_struct *fsp,
5508 const char *fname,
5509 SMB_STRUCT_STAT *psbuf)
5511 uint16 posix_acl_version;
5512 uint16 num_file_acls;
5513 uint16 num_def_acls;
5514 bool valid_file_acls = True;
5515 bool valid_def_acls = True;
5517 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5518 return NT_STATUS_INVALID_PARAMETER;
5520 posix_acl_version = SVAL(pdata,0);
5521 num_file_acls = SVAL(pdata,2);
5522 num_def_acls = SVAL(pdata,4);
5524 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5525 valid_file_acls = False;
5526 num_file_acls = 0;
5529 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5530 valid_def_acls = False;
5531 num_def_acls = 0;
5534 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5535 return NT_STATUS_INVALID_PARAMETER;
5538 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5539 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5540 return NT_STATUS_INVALID_PARAMETER;
5543 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5544 fname ? fname : fsp->fsp_name,
5545 (unsigned int)num_file_acls,
5546 (unsigned int)num_def_acls));
5548 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5549 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5550 return map_nt_error_from_unix(errno);
5553 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5554 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5555 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5556 return map_nt_error_from_unix(errno);
5558 return NT_STATUS_OK;
5560 #endif
5562 /****************************************************************************
5563 Deal with SMB_SET_POSIX_LOCK.
5564 ****************************************************************************/
5566 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5567 struct smb_request *req,
5568 const char *pdata,
5569 int total_data,
5570 files_struct *fsp)
5572 uint64_t count;
5573 uint64_t offset;
5574 uint32 lock_pid;
5575 bool blocking_lock = False;
5576 enum brl_type lock_type;
5578 NTSTATUS status = NT_STATUS_OK;
5580 if (fsp == NULL || fsp->fh->fd == -1) {
5581 return NT_STATUS_INVALID_HANDLE;
5584 if (total_data != POSIX_LOCK_DATA_SIZE) {
5585 return NT_STATUS_INVALID_PARAMETER;
5588 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5589 case POSIX_LOCK_TYPE_READ:
5590 lock_type = READ_LOCK;
5591 break;
5592 case POSIX_LOCK_TYPE_WRITE:
5593 /* Return the right POSIX-mappable error code for files opened read-only. */
5594 if (!fsp->can_write) {
5595 return NT_STATUS_INVALID_HANDLE;
5597 lock_type = WRITE_LOCK;
5598 break;
5599 case POSIX_LOCK_TYPE_UNLOCK:
5600 lock_type = UNLOCK_LOCK;
5601 break;
5602 default:
5603 return NT_STATUS_INVALID_PARAMETER;
5606 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5607 blocking_lock = False;
5608 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5609 blocking_lock = True;
5610 } else {
5611 return NT_STATUS_INVALID_PARAMETER;
5614 if (!lp_blocking_locks(SNUM(conn))) {
5615 blocking_lock = False;
5618 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5619 #if defined(HAVE_LONGLONG)
5620 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5621 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5622 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5623 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5624 #else /* HAVE_LONGLONG */
5625 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5626 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5627 #endif /* HAVE_LONGLONG */
5629 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5630 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5631 fsp->fsp_name,
5632 (unsigned int)lock_type,
5633 (unsigned int)lock_pid,
5634 (double)count,
5635 (double)offset ));
5637 if (lock_type == UNLOCK_LOCK) {
5638 status = do_unlock(smbd_messaging_context(),
5639 fsp,
5640 lock_pid,
5641 count,
5642 offset,
5643 POSIX_LOCK);
5644 } else {
5645 uint32 block_smbpid;
5647 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5648 fsp,
5649 lock_pid,
5650 count,
5651 offset,
5652 lock_type,
5653 POSIX_LOCK,
5654 blocking_lock,
5655 &status,
5656 &block_smbpid,
5657 NULL);
5659 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5661 * A blocking lock was requested. Package up
5662 * this smb into a queued request and push it
5663 * onto the blocking lock queue.
5665 if(push_blocking_lock_request(br_lck,
5666 req,
5667 fsp,
5668 -1, /* infinite timeout. */
5670 lock_pid,
5671 lock_type,
5672 POSIX_LOCK,
5673 offset,
5674 count,
5675 block_smbpid)) {
5676 TALLOC_FREE(br_lck);
5677 return status;
5680 TALLOC_FREE(br_lck);
5683 return status;
5686 /****************************************************************************
5687 Deal with SMB_INFO_STANDARD.
5688 ****************************************************************************/
5690 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5691 const char *pdata,
5692 int total_data,
5693 files_struct *fsp,
5694 const char *fname,
5695 const SMB_STRUCT_STAT *psbuf)
5697 struct smb_file_time ft;
5698 ZERO_STRUCT(ft);
5700 if (total_data < 12) {
5701 return NT_STATUS_INVALID_PARAMETER;
5704 /* create time */
5705 ft.create_time = interpret_long_date(pdata);
5707 /* access time */
5708 ft.atime = interpret_long_date(pdata + 8);
5710 /* write time */
5711 ft.mtime = interpret_long_date(pdata + 16);
5713 DEBUG(10,("smb_set_info_standard: file %s\n",
5714 fname ? fname : fsp->fsp_name ));
5716 return smb_set_file_time(conn,
5717 fsp,
5718 fname,
5719 psbuf,
5720 &ft,
5721 true);
5724 /****************************************************************************
5725 Deal with SMB_SET_FILE_BASIC_INFO.
5726 ****************************************************************************/
5728 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5729 const char *pdata,
5730 int total_data,
5731 files_struct *fsp,
5732 const char *fname,
5733 SMB_STRUCT_STAT *psbuf)
5735 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5736 struct timespec write_time;
5737 struct timespec changed_time;
5738 struct smb_file_time ft;
5739 uint32 dosmode = 0;
5740 NTSTATUS status = NT_STATUS_OK;
5741 bool setting_write_time = true;
5743 ZERO_STRUCT(ft);
5745 if (total_data < 36) {
5746 return NT_STATUS_INVALID_PARAMETER;
5749 /* Set the attributes */
5750 dosmode = IVAL(pdata,32);
5751 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5752 if (!NT_STATUS_IS_OK(status)) {
5753 return status;
5756 /* access time */
5757 ft.atime = interpret_long_date(pdata+8);
5759 write_time = interpret_long_date(pdata+16);
5760 changed_time = interpret_long_date(pdata+24);
5762 /* mtime */
5763 ft.mtime = timespec_min(&write_time, &changed_time);
5765 /* create time */
5766 ft.create_time = interpret_long_date(pdata);
5768 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5769 !null_timespec(write_time)) {
5770 ft.mtime = write_time;
5773 /* Prefer a defined time to an undefined one. */
5774 if (null_timespec(ft.mtime)) {
5775 if (null_timespec(write_time)) {
5776 ft.mtime = changed_time;
5777 setting_write_time = false;
5778 } else {
5779 ft.mtime = write_time;
5783 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5784 fname ? fname : fsp->fsp_name ));
5786 return smb_set_file_time(conn,
5787 fsp,
5788 fname,
5789 psbuf,
5790 &ft,
5791 setting_write_time);
5794 /****************************************************************************
5795 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5796 ****************************************************************************/
5798 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5799 struct smb_request *req,
5800 const char *pdata,
5801 int total_data,
5802 files_struct *fsp,
5803 const char *fname,
5804 SMB_STRUCT_STAT *psbuf)
5806 uint64_t allocation_size = 0;
5807 NTSTATUS status = NT_STATUS_OK;
5808 files_struct *new_fsp = NULL;
5810 if (!VALID_STAT(*psbuf)) {
5811 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5814 if (total_data < 8) {
5815 return NT_STATUS_INVALID_PARAMETER;
5818 allocation_size = (uint64_t)IVAL(pdata,0);
5819 #ifdef LARGE_SMB_OFF_T
5820 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5821 #else /* LARGE_SMB_OFF_T */
5822 if (IVAL(pdata,4) != 0) {
5823 /* more than 32 bits? */
5824 return NT_STATUS_INVALID_PARAMETER;
5826 #endif /* LARGE_SMB_OFF_T */
5828 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5829 fname, (double)allocation_size ));
5831 if (allocation_size) {
5832 allocation_size = smb_roundup(conn, allocation_size);
5835 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5836 fname, (double)allocation_size ));
5838 if (fsp && fsp->fh->fd != -1) {
5839 /* Open file handle. */
5840 /* Only change if needed. */
5841 if (allocation_size != get_file_size_stat(psbuf)) {
5842 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5843 return map_nt_error_from_unix(errno);
5846 /* But always update the time. */
5848 * This is equivalent to a write. Ensure it's seen immediately
5849 * if there are no pending writes.
5851 trigger_write_time_update_immediate(fsp);
5852 return NT_STATUS_OK;
5855 /* Pathname or stat or directory file. */
5857 status = SMB_VFS_CREATE_FILE(
5858 conn, /* conn */
5859 req, /* req */
5860 0, /* root_dir_fid */
5861 fname, /* fname */
5862 0, /* create_file_flags */
5863 FILE_WRITE_DATA, /* access_mask */
5864 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5865 FILE_SHARE_DELETE),
5866 FILE_OPEN, /* create_disposition*/
5867 0, /* create_options */
5868 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5869 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5870 0, /* allocation_size */
5871 NULL, /* sd */
5872 NULL, /* ea_list */
5873 &new_fsp, /* result */
5874 NULL, /* pinfo */
5875 psbuf); /* psbuf */
5877 if (!NT_STATUS_IS_OK(status)) {
5878 /* NB. We check for open_was_deferred in the caller. */
5879 return status;
5882 /* Only change if needed. */
5883 if (allocation_size != get_file_size_stat(psbuf)) {
5884 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5885 status = map_nt_error_from_unix(errno);
5886 close_file(req, new_fsp, NORMAL_CLOSE);
5887 return status;
5891 /* Changing the allocation size should set the last mod time. */
5893 * This is equivalent to a write. Ensure it's seen immediately
5894 * if there are no pending writes.
5896 trigger_write_time_update_immediate(new_fsp);
5898 close_file(req, new_fsp, NORMAL_CLOSE);
5899 return NT_STATUS_OK;
5902 /****************************************************************************
5903 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5904 ****************************************************************************/
5906 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5907 struct smb_request *req,
5908 const char *pdata,
5909 int total_data,
5910 files_struct *fsp,
5911 const char *fname,
5912 SMB_STRUCT_STAT *psbuf)
5914 SMB_OFF_T size;
5916 if (total_data < 8) {
5917 return NT_STATUS_INVALID_PARAMETER;
5920 size = IVAL(pdata,0);
5921 #ifdef LARGE_SMB_OFF_T
5922 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5923 #else /* LARGE_SMB_OFF_T */
5924 if (IVAL(pdata,4) != 0) {
5925 /* more than 32 bits? */
5926 return NT_STATUS_INVALID_PARAMETER;
5928 #endif /* LARGE_SMB_OFF_T */
5929 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5930 "file %s to %.0f\n", fname, (double)size ));
5932 return smb_set_file_size(conn, req,
5933 fsp,
5934 fname,
5935 psbuf,
5936 size);
5939 /****************************************************************************
5940 Allow a UNIX info mknod.
5941 ****************************************************************************/
5943 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5944 const char *pdata,
5945 int total_data,
5946 const char *fname,
5947 SMB_STRUCT_STAT *psbuf)
5949 uint32 file_type = IVAL(pdata,56);
5950 #if defined(HAVE_MAKEDEV)
5951 uint32 dev_major = IVAL(pdata,60);
5952 uint32 dev_minor = IVAL(pdata,68);
5953 #endif
5954 SMB_DEV_T dev = (SMB_DEV_T)0;
5955 uint32 raw_unixmode = IVAL(pdata,84);
5956 NTSTATUS status;
5957 mode_t unixmode;
5959 if (total_data < 100) {
5960 return NT_STATUS_INVALID_PARAMETER;
5963 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5964 if (!NT_STATUS_IS_OK(status)) {
5965 return status;
5968 #if defined(HAVE_MAKEDEV)
5969 dev = makedev(dev_major, dev_minor);
5970 #endif
5972 switch (file_type) {
5973 #if defined(S_IFIFO)
5974 case UNIX_TYPE_FIFO:
5975 unixmode |= S_IFIFO;
5976 break;
5977 #endif
5978 #if defined(S_IFSOCK)
5979 case UNIX_TYPE_SOCKET:
5980 unixmode |= S_IFSOCK;
5981 break;
5982 #endif
5983 #if defined(S_IFCHR)
5984 case UNIX_TYPE_CHARDEV:
5985 unixmode |= S_IFCHR;
5986 break;
5987 #endif
5988 #if defined(S_IFBLK)
5989 case UNIX_TYPE_BLKDEV:
5990 unixmode |= S_IFBLK;
5991 break;
5992 #endif
5993 default:
5994 return NT_STATUS_INVALID_PARAMETER;
5997 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5998 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
6000 /* Ok - do the mknod. */
6001 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
6002 return map_nt_error_from_unix(errno);
6005 /* If any of the other "set" calls fail we
6006 * don't want to end up with a half-constructed mknod.
6009 if (lp_inherit_perms(SNUM(conn))) {
6010 char *parent;
6011 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
6012 return NT_STATUS_NO_MEMORY;
6014 inherit_access_posix_acl(conn, parent, fname, unixmode);
6015 TALLOC_FREE(parent);
6018 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
6019 status = map_nt_error_from_unix(errno);
6020 SMB_VFS_UNLINK(conn,fname);
6021 return status;
6023 return NT_STATUS_OK;
6026 /****************************************************************************
6027 Deal with SMB_SET_FILE_UNIX_BASIC.
6028 ****************************************************************************/
6030 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6031 struct smb_request *req,
6032 const char *pdata,
6033 int total_data,
6034 files_struct *fsp,
6035 const char *fname,
6036 SMB_STRUCT_STAT *psbuf)
6038 struct smb_file_time ft;
6039 uint32 raw_unixmode;
6040 mode_t unixmode;
6041 SMB_OFF_T size = 0;
6042 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6043 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6044 NTSTATUS status = NT_STATUS_OK;
6045 bool delete_on_fail = False;
6046 enum perm_type ptype;
6048 ZERO_STRUCT(ft);
6050 if (total_data < 100) {
6051 return NT_STATUS_INVALID_PARAMETER;
6054 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6055 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6056 size=IVAL(pdata,0); /* first 8 Bytes are size */
6057 #ifdef LARGE_SMB_OFF_T
6058 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6059 #else /* LARGE_SMB_OFF_T */
6060 if (IVAL(pdata,4) != 0) {
6061 /* more than 32 bits? */
6062 return NT_STATUS_INVALID_PARAMETER;
6064 #endif /* LARGE_SMB_OFF_T */
6067 ft.atime = interpret_long_date(pdata+24); /* access_time */
6068 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6069 set_owner = (uid_t)IVAL(pdata,40);
6070 set_grp = (gid_t)IVAL(pdata,48);
6071 raw_unixmode = IVAL(pdata,84);
6073 if (VALID_STAT(*psbuf)) {
6074 if (S_ISDIR(psbuf->st_mode)) {
6075 ptype = PERM_EXISTING_DIR;
6076 } else {
6077 ptype = PERM_EXISTING_FILE;
6079 } else {
6080 ptype = PERM_NEW_FILE;
6083 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6084 if (!NT_STATUS_IS_OK(status)) {
6085 return status;
6088 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6089 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6090 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6092 if (!VALID_STAT(*psbuf)) {
6094 * The only valid use of this is to create character and block
6095 * devices, and named pipes. This is deprecated (IMHO) and
6096 * a new info level should be used for mknod. JRA.
6099 status = smb_unix_mknod(conn,
6100 pdata,
6101 total_data,
6102 fname,
6103 psbuf);
6104 if (!NT_STATUS_IS_OK(status)) {
6105 return status;
6108 /* Ensure we don't try and change anything else. */
6109 raw_unixmode = SMB_MODE_NO_CHANGE;
6110 size = get_file_size_stat(psbuf);
6111 ft.atime = get_atimespec(psbuf);
6112 ft.mtime = get_mtimespec(psbuf);
6114 * We continue here as we might want to change the
6115 * owner uid/gid.
6117 delete_on_fail = True;
6120 #if 1
6121 /* Horrible backwards compatibility hack as an old server bug
6122 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6123 * */
6125 if (!size) {
6126 size = get_file_size_stat(psbuf);
6128 #endif
6131 * Deal with the UNIX specific mode set.
6134 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6135 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6136 (unsigned int)unixmode, fname ));
6137 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6138 return map_nt_error_from_unix(errno);
6143 * Deal with the UNIX specific uid set.
6146 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6147 int ret;
6149 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6150 (unsigned int)set_owner, fname ));
6152 if (S_ISLNK(psbuf->st_mode)) {
6153 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6154 } else {
6155 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6158 if (ret != 0) {
6159 status = map_nt_error_from_unix(errno);
6160 if (delete_on_fail) {
6161 SMB_VFS_UNLINK(conn,fname);
6163 return status;
6168 * Deal with the UNIX specific gid set.
6171 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6172 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6173 (unsigned int)set_owner, fname ));
6174 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6175 status = map_nt_error_from_unix(errno);
6176 if (delete_on_fail) {
6177 SMB_VFS_UNLINK(conn,fname);
6179 return status;
6183 /* Deal with any size changes. */
6185 status = smb_set_file_size(conn, req,
6186 fsp,
6187 fname,
6188 psbuf,
6189 size);
6190 if (!NT_STATUS_IS_OK(status)) {
6191 return status;
6194 /* Deal with any time changes. */
6196 return smb_set_file_time(conn,
6197 fsp,
6198 fname,
6199 psbuf,
6200 &ft,
6201 true);
6204 /****************************************************************************
6205 Deal with SMB_SET_FILE_UNIX_INFO2.
6206 ****************************************************************************/
6208 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6209 struct smb_request *req,
6210 const char *pdata,
6211 int total_data,
6212 files_struct *fsp,
6213 const char *fname,
6214 SMB_STRUCT_STAT *psbuf)
6216 NTSTATUS status;
6217 uint32 smb_fflags;
6218 uint32 smb_fmask;
6220 if (total_data < 116) {
6221 return NT_STATUS_INVALID_PARAMETER;
6224 /* Start by setting all the fields that are common between UNIX_BASIC
6225 * and UNIX_INFO2.
6227 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6228 fsp, fname, psbuf);
6229 if (!NT_STATUS_IS_OK(status)) {
6230 return status;
6233 smb_fflags = IVAL(pdata, 108);
6234 smb_fmask = IVAL(pdata, 112);
6236 /* NB: We should only attempt to alter the file flags if the client
6237 * sends a non-zero mask.
6239 if (smb_fmask != 0) {
6240 int stat_fflags = 0;
6242 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6243 &stat_fflags)) {
6244 /* Client asked to alter a flag we don't understand. */
6245 return NT_STATUS_INVALID_PARAMETER;
6248 if (fsp && fsp->fh->fd != -1) {
6249 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6250 return NT_STATUS_NOT_SUPPORTED;
6251 } else {
6252 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6253 return map_nt_error_from_unix(errno);
6258 /* XXX: need to add support for changing the create_time here. You
6259 * can do this for paths on Darwin with setattrlist(2). The right way
6260 * to hook this up is probably by extending the VFS utimes interface.
6263 return NT_STATUS_OK;
6266 /****************************************************************************
6267 Create a directory with POSIX semantics.
6268 ****************************************************************************/
6270 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6271 struct smb_request *req,
6272 char **ppdata,
6273 int total_data,
6274 const char *fname,
6275 SMB_STRUCT_STAT *psbuf,
6276 int *pdata_return_size)
6278 NTSTATUS status = NT_STATUS_OK;
6279 uint32 raw_unixmode = 0;
6280 uint32 mod_unixmode = 0;
6281 mode_t unixmode = (mode_t)0;
6282 files_struct *fsp = NULL;
6283 uint16 info_level_return = 0;
6284 int info;
6285 char *pdata = *ppdata;
6287 if (total_data < 18) {
6288 return NT_STATUS_INVALID_PARAMETER;
6291 raw_unixmode = IVAL(pdata,8);
6292 /* Next 4 bytes are not yet defined. */
6294 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6295 if (!NT_STATUS_IS_OK(status)) {
6296 return status;
6299 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6301 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6302 fname, (unsigned int)unixmode ));
6304 status = SMB_VFS_CREATE_FILE(
6305 conn, /* conn */
6306 req, /* req */
6307 0, /* root_dir_fid */
6308 fname, /* fname */
6309 0, /* create_file_flags */
6310 FILE_READ_ATTRIBUTES, /* access_mask */
6311 FILE_SHARE_NONE, /* share_access */
6312 FILE_CREATE, /* create_disposition*/
6313 FILE_DIRECTORY_FILE, /* create_options */
6314 mod_unixmode, /* file_attributes */
6315 0, /* oplock_request */
6316 0, /* allocation_size */
6317 NULL, /* sd */
6318 NULL, /* ea_list */
6319 &fsp, /* result */
6320 &info, /* pinfo */
6321 psbuf); /* psbuf */
6323 if (NT_STATUS_IS_OK(status)) {
6324 close_file(req, fsp, NORMAL_CLOSE);
6327 info_level_return = SVAL(pdata,16);
6329 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6330 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6331 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6332 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6333 } else {
6334 *pdata_return_size = 12;
6337 /* Realloc the data size */
6338 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6339 if (*ppdata == NULL) {
6340 *pdata_return_size = 0;
6341 return NT_STATUS_NO_MEMORY;
6343 pdata = *ppdata;
6345 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6346 SSVAL(pdata,2,0); /* No fnum. */
6347 SIVAL(pdata,4,info); /* Was directory created. */
6349 switch (info_level_return) {
6350 case SMB_QUERY_FILE_UNIX_BASIC:
6351 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6352 SSVAL(pdata,10,0); /* Padding. */
6353 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6354 break;
6355 case SMB_QUERY_FILE_UNIX_INFO2:
6356 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6357 SSVAL(pdata,10,0); /* Padding. */
6358 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6359 break;
6360 default:
6361 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6362 SSVAL(pdata,10,0); /* Padding. */
6363 break;
6366 return status;
6369 /****************************************************************************
6370 Open/Create a file with POSIX semantics.
6371 ****************************************************************************/
6373 static NTSTATUS smb_posix_open(connection_struct *conn,
6374 struct smb_request *req,
6375 char **ppdata,
6376 int total_data,
6377 const char *fname,
6378 SMB_STRUCT_STAT *psbuf,
6379 int *pdata_return_size)
6381 bool extended_oplock_granted = False;
6382 char *pdata = *ppdata;
6383 uint32 flags = 0;
6384 uint32 wire_open_mode = 0;
6385 uint32 raw_unixmode = 0;
6386 uint32 mod_unixmode = 0;
6387 uint32 create_disp = 0;
6388 uint32 access_mask = 0;
6389 uint32 create_options = 0;
6390 NTSTATUS status = NT_STATUS_OK;
6391 mode_t unixmode = (mode_t)0;
6392 files_struct *fsp = NULL;
6393 int oplock_request = 0;
6394 int info = 0;
6395 uint16 info_level_return = 0;
6397 if (total_data < 18) {
6398 return NT_STATUS_INVALID_PARAMETER;
6401 flags = IVAL(pdata,0);
6402 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6403 if (oplock_request) {
6404 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6407 wire_open_mode = IVAL(pdata,4);
6409 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6410 return smb_posix_mkdir(conn, req,
6411 ppdata,
6412 total_data,
6413 fname,
6414 psbuf,
6415 pdata_return_size);
6418 switch (wire_open_mode & SMB_ACCMODE) {
6419 case SMB_O_RDONLY:
6420 access_mask = FILE_READ_DATA;
6421 break;
6422 case SMB_O_WRONLY:
6423 access_mask = FILE_WRITE_DATA;
6424 break;
6425 case SMB_O_RDWR:
6426 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6427 break;
6428 default:
6429 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6430 (unsigned int)wire_open_mode ));
6431 return NT_STATUS_INVALID_PARAMETER;
6434 wire_open_mode &= ~SMB_ACCMODE;
6436 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6437 create_disp = FILE_CREATE;
6438 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6439 create_disp = FILE_OVERWRITE_IF;
6440 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6441 create_disp = FILE_OPEN_IF;
6442 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6443 create_disp = FILE_OPEN;
6444 } else {
6445 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6446 (unsigned int)wire_open_mode ));
6447 return NT_STATUS_INVALID_PARAMETER;
6450 raw_unixmode = IVAL(pdata,8);
6451 /* Next 4 bytes are not yet defined. */
6453 status = unix_perms_from_wire(conn,
6454 psbuf,
6455 raw_unixmode,
6456 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6457 &unixmode);
6459 if (!NT_STATUS_IS_OK(status)) {
6460 return status;
6463 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6465 if (wire_open_mode & SMB_O_SYNC) {
6466 create_options |= FILE_WRITE_THROUGH;
6468 if (wire_open_mode & SMB_O_APPEND) {
6469 access_mask |= FILE_APPEND_DATA;
6471 if (wire_open_mode & SMB_O_DIRECT) {
6472 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6475 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6476 fname,
6477 (unsigned int)wire_open_mode,
6478 (unsigned int)unixmode ));
6480 status = SMB_VFS_CREATE_FILE(
6481 conn, /* conn */
6482 req, /* req */
6483 0, /* root_dir_fid */
6484 fname, /* fname */
6485 0, /* create_file_flags */
6486 access_mask, /* access_mask */
6487 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6488 FILE_SHARE_DELETE),
6489 create_disp, /* create_disposition*/
6490 FILE_NON_DIRECTORY_FILE, /* create_options */
6491 mod_unixmode, /* file_attributes */
6492 oplock_request, /* oplock_request */
6493 0, /* allocation_size */
6494 NULL, /* sd */
6495 NULL, /* ea_list */
6496 &fsp, /* result */
6497 &info, /* pinfo */
6498 psbuf); /* psbuf */
6500 if (!NT_STATUS_IS_OK(status)) {
6501 return status;
6504 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6505 extended_oplock_granted = True;
6508 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6509 extended_oplock_granted = True;
6512 info_level_return = SVAL(pdata,16);
6514 /* Allocate the correct return size. */
6516 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6517 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6518 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6519 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6520 } else {
6521 *pdata_return_size = 12;
6524 /* Realloc the data size */
6525 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6526 if (*ppdata == NULL) {
6527 close_file(req, fsp, ERROR_CLOSE);
6528 *pdata_return_size = 0;
6529 return NT_STATUS_NO_MEMORY;
6531 pdata = *ppdata;
6533 if (extended_oplock_granted) {
6534 if (flags & REQUEST_BATCH_OPLOCK) {
6535 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6536 } else {
6537 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6539 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6540 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6541 } else {
6542 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6545 SSVAL(pdata,2,fsp->fnum);
6546 SIVAL(pdata,4,info); /* Was file created etc. */
6548 switch (info_level_return) {
6549 case SMB_QUERY_FILE_UNIX_BASIC:
6550 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6551 SSVAL(pdata,10,0); /* padding. */
6552 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6553 break;
6554 case SMB_QUERY_FILE_UNIX_INFO2:
6555 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6556 SSVAL(pdata,10,0); /* padding. */
6557 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6558 break;
6559 default:
6560 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6561 SSVAL(pdata,10,0); /* padding. */
6562 break;
6564 return NT_STATUS_OK;
6567 /****************************************************************************
6568 Delete a file with POSIX semantics.
6569 ****************************************************************************/
6571 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6572 struct smb_request *req,
6573 const char *pdata,
6574 int total_data,
6575 const char *fname,
6576 SMB_STRUCT_STAT *psbuf)
6578 NTSTATUS status = NT_STATUS_OK;
6579 files_struct *fsp = NULL;
6580 uint16 flags = 0;
6581 char del = 1;
6582 int info = 0;
6583 int create_options = 0;
6584 int i;
6585 struct share_mode_lock *lck = NULL;
6587 if (total_data < 2) {
6588 return NT_STATUS_INVALID_PARAMETER;
6591 flags = SVAL(pdata,0);
6593 if (!VALID_STAT(*psbuf)) {
6594 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6597 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6598 !VALID_STAT_OF_DIR(*psbuf)) {
6599 return NT_STATUS_NOT_A_DIRECTORY;
6602 DEBUG(10,("smb_posix_unlink: %s %s\n",
6603 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6604 fname));
6606 if (VALID_STAT_OF_DIR(*psbuf)) {
6607 create_options |= FILE_DIRECTORY_FILE;
6610 status = SMB_VFS_CREATE_FILE(
6611 conn, /* conn */
6612 req, /* req */
6613 0, /* root_dir_fid */
6614 fname, /* fname */
6615 0, /* create_file_flags */
6616 DELETE_ACCESS, /* access_mask */
6617 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6618 FILE_SHARE_DELETE),
6619 FILE_OPEN, /* create_disposition*/
6620 create_options, /* create_options */
6621 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6622 0, /* oplock_request */
6623 0, /* allocation_size */
6624 NULL, /* sd */
6625 NULL, /* ea_list */
6626 &fsp, /* result */
6627 &info, /* pinfo */
6628 psbuf); /* psbuf */
6630 if (!NT_STATUS_IS_OK(status)) {
6631 return status;
6635 * Don't lie to client. If we can't really delete due to
6636 * non-POSIX opens return SHARING_VIOLATION.
6639 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6640 NULL);
6641 if (lck == NULL) {
6642 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6643 "lock for file %s\n", fsp->fsp_name));
6644 close_file(req, fsp, NORMAL_CLOSE);
6645 return NT_STATUS_INVALID_PARAMETER;
6649 * See if others still have the file open. If this is the case, then
6650 * don't delete. If all opens are POSIX delete we can set the delete
6651 * on close disposition.
6653 for (i=0; i<lck->num_share_modes; i++) {
6654 struct share_mode_entry *e = &lck->share_modes[i];
6655 if (is_valid_share_mode_entry(e)) {
6656 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6657 continue;
6659 /* Fail with sharing violation. */
6660 close_file(req, fsp, NORMAL_CLOSE);
6661 TALLOC_FREE(lck);
6662 return NT_STATUS_SHARING_VIOLATION;
6667 * Set the delete on close.
6669 status = smb_set_file_disposition_info(conn,
6670 &del,
6672 fsp,
6673 fname,
6674 psbuf);
6676 if (!NT_STATUS_IS_OK(status)) {
6677 close_file(req, fsp, NORMAL_CLOSE);
6678 TALLOC_FREE(lck);
6679 return status;
6681 TALLOC_FREE(lck);
6682 return close_file(req, fsp, NORMAL_CLOSE);
6685 /****************************************************************************
6686 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6687 ****************************************************************************/
6689 static void call_trans2setfilepathinfo(connection_struct *conn,
6690 struct smb_request *req,
6691 unsigned int tran_call,
6692 char **pparams, int total_params,
6693 char **ppdata, int total_data,
6694 unsigned int max_data_bytes)
6696 char *params = *pparams;
6697 char *pdata = *ppdata;
6698 uint16 info_level;
6699 SMB_STRUCT_STAT sbuf;
6700 char *fname = NULL;
6701 files_struct *fsp = NULL;
6702 NTSTATUS status = NT_STATUS_OK;
6703 int data_return_size = 0;
6704 TALLOC_CTX *ctx = talloc_tos();
6706 if (!params) {
6707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6708 return;
6711 ZERO_STRUCT(sbuf);
6713 if (tran_call == TRANSACT2_SETFILEINFO) {
6714 if (total_params < 4) {
6715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6716 return;
6719 fsp = file_fsp(req, SVAL(params,0));
6720 /* Basic check for non-null fsp. */
6721 if (!check_fsp_open(conn, req, fsp)) {
6722 return;
6724 info_level = SVAL(params,2);
6726 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6727 if (!fname) {
6728 reply_nterror(req, NT_STATUS_NO_MEMORY);
6729 return;
6732 if(fsp->is_directory || fsp->fh->fd == -1) {
6734 * This is actually a SETFILEINFO on a directory
6735 * handle (returned from an NT SMB). NT5.0 seems
6736 * to do this call. JRA.
6738 if (INFO_LEVEL_IS_UNIX(info_level)) {
6739 /* Always do lstat for UNIX calls. */
6740 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6741 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6742 reply_unixerror(req,ERRDOS,ERRbadpath);
6743 return;
6745 } else {
6746 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6747 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6748 reply_unixerror(req,ERRDOS,ERRbadpath);
6749 return;
6752 } else if (fsp->print_file) {
6754 * Doing a DELETE_ON_CLOSE should cancel a print job.
6756 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6757 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6759 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6761 SSVAL(params,0,0);
6762 send_trans2_replies(conn, req, params, 2,
6763 *ppdata, 0,
6764 max_data_bytes);
6765 return;
6766 } else {
6767 reply_unixerror(req, ERRDOS, ERRbadpath);
6768 return;
6770 } else {
6772 * Original code - this is an open file.
6774 if (!check_fsp(conn, req, fsp)) {
6775 return;
6778 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6779 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6780 reply_unixerror(req, ERRDOS, ERRbadfid);
6781 return;
6784 } else {
6785 /* set path info */
6786 if (total_params < 7) {
6787 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6788 return;
6791 info_level = SVAL(params,0);
6792 srvstr_get_path(ctx, params, req->flags2, &fname, &params[6],
6793 total_params - 6, STR_TERMINATE,
6794 &status);
6795 if (!NT_STATUS_IS_OK(status)) {
6796 reply_nterror(req, status);
6797 return;
6800 status = resolve_dfspath(ctx, conn,
6801 req->flags2 & FLAGS2_DFS_PATHNAMES,
6802 fname,
6803 &fname);
6804 if (!NT_STATUS_IS_OK(status)) {
6805 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6806 reply_botherror(req,
6807 NT_STATUS_PATH_NOT_COVERED,
6808 ERRSRV, ERRbadpath);
6809 return;
6811 reply_nterror(req, status);
6812 return;
6815 status = unix_convert(ctx, conn, fname, False,
6816 &fname, NULL, &sbuf);
6817 if (!NT_STATUS_IS_OK(status)) {
6818 reply_nterror(req, status);
6819 return;
6822 status = check_name(conn, fname);
6823 if (!NT_STATUS_IS_OK(status)) {
6824 reply_nterror(req, status);
6825 return;
6828 if (INFO_LEVEL_IS_UNIX(info_level)) {
6830 * For CIFS UNIX extensions the target name may not exist.
6833 /* Always do lstat for UNIX calls. */
6834 SMB_VFS_LSTAT(conn,fname,&sbuf);
6836 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6837 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6838 reply_unixerror(req, ERRDOS, ERRbadpath);
6839 return;
6843 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6844 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6845 return;
6848 if (!CAN_WRITE(conn)) {
6849 /* Allow POSIX opens. The open path will deny
6850 * any non-readonly opens. */
6851 if (info_level != SMB_POSIX_PATH_OPEN) {
6852 reply_doserror(req, ERRSRV, ERRaccess);
6853 return;
6857 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6858 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6860 /* Realloc the parameter size */
6861 *pparams = (char *)SMB_REALLOC(*pparams,2);
6862 if (*pparams == NULL) {
6863 reply_nterror(req, NT_STATUS_NO_MEMORY);
6864 return;
6866 params = *pparams;
6868 SSVAL(params,0,0);
6870 switch (info_level) {
6872 case SMB_INFO_STANDARD:
6874 status = smb_set_info_standard(conn,
6875 pdata,
6876 total_data,
6877 fsp,
6878 fname,
6879 &sbuf);
6880 break;
6883 case SMB_INFO_SET_EA:
6885 status = smb_info_set_ea(conn,
6886 pdata,
6887 total_data,
6888 fsp,
6889 fname);
6890 break;
6893 case SMB_SET_FILE_BASIC_INFO:
6894 case SMB_FILE_BASIC_INFORMATION:
6896 status = smb_set_file_basic_info(conn,
6897 pdata,
6898 total_data,
6899 fsp,
6900 fname,
6901 &sbuf);
6902 break;
6905 case SMB_FILE_ALLOCATION_INFORMATION:
6906 case SMB_SET_FILE_ALLOCATION_INFO:
6908 status = smb_set_file_allocation_info(conn, req,
6909 pdata,
6910 total_data,
6911 fsp,
6912 fname,
6913 &sbuf);
6914 break;
6917 case SMB_FILE_END_OF_FILE_INFORMATION:
6918 case SMB_SET_FILE_END_OF_FILE_INFO:
6920 status = smb_set_file_end_of_file_info(conn, req,
6921 pdata,
6922 total_data,
6923 fsp,
6924 fname,
6925 &sbuf);
6926 break;
6929 case SMB_FILE_DISPOSITION_INFORMATION:
6930 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6932 #if 0
6933 /* JRA - We used to just ignore this on a path ?
6934 * Shouldn't this be invalid level on a pathname
6935 * based call ?
6937 if (tran_call != TRANSACT2_SETFILEINFO) {
6938 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6940 #endif
6941 status = smb_set_file_disposition_info(conn,
6942 pdata,
6943 total_data,
6944 fsp,
6945 fname,
6946 &sbuf);
6947 break;
6950 case SMB_FILE_POSITION_INFORMATION:
6952 status = smb_file_position_information(conn,
6953 pdata,
6954 total_data,
6955 fsp);
6956 break;
6959 /* From tridge Samba4 :
6960 * MODE_INFORMATION in setfileinfo (I have no
6961 * idea what "mode information" on a file is - it takes a value of 0,
6962 * 2, 4 or 6. What could it be?).
6965 case SMB_FILE_MODE_INFORMATION:
6967 status = smb_file_mode_information(conn,
6968 pdata,
6969 total_data);
6970 break;
6974 * CIFS UNIX extensions.
6977 case SMB_SET_FILE_UNIX_BASIC:
6979 status = smb_set_file_unix_basic(conn, req,
6980 pdata,
6981 total_data,
6982 fsp,
6983 fname,
6984 &sbuf);
6985 break;
6988 case SMB_SET_FILE_UNIX_INFO2:
6990 status = smb_set_file_unix_info2(conn, req,
6991 pdata,
6992 total_data,
6993 fsp,
6994 fname,
6995 &sbuf);
6996 break;
6999 case SMB_SET_FILE_UNIX_LINK:
7001 if (tran_call != TRANSACT2_SETPATHINFO) {
7002 /* We must have a pathname for this. */
7003 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7004 return;
7006 status = smb_set_file_unix_link(conn, req, pdata,
7007 total_data, fname);
7008 break;
7011 case SMB_SET_FILE_UNIX_HLINK:
7013 if (tran_call != TRANSACT2_SETPATHINFO) {
7014 /* We must have a pathname for this. */
7015 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7016 return;
7018 status = smb_set_file_unix_hlink(conn, req,
7019 pdata, total_data,
7020 fname);
7021 break;
7024 case SMB_FILE_RENAME_INFORMATION:
7026 status = smb_file_rename_information(conn, req,
7027 pdata, total_data,
7028 fsp, fname);
7029 break;
7032 #if defined(HAVE_POSIX_ACLS)
7033 case SMB_SET_POSIX_ACL:
7035 status = smb_set_posix_acl(conn,
7036 pdata,
7037 total_data,
7038 fsp,
7039 fname,
7040 &sbuf);
7041 break;
7043 #endif
7045 case SMB_SET_POSIX_LOCK:
7047 if (tran_call != TRANSACT2_SETFILEINFO) {
7048 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7049 return;
7051 status = smb_set_posix_lock(conn, req,
7052 pdata, total_data, fsp);
7053 break;
7056 case SMB_POSIX_PATH_OPEN:
7058 if (tran_call != TRANSACT2_SETPATHINFO) {
7059 /* We must have a pathname for this. */
7060 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7061 return;
7064 status = smb_posix_open(conn, req,
7065 ppdata,
7066 total_data,
7067 fname,
7068 &sbuf,
7069 &data_return_size);
7070 break;
7073 case SMB_POSIX_PATH_UNLINK:
7075 if (tran_call != TRANSACT2_SETPATHINFO) {
7076 /* We must have a pathname for this. */
7077 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7078 return;
7081 status = smb_posix_unlink(conn, req,
7082 pdata,
7083 total_data,
7084 fname,
7085 &sbuf);
7086 break;
7089 default:
7090 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7091 return;
7095 if (!NT_STATUS_IS_OK(status)) {
7096 if (open_was_deferred(req->mid)) {
7097 /* We have re-scheduled this call. */
7098 return;
7100 if (blocking_lock_was_deferred(req->mid)) {
7101 /* We have re-scheduled this call. */
7102 return;
7104 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7105 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7106 ERRSRV, ERRbadpath);
7107 return;
7109 if (info_level == SMB_POSIX_PATH_OPEN) {
7110 reply_openerror(req, status);
7111 return;
7114 reply_nterror(req, status);
7115 return;
7118 SSVAL(params,0,0);
7119 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7120 max_data_bytes);
7122 return;
7125 /****************************************************************************
7126 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7127 ****************************************************************************/
7129 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7130 char **pparams, int total_params,
7131 char **ppdata, int total_data,
7132 unsigned int max_data_bytes)
7134 char *params = *pparams;
7135 char *pdata = *ppdata;
7136 char *directory = NULL;
7137 SMB_STRUCT_STAT sbuf;
7138 NTSTATUS status = NT_STATUS_OK;
7139 struct ea_list *ea_list = NULL;
7140 TALLOC_CTX *ctx = talloc_tos();
7142 if (!CAN_WRITE(conn)) {
7143 reply_doserror(req, ERRSRV, ERRaccess);
7144 return;
7147 if (total_params < 5) {
7148 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7149 return;
7152 srvstr_get_path(ctx, params, req->flags2, &directory, &params[4],
7153 total_params - 4, STR_TERMINATE,
7154 &status);
7155 if (!NT_STATUS_IS_OK(status)) {
7156 reply_nterror(req, status);
7157 return;
7160 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7162 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7163 if (!NT_STATUS_IS_OK(status)) {
7164 reply_nterror(req, status);
7165 return;
7168 status = check_name(conn, directory);
7169 if (!NT_STATUS_IS_OK(status)) {
7170 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7171 reply_nterror(req, status);
7172 return;
7175 /* Any data in this call is an EA list. */
7176 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7177 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7178 return;
7182 * OS/2 workplace shell seems to send SET_EA requests of "null"
7183 * length (4 bytes containing IVAL 4).
7184 * They seem to have no effect. Bug #3212. JRA.
7187 if (total_data != 4) {
7188 if (total_data < 10) {
7189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7190 return;
7193 if (IVAL(pdata,0) > total_data) {
7194 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7195 IVAL(pdata,0), (unsigned int)total_data));
7196 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7197 return;
7200 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7201 total_data - 4);
7202 if (!ea_list) {
7203 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7204 return;
7207 /* If total_data == 4 Windows doesn't care what values
7208 * are placed in that field, it just ignores them.
7209 * The System i QNTC IBM SMB client puts bad values here,
7210 * so ignore them. */
7212 status = create_directory(conn, req, directory);
7214 if (!NT_STATUS_IS_OK(status)) {
7215 reply_nterror(req, status);
7216 return;
7219 /* Try and set any given EA. */
7220 if (ea_list) {
7221 status = set_ea(conn, NULL, directory, ea_list);
7222 if (!NT_STATUS_IS_OK(status)) {
7223 reply_nterror(req, status);
7224 return;
7228 /* Realloc the parameter and data sizes */
7229 *pparams = (char *)SMB_REALLOC(*pparams,2);
7230 if(*pparams == NULL) {
7231 reply_nterror(req, NT_STATUS_NO_MEMORY);
7232 return;
7234 params = *pparams;
7236 SSVAL(params,0,0);
7238 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7240 return;
7243 /****************************************************************************
7244 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7245 We don't actually do this - we just send a null response.
7246 ****************************************************************************/
7248 static void call_trans2findnotifyfirst(connection_struct *conn,
7249 struct smb_request *req,
7250 char **pparams, int total_params,
7251 char **ppdata, int total_data,
7252 unsigned int max_data_bytes)
7254 char *params = *pparams;
7255 uint16 info_level;
7257 if (total_params < 6) {
7258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7259 return;
7262 info_level = SVAL(params,4);
7263 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7265 switch (info_level) {
7266 case 1:
7267 case 2:
7268 break;
7269 default:
7270 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7271 return;
7274 /* Realloc the parameter and data sizes */
7275 *pparams = (char *)SMB_REALLOC(*pparams,6);
7276 if (*pparams == NULL) {
7277 reply_nterror(req, NT_STATUS_NO_MEMORY);
7278 return;
7280 params = *pparams;
7282 SSVAL(params,0,fnf_handle);
7283 SSVAL(params,2,0); /* No changes */
7284 SSVAL(params,4,0); /* No EA errors */
7286 fnf_handle++;
7288 if(fnf_handle == 0)
7289 fnf_handle = 257;
7291 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7293 return;
7296 /****************************************************************************
7297 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7298 changes). Currently this does nothing.
7299 ****************************************************************************/
7301 static void call_trans2findnotifynext(connection_struct *conn,
7302 struct smb_request *req,
7303 char **pparams, int total_params,
7304 char **ppdata, int total_data,
7305 unsigned int max_data_bytes)
7307 char *params = *pparams;
7309 DEBUG(3,("call_trans2findnotifynext\n"));
7311 /* Realloc the parameter and data sizes */
7312 *pparams = (char *)SMB_REALLOC(*pparams,4);
7313 if (*pparams == NULL) {
7314 reply_nterror(req, NT_STATUS_NO_MEMORY);
7315 return;
7317 params = *pparams;
7319 SSVAL(params,0,0); /* No changes */
7320 SSVAL(params,2,0); /* No EA errors */
7322 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7324 return;
7327 /****************************************************************************
7328 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7329 ****************************************************************************/
7331 static void call_trans2getdfsreferral(connection_struct *conn,
7332 struct smb_request *req,
7333 char **pparams, int total_params,
7334 char **ppdata, int total_data,
7335 unsigned int max_data_bytes)
7337 char *params = *pparams;
7338 char *pathname = NULL;
7339 int reply_size = 0;
7340 int max_referral_level;
7341 NTSTATUS status = NT_STATUS_OK;
7342 TALLOC_CTX *ctx = talloc_tos();
7344 DEBUG(10,("call_trans2getdfsreferral\n"));
7346 if (total_params < 3) {
7347 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7348 return;
7351 max_referral_level = SVAL(params,0);
7353 if(!lp_host_msdfs()) {
7354 reply_doserror(req, ERRDOS, ERRbadfunc);
7355 return;
7358 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
7359 total_params - 2, STR_TERMINATE);
7360 if (!pathname) {
7361 reply_nterror(req, NT_STATUS_NOT_FOUND);
7362 return;
7364 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7365 ppdata,&status)) < 0) {
7366 reply_nterror(req, status);
7367 return;
7370 SSVAL(req->inbuf, smb_flg2,
7371 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7372 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7374 return;
7377 #define LMCAT_SPL 0x53
7378 #define LMFUNC_GETJOBID 0x60
7380 /****************************************************************************
7381 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7382 ****************************************************************************/
7384 static void call_trans2ioctl(connection_struct *conn,
7385 struct smb_request *req,
7386 char **pparams, int total_params,
7387 char **ppdata, int total_data,
7388 unsigned int max_data_bytes)
7390 char *pdata = *ppdata;
7391 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7393 /* check for an invalid fid before proceeding */
7395 if (!fsp) {
7396 reply_doserror(req, ERRDOS, ERRbadfid);
7397 return;
7400 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7401 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7402 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7403 if (*ppdata == NULL) {
7404 reply_nterror(req, NT_STATUS_NO_MEMORY);
7405 return;
7407 pdata = *ppdata;
7409 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7410 CAN ACCEPT THIS IN UNICODE. JRA. */
7412 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7413 srvstr_push(pdata, req->flags2, pdata + 2,
7414 global_myname(), 15,
7415 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7416 srvstr_push(pdata, req->flags2, pdata+18,
7417 lp_servicename(SNUM(conn)), 13,
7418 STR_ASCII|STR_TERMINATE); /* Service name */
7419 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7420 max_data_bytes);
7421 return;
7424 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7425 reply_doserror(req, ERRSRV, ERRerror);
7428 /****************************************************************************
7429 Reply to a SMBfindclose (stop trans2 directory search).
7430 ****************************************************************************/
7432 void reply_findclose(struct smb_request *req)
7434 int dptr_num;
7436 START_PROFILE(SMBfindclose);
7438 if (req->wct < 1) {
7439 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7440 END_PROFILE(SMBfindclose);
7441 return;
7444 dptr_num = SVALS(req->vwv+0, 0);
7446 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7448 dptr_close(&dptr_num);
7450 reply_outbuf(req, 0, 0);
7452 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7454 END_PROFILE(SMBfindclose);
7455 return;
7458 /****************************************************************************
7459 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7460 ****************************************************************************/
7462 void reply_findnclose(struct smb_request *req)
7464 int dptr_num;
7466 START_PROFILE(SMBfindnclose);
7468 if (req->wct < 1) {
7469 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7470 END_PROFILE(SMBfindnclose);
7471 return;
7474 dptr_num = SVAL(req->vwv+0, 0);
7476 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7478 /* We never give out valid handles for a
7479 findnotifyfirst - so any dptr_num is ok here.
7480 Just ignore it. */
7482 reply_outbuf(req, 0, 0);
7484 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7486 END_PROFILE(SMBfindnclose);
7487 return;
7490 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7491 struct trans_state *state)
7493 if (Protocol >= PROTOCOL_NT1) {
7494 req->flags2 |= 0x40; /* IS_LONG_NAME */
7495 SSVAL(req->inbuf,smb_flg2,req->flags2);
7498 if (conn->encrypt_level == Required && !req->encrypted) {
7499 if (state->call != TRANSACT2_QFSINFO &&
7500 state->call != TRANSACT2_SETFSINFO) {
7501 DEBUG(0,("handle_trans2: encryption required "
7502 "with call 0x%x\n",
7503 (unsigned int)state->call));
7504 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7505 return;
7509 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7511 /* Now we must call the relevant TRANS2 function */
7512 switch(state->call) {
7513 case TRANSACT2_OPEN:
7515 START_PROFILE(Trans2_open);
7516 call_trans2open(conn, req,
7517 &state->param, state->total_param,
7518 &state->data, state->total_data,
7519 state->max_data_return);
7520 END_PROFILE(Trans2_open);
7521 break;
7524 case TRANSACT2_FINDFIRST:
7526 START_PROFILE(Trans2_findfirst);
7527 call_trans2findfirst(conn, req,
7528 &state->param, state->total_param,
7529 &state->data, state->total_data,
7530 state->max_data_return);
7531 END_PROFILE(Trans2_findfirst);
7532 break;
7535 case TRANSACT2_FINDNEXT:
7537 START_PROFILE(Trans2_findnext);
7538 call_trans2findnext(conn, req,
7539 &state->param, state->total_param,
7540 &state->data, state->total_data,
7541 state->max_data_return);
7542 END_PROFILE(Trans2_findnext);
7543 break;
7546 case TRANSACT2_QFSINFO:
7548 START_PROFILE(Trans2_qfsinfo);
7549 call_trans2qfsinfo(conn, req,
7550 &state->param, state->total_param,
7551 &state->data, state->total_data,
7552 state->max_data_return);
7553 END_PROFILE(Trans2_qfsinfo);
7554 break;
7557 case TRANSACT2_SETFSINFO:
7559 START_PROFILE(Trans2_setfsinfo);
7560 call_trans2setfsinfo(conn, req,
7561 &state->param, state->total_param,
7562 &state->data, state->total_data,
7563 state->max_data_return);
7564 END_PROFILE(Trans2_setfsinfo);
7565 break;
7568 case TRANSACT2_QPATHINFO:
7569 case TRANSACT2_QFILEINFO:
7571 START_PROFILE(Trans2_qpathinfo);
7572 call_trans2qfilepathinfo(conn, req, state->call,
7573 &state->param, state->total_param,
7574 &state->data, state->total_data,
7575 state->max_data_return);
7576 END_PROFILE(Trans2_qpathinfo);
7577 break;
7580 case TRANSACT2_SETPATHINFO:
7581 case TRANSACT2_SETFILEINFO:
7583 START_PROFILE(Trans2_setpathinfo);
7584 call_trans2setfilepathinfo(conn, req, state->call,
7585 &state->param, state->total_param,
7586 &state->data, state->total_data,
7587 state->max_data_return);
7588 END_PROFILE(Trans2_setpathinfo);
7589 break;
7592 case TRANSACT2_FINDNOTIFYFIRST:
7594 START_PROFILE(Trans2_findnotifyfirst);
7595 call_trans2findnotifyfirst(conn, req,
7596 &state->param, state->total_param,
7597 &state->data, state->total_data,
7598 state->max_data_return);
7599 END_PROFILE(Trans2_findnotifyfirst);
7600 break;
7603 case TRANSACT2_FINDNOTIFYNEXT:
7605 START_PROFILE(Trans2_findnotifynext);
7606 call_trans2findnotifynext(conn, req,
7607 &state->param, state->total_param,
7608 &state->data, state->total_data,
7609 state->max_data_return);
7610 END_PROFILE(Trans2_findnotifynext);
7611 break;
7614 case TRANSACT2_MKDIR:
7616 START_PROFILE(Trans2_mkdir);
7617 call_trans2mkdir(conn, req,
7618 &state->param, state->total_param,
7619 &state->data, state->total_data,
7620 state->max_data_return);
7621 END_PROFILE(Trans2_mkdir);
7622 break;
7625 case TRANSACT2_GET_DFS_REFERRAL:
7627 START_PROFILE(Trans2_get_dfs_referral);
7628 call_trans2getdfsreferral(conn, req,
7629 &state->param, state->total_param,
7630 &state->data, state->total_data,
7631 state->max_data_return);
7632 END_PROFILE(Trans2_get_dfs_referral);
7633 break;
7636 case TRANSACT2_IOCTL:
7638 START_PROFILE(Trans2_ioctl);
7639 call_trans2ioctl(conn, req,
7640 &state->param, state->total_param,
7641 &state->data, state->total_data,
7642 state->max_data_return);
7643 END_PROFILE(Trans2_ioctl);
7644 break;
7647 default:
7648 /* Error in request */
7649 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7650 reply_doserror(req, ERRSRV,ERRerror);
7654 /****************************************************************************
7655 Reply to a SMBtrans2.
7656 ****************************************************************************/
7658 void reply_trans2(struct smb_request *req)
7660 connection_struct *conn = req->conn;
7661 unsigned int dsoff;
7662 unsigned int dscnt;
7663 unsigned int psoff;
7664 unsigned int pscnt;
7665 unsigned int tran_call;
7666 struct trans_state *state;
7667 NTSTATUS result;
7669 START_PROFILE(SMBtrans2);
7671 if (req->wct < 14) {
7672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7673 END_PROFILE(SMBtrans2);
7674 return;
7677 dsoff = SVAL(req->vwv+12, 0);
7678 dscnt = SVAL(req->vwv+11, 0);
7679 psoff = SVAL(req->vwv+10, 0);
7680 pscnt = SVAL(req->vwv+9, 0);
7681 tran_call = SVAL(req->vwv+14, 0);
7683 result = allow_new_trans(conn->pending_trans, req->mid);
7684 if (!NT_STATUS_IS_OK(result)) {
7685 DEBUG(2, ("Got invalid trans2 request: %s\n",
7686 nt_errstr(result)));
7687 reply_nterror(req, result);
7688 END_PROFILE(SMBtrans2);
7689 return;
7692 if (IS_IPC(conn)) {
7693 switch (tran_call) {
7694 /* List the allowed trans2 calls on IPC$ */
7695 case TRANSACT2_OPEN:
7696 case TRANSACT2_GET_DFS_REFERRAL:
7697 case TRANSACT2_QFILEINFO:
7698 case TRANSACT2_QFSINFO:
7699 case TRANSACT2_SETFSINFO:
7700 break;
7701 default:
7702 reply_doserror(req, ERRSRV, ERRaccess);
7703 END_PROFILE(SMBtrans2);
7704 return;
7708 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7709 DEBUG(0, ("talloc failed\n"));
7710 reply_nterror(req, NT_STATUS_NO_MEMORY);
7711 END_PROFILE(SMBtrans2);
7712 return;
7715 state->cmd = SMBtrans2;
7717 state->mid = req->mid;
7718 state->vuid = req->vuid;
7719 state->setup_count = SVAL(req->vwv+13, 0);
7720 state->setup = NULL;
7721 state->total_param = SVAL(req->vwv+0, 0);
7722 state->param = NULL;
7723 state->total_data = SVAL(req->vwv+1, 0);
7724 state->data = NULL;
7725 state->max_param_return = SVAL(req->vwv+2, 0);
7726 state->max_data_return = SVAL(req->vwv+3, 0);
7727 state->max_setup_return = SVAL(req->vwv+4, 0);
7728 state->close_on_completion = BITSETW(req->vwv+5, 0);
7729 state->one_way = BITSETW(req->vwv+5, 1);
7731 state->call = tran_call;
7733 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7734 is so as a sanity check */
7735 if (state->setup_count != 1) {
7737 * Need to have rc=0 for ioctl to get job id for OS/2.
7738 * Network printing will fail if function is not successful.
7739 * Similar function in reply.c will be used if protocol
7740 * is LANMAN1.0 instead of LM1.2X002.
7741 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7742 * outbuf doesn't have to be set(only job id is used).
7744 if ( (state->setup_count == 4)
7745 && (tran_call == TRANSACT2_IOCTL)
7746 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7747 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7748 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7749 } else {
7750 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7751 DEBUG(2,("Transaction is %d\n",tran_call));
7752 TALLOC_FREE(state);
7753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7754 END_PROFILE(SMBtrans2);
7755 return;
7759 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7760 goto bad_param;
7762 if (state->total_data) {
7764 if (trans_oob(state->total_data, 0, dscnt)
7765 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7766 goto bad_param;
7769 /* Can't use talloc here, the core routines do realloc on the
7770 * params and data. */
7771 state->data = (char *)SMB_MALLOC(state->total_data);
7772 if (state->data == NULL) {
7773 DEBUG(0,("reply_trans2: data malloc fail for %u "
7774 "bytes !\n", (unsigned int)state->total_data));
7775 TALLOC_FREE(state);
7776 reply_nterror(req, NT_STATUS_NO_MEMORY);
7777 END_PROFILE(SMBtrans2);
7778 return;
7781 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7784 if (state->total_param) {
7786 if (trans_oob(state->total_param, 0, pscnt)
7787 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7788 goto bad_param;
7791 /* Can't use talloc here, the core routines do realloc on the
7792 * params and data. */
7793 state->param = (char *)SMB_MALLOC(state->total_param);
7794 if (state->param == NULL) {
7795 DEBUG(0,("reply_trans: param malloc fail for %u "
7796 "bytes !\n", (unsigned int)state->total_param));
7797 SAFE_FREE(state->data);
7798 TALLOC_FREE(state);
7799 reply_nterror(req, NT_STATUS_NO_MEMORY);
7800 END_PROFILE(SMBtrans2);
7801 return;
7804 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7807 state->received_data = dscnt;
7808 state->received_param = pscnt;
7810 if ((state->received_param == state->total_param) &&
7811 (state->received_data == state->total_data)) {
7813 handle_trans2(conn, req, state);
7815 SAFE_FREE(state->data);
7816 SAFE_FREE(state->param);
7817 TALLOC_FREE(state);
7818 END_PROFILE(SMBtrans2);
7819 return;
7822 DLIST_ADD(conn->pending_trans, state);
7824 /* We need to send an interim response then receive the rest
7825 of the parameter/data bytes */
7826 reply_outbuf(req, 0, 0);
7827 show_msg((char *)req->outbuf);
7828 END_PROFILE(SMBtrans2);
7829 return;
7831 bad_param:
7833 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7834 SAFE_FREE(state->data);
7835 SAFE_FREE(state->param);
7836 TALLOC_FREE(state);
7837 END_PROFILE(SMBtrans2);
7838 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7842 /****************************************************************************
7843 Reply to a SMBtranss2
7844 ****************************************************************************/
7846 void reply_transs2(struct smb_request *req)
7848 connection_struct *conn = req->conn;
7849 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7850 struct trans_state *state;
7852 START_PROFILE(SMBtranss2);
7854 show_msg((char *)req->inbuf);
7856 if (req->wct < 8) {
7857 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7858 END_PROFILE(SMBtranss2);
7859 return;
7862 for (state = conn->pending_trans; state != NULL;
7863 state = state->next) {
7864 if (state->mid == req->mid) {
7865 break;
7869 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7871 END_PROFILE(SMBtranss2);
7872 return;
7875 /* Revise state->total_param and state->total_data in case they have
7876 changed downwards */
7878 if (SVAL(req->vwv+0, 0) < state->total_param)
7879 state->total_param = SVAL(req->vwv+0, 0);
7880 if (SVAL(req->vwv+1, 0) < state->total_data)
7881 state->total_data = SVAL(req->vwv+1, 0);
7883 pcnt = SVAL(req->vwv+2, 0);
7884 poff = SVAL(req->vwv+3, 0);
7885 pdisp = SVAL(req->vwv+4, 0);
7887 dcnt = SVAL(req->vwv+5, 0);
7888 doff = SVAL(req->vwv+6, 0);
7889 ddisp = SVAL(req->vwv+7, 0);
7891 state->received_param += pcnt;
7892 state->received_data += dcnt;
7894 if ((state->received_data > state->total_data) ||
7895 (state->received_param > state->total_param))
7896 goto bad_param;
7898 if (pcnt) {
7899 if (trans_oob(state->total_param, pdisp, pcnt)
7900 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7901 goto bad_param;
7903 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7906 if (dcnt) {
7907 if (trans_oob(state->total_data, ddisp, dcnt)
7908 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7909 goto bad_param;
7911 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7914 if ((state->received_param < state->total_param) ||
7915 (state->received_data < state->total_data)) {
7916 END_PROFILE(SMBtranss2);
7917 return;
7920 handle_trans2(conn, req, state);
7922 DLIST_REMOVE(conn->pending_trans, state);
7923 SAFE_FREE(state->data);
7924 SAFE_FREE(state->param);
7925 TALLOC_FREE(state);
7927 END_PROFILE(SMBtranss2);
7928 return;
7930 bad_param:
7932 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7933 DLIST_REMOVE(conn->pending_trans, state);
7934 SAFE_FREE(state->data);
7935 SAFE_FREE(state->param);
7936 TALLOC_FREE(state);
7937 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7938 END_PROFILE(SMBtranss2);
7939 return;