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/>.
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,
37 const SMB_STRUCT_STAT *psbuf);
39 static char *store_file_unix_basic_info2(connection_struct *conn,
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);
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,
79 for (i = 0; prohibited_ea_names[i]; i++) {
80 if (strequal( prohibited_ea_names[i], unix_ea_name))
83 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
84 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
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;
105 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
107 return NT_STATUS_NO_MEMORY;
110 if (fsp && fsp->fh->fd != -1) {
111 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
113 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
116 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
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);
129 if (strnequal(ea_name, "user.", 5)) {
130 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
132 pea->name = talloc_strdup(mem_ctx, ea_name);
134 if (pea->name == NULL) {
136 return NT_STATUS_NO_MEMORY;
138 pea->value.data = (unsigned char *)val;
139 pea->value.length = (size_t)sizeret;
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;
154 ssize_t sizeret = -1;
156 if (!lp_ea_support(SNUM(conn))) {
163 * TALLOC the result early to get the talloc hierarchy right.
166 names = TALLOC_ARRAY(mem_ctx, char *, 1);
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"));
179 return NT_STATUS_NO_MEMORY;
182 if (fsp && fsp->fh->fd != -1) {
183 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
186 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
190 if ((sizeret == -1) && (errno == ERANGE)) {
191 ea_namelist_size *= 2;
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));
214 * Ensure the result is 0-terminated
217 if (ea_namelist[sizeret-1] != '\0') {
219 return NT_STATUS_INTERNAL_ERROR;
227 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
231 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
233 DEBUG(0, ("talloc failed\n"));
235 return NT_STATUS_NO_MEMORY;
241 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
242 names[num_names++] = p;
246 *pnum_names = num_names;
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. */
260 struct ea_list *ea_list_head = NULL;
265 if (!lp_ea_support(SNUM(conn))) {
269 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
272 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
276 for (i=0; i<num_names; i++) {
277 struct ea_list *listp;
280 if (strnequal(names[i], "system.", 7)
281 || samba_private_attr_name(names[i]))
284 listp = TALLOC_P(mem_ctx, struct ea_list);
289 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
295 push_ascii_fstring(dos_ea_name, listp->ea.name);
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) {
313 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
314 (unsigned int)*pea_total_len));
319 /****************************************************************************
320 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
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;
330 SMB_ASSERT(total_data_size >= 4);
332 if (!lp_ea_support(SNUM(conn))) {
337 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
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) {
345 if (ea_list->ea.value.length > 65535) {
348 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
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))) {
377 mem_ctx = talloc_tos();
378 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &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)
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);
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) {
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);
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);
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",
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);
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);
463 if (errno == ENOTSUP) {
464 return NT_STATUS_EAS_NOT_SUPPORTED;
467 return map_nt_error_from_unix(errno);
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)) {
494 /* Ensure the name is null terminated. */
495 if (pdata[offset + namelen] != '\0') {
498 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
500 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
501 "failed: %s", strerror(errno)));
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));
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);
523 unsigned int namelen;
524 size_t converted_size;
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) {
542 /* Ensure the name is null terminated. */
543 if (pdata[namelen + 4] != '\0') {
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",
554 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
555 if (!eal->ea.value.data) {
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--;
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);
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;
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);
593 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
594 offset += bytes_used;
600 /****************************************************************************
601 Count the total EA size needed.
602 ****************************************************************************/
604 static size_t ea_list_size(struct ea_list *ealist)
607 struct ea_list *listp;
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. */
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)) {
640 /* Copy the data from this entry. */
641 nlistp->ea.flags = flistp->ea.flags;
642 nlistp->ea.value = flistp->ea.value;
645 nlistp->ea.flags = 0;
646 ZERO_STRUCT(nlistp->ea.value);
650 *total_ea_len = ea_list_size(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,
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;
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
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;
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);
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
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);
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);
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));
825 error_packet_set((char *)req->outbuf,
826 ERRDOS,ERRbufferoverflow,
827 STATUS_BUFFER_OVERFLOW,
831 /* Send the packet */
832 show_msg((char *)req->outbuf);
833 if (!srv_send_smb(smbd_server_fd(),
835 IS_CONN_ENCRYPTED(conn)))
836 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
838 TALLOC_FREE(req->outbuf);
840 pp += params_sent_thistime;
841 pd += data_sent_thistime;
843 params_to_send -= params_sent_thistime;
844 data_to_send -= data_sent_thistime;
847 if(params_to_send < 0 || data_to_send < 0) {
848 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
849 params_to_send, data_to_send));
857 /****************************************************************************
858 Reply to a TRANSACT2_OPEN.
859 ****************************************************************************/
861 static void call_trans2open(connection_struct *conn,
862 struct smb_request *req,
863 char **pparams, int total_params,
864 char **ppdata, int total_data,
865 unsigned int max_data_bytes)
867 char *params = *pparams;
868 char *pdata = *ppdata;
873 bool return_additional_info;
884 SMB_STRUCT_STAT sbuf;
887 struct ea_list *ea_list = NULL;
892 uint32 create_disposition;
893 uint32 create_options = 0;
894 TALLOC_CTX *ctx = talloc_tos();
897 * Ensure we have enough parameters to perform the operation.
900 if (total_params < 29) {
901 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
905 flags = SVAL(params, 0);
906 deny_mode = SVAL(params, 2);
907 open_attr = SVAL(params,6);
908 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
909 if (oplock_request) {
910 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
914 return_additional_info = BITSETW(params,0);
915 open_sattr = SVAL(params, 4);
916 open_time = make_unix_date3(params+8);
918 open_ofun = SVAL(params,12);
919 open_size = IVAL(params,14);
923 reply_doserror(req, ERRSRV, ERRaccess);
927 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
928 total_params - 28, STR_TERMINATE,
930 if (!NT_STATUS_IS_OK(status)) {
931 reply_nterror(req, status);
935 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
936 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
937 (unsigned int)open_ofun, open_size));
939 if (open_ofun == 0) {
940 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
944 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
949 reply_doserror(req, ERRDOS, ERRbadaccess);
953 /* Any data in this call is an EA list. */
954 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
955 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
959 if (total_data != 4) {
960 if (total_data < 10) {
961 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
965 if (IVAL(pdata,0) > total_data) {
966 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
967 IVAL(pdata,0), (unsigned int)total_data));
968 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
972 ea_list = read_ea_list(talloc_tos(), pdata + 4,
975 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
978 } else if (IVAL(pdata,0) != 4) {
979 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
983 status = SMB_VFS_CREATE_FILE(
986 0, /* root_dir_fid */
988 CFF_DOS_PATH, /* create_file_flags */
989 access_mask, /* access_mask */
990 share_mode, /* share_access */
991 create_disposition, /* create_disposition*/
992 create_options, /* create_options */
993 open_attr, /* file_attributes */
994 oplock_request, /* oplock_request */
995 open_size, /* allocation_size */
997 ea_list, /* ea_list */
999 &smb_action, /* pinfo */
1002 if (!NT_STATUS_IS_OK(status)) {
1003 if (open_was_deferred(req->mid)) {
1004 /* We have re-scheduled this call. */
1007 reply_openerror(req, status);
1011 size = get_file_size_stat(&sbuf);
1012 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1013 mtime = sbuf.st_mtime;
1014 inode = sbuf.st_ino;
1016 close_file(req, fsp, ERROR_CLOSE);
1017 reply_doserror(req, ERRDOS,ERRnoaccess);
1021 /* Realloc the size of parameters and data we will return */
1022 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1023 if(*pparams == NULL ) {
1024 reply_nterror(req, NT_STATUS_NO_MEMORY);
1029 SSVAL(params,0,fsp->fnum);
1030 SSVAL(params,2,fattr);
1031 srv_put_dos_date2(params,4, mtime);
1032 SIVAL(params,8, (uint32)size);
1033 SSVAL(params,12,deny_mode);
1034 SSVAL(params,14,0); /* open_type - file or directory. */
1035 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1037 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1038 smb_action |= EXTENDED_OPLOCK_GRANTED;
1041 SSVAL(params,18,smb_action);
1044 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1046 SIVAL(params,20,inode);
1047 SSVAL(params,24,0); /* Padding. */
1049 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1050 SIVAL(params, 26, ea_size);
1052 SIVAL(params, 26, 0);
1055 /* Send the required number of replies */
1056 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1059 /*********************************************************
1060 Routine to check if a given string matches exactly.
1061 as a special case a mask of "." does NOT match. That
1062 is required for correct wildcard semantics
1063 Case can be significant or not.
1064 **********************************************************/
1066 static bool exact_match(connection_struct *conn,
1070 if (mask[0] == '.' && mask[1] == 0)
1072 if (dptr_has_wild(conn->dirptr)) {
1075 if (conn->case_sensitive)
1076 return strcmp(str,mask)==0;
1078 return StrCaseCmp(str,mask) == 0;
1081 /****************************************************************************
1082 Return the filetype for UNIX extensions.
1083 ****************************************************************************/
1085 static uint32 unix_filetype(mode_t mode)
1088 return UNIX_TYPE_FILE;
1089 else if(S_ISDIR(mode))
1090 return UNIX_TYPE_DIR;
1092 else if(S_ISLNK(mode))
1093 return UNIX_TYPE_SYMLINK;
1096 else if(S_ISCHR(mode))
1097 return UNIX_TYPE_CHARDEV;
1100 else if(S_ISBLK(mode))
1101 return UNIX_TYPE_BLKDEV;
1104 else if(S_ISFIFO(mode))
1105 return UNIX_TYPE_FIFO;
1108 else if(S_ISSOCK(mode))
1109 return UNIX_TYPE_SOCKET;
1112 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1113 return UNIX_TYPE_UNKNOWN;
1116 /****************************************************************************
1117 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1118 ****************************************************************************/
1120 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1122 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1123 SMB_STRUCT_STAT *psbuf,
1125 enum perm_type ptype,
1130 if (perms == SMB_MODE_NO_CHANGE) {
1131 if (!VALID_STAT(*psbuf)) {
1132 return NT_STATUS_INVALID_PARAMETER;
1134 *ret_perms = psbuf->st_mode;
1135 return NT_STATUS_OK;
1139 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1140 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1141 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1142 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1143 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1144 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1145 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1146 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1147 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1149 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1152 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1155 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1160 /* Apply mode mask */
1161 ret &= lp_create_mask(SNUM(conn));
1162 /* Add in force bits */
1163 ret |= lp_force_create_mode(SNUM(conn));
1166 ret &= lp_dir_mask(SNUM(conn));
1167 /* Add in force bits */
1168 ret |= lp_force_dir_mode(SNUM(conn));
1170 case PERM_EXISTING_FILE:
1171 /* Apply mode mask */
1172 ret &= lp_security_mask(SNUM(conn));
1173 /* Add in force bits */
1174 ret |= lp_force_security_mode(SNUM(conn));
1176 case PERM_EXISTING_DIR:
1177 /* Apply mode mask */
1178 ret &= lp_dir_security_mask(SNUM(conn));
1179 /* Add in force bits */
1180 ret |= lp_force_dir_security_mode(SNUM(conn));
1185 return NT_STATUS_OK;
1188 /****************************************************************************
1189 Needed to show the msdfs symlinks as directories. Modifies psbuf
1190 to be a directory if it's a msdfs link.
1191 ****************************************************************************/
1193 static bool check_msdfs_link(connection_struct *conn,
1194 const char *pathname,
1195 SMB_STRUCT_STAT *psbuf)
1197 int saved_errno = errno;
1198 if(lp_host_msdfs() &&
1199 lp_msdfs_root(SNUM(conn)) &&
1200 is_msdfs_link(conn, pathname, psbuf)) {
1202 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1205 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1206 errno = saved_errno;
1209 errno = saved_errno;
1214 /****************************************************************************
1215 Get a level dependent lanman2 dir entry.
1216 ****************************************************************************/
1218 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1219 connection_struct *conn,
1221 const char *path_mask,
1224 int requires_resume_key,
1230 int space_remaining,
1232 bool *got_exact_match,
1233 int *last_entry_off,
1234 struct ea_list *name_list)
1238 SMB_STRUCT_STAT sbuf;
1239 const char *mask = NULL;
1240 char *pathreal = NULL;
1241 const char *fname = NULL;
1242 char *p, *q, *pdata = *ppdata;
1246 SMB_OFF_T file_size = 0;
1247 uint64_t allocation_size = 0;
1249 struct timespec mdate_ts, adate_ts, create_date_ts;
1250 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1252 char *last_entry_ptr;
1254 uint32 nt_extmode; /* Used for NT connections instead of mode */
1255 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1256 bool check_mangled_names = lp_manglednames(conn->params);
1257 char mangled_name[13]; /* mangled 8.3 name. */
1259 *out_of_space = False;
1260 *got_exact_match = False;
1262 ZERO_STRUCT(mdate_ts);
1263 ZERO_STRUCT(adate_ts);
1264 ZERO_STRUCT(create_date_ts);
1266 if (!conn->dirptr) {
1270 p = strrchr_m(path_mask,'/');
1273 mask = talloc_strdup(ctx,"*.*");
1283 bool ms_dfs_link = False;
1285 /* Needed if we run out of space */
1286 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1287 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1290 * Due to bugs in NT client redirectors we are not using
1291 * resume keys any more - set them to zero.
1292 * Check out the related comments in findfirst/findnext.
1298 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1299 (long)conn->dirptr,curr_dirpos));
1306 * fname may get mangled, dname is never mangled.
1307 * Whenever we're accessing the filesystem we use
1308 * pathreal which is composed from dname.
1314 /* Mangle fname if it's an illegal name. */
1315 if (mangle_must_mangle(dname,conn->params)) {
1316 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1317 continue; /* Error - couldn't mangle. */
1319 fname = mangled_name;
1322 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1323 got_match = mask_match(fname, mask, conn->case_sensitive);
1326 if(!got_match && check_mangled_names &&
1327 !mangle_is_8_3(fname, False, conn->params)) {
1329 * It turns out that NT matches wildcards against
1330 * both long *and* short names. This may explain some
1331 * of the wildcard wierdness from old DOS clients
1332 * that some people have been seeing.... JRA.
1334 /* Force the mangling into 8.3. */
1335 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1336 continue; /* Error - couldn't mangle. */
1339 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1340 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1345 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1347 if (dont_descend && !isdots) {
1353 pathreal = talloc_asprintf(ctx,
1358 pathreal = talloc_asprintf(ctx,
1368 if (INFO_LEVEL_IS_UNIX(info_level)) {
1369 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1370 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1371 pathreal,strerror(errno)));
1372 TALLOC_FREE(pathreal);
1375 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1376 /* Needed to show the msdfs symlinks as
1379 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1381 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1382 pathreal,strerror(errno)));
1383 TALLOC_FREE(pathreal);
1389 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1391 mode = dos_mode(conn,pathreal,&sbuf);
1394 if (!dir_check_ftype(conn,mode,dirtype)) {
1395 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1396 TALLOC_FREE(pathreal);
1400 if (!(mode & aDIR)) {
1401 file_size = get_file_size_stat(&sbuf);
1403 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1405 mdate_ts = get_mtimespec(&sbuf);
1406 adate_ts = get_atimespec(&sbuf);
1407 create_date_ts = get_create_timespec(&sbuf,
1408 lp_fake_dir_create_times(SNUM(conn)));
1410 if (ask_sharemode) {
1411 struct timespec write_time_ts;
1412 struct file_id fileid;
1414 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1415 get_file_infos(fileid, NULL, &write_time_ts);
1416 if (!null_timespec(write_time_ts)) {
1417 mdate_ts = write_time_ts;
1421 if (lp_dos_filetime_resolution(SNUM(conn))) {
1422 dos_filetime_timespec(&create_date_ts);
1423 dos_filetime_timespec(&mdate_ts);
1424 dos_filetime_timespec(&adate_ts);
1427 create_date = convert_timespec_to_time_t(create_date_ts);
1428 mdate = convert_timespec_to_time_t(mdate_ts);
1429 adate = convert_timespec_to_time_t(adate_ts);
1431 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1436 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1443 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1445 switch (info_level) {
1446 case SMB_FIND_INFO_STANDARD:
1447 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1448 if(requires_resume_key) {
1452 srv_put_dos_date2(p,0,create_date);
1453 srv_put_dos_date2(p,4,adate);
1454 srv_put_dos_date2(p,8,mdate);
1455 SIVAL(p,12,(uint32)file_size);
1456 SIVAL(p,16,(uint32)allocation_size);
1460 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1461 p += ucs2_align(base_data, p, 0);
1463 len = srvstr_push(base_data, flags2, p,
1464 fname, PTR_DIFF(end_data, p),
1466 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1468 SCVAL(nameptr, -1, len - 2);
1470 SCVAL(nameptr, -1, 0);
1474 SCVAL(nameptr, -1, len - 1);
1476 SCVAL(nameptr, -1, 0);
1482 case SMB_FIND_EA_SIZE:
1483 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1484 if(requires_resume_key) {
1488 srv_put_dos_date2(p,0,create_date);
1489 srv_put_dos_date2(p,4,adate);
1490 srv_put_dos_date2(p,8,mdate);
1491 SIVAL(p,12,(uint32)file_size);
1492 SIVAL(p,16,(uint32)allocation_size);
1495 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1496 SIVAL(p,22,ea_size); /* Extended attributes */
1500 len = srvstr_push(base_data, flags2,
1501 p, fname, PTR_DIFF(end_data, p),
1502 STR_TERMINATE | STR_NOALIGN);
1503 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1516 SCVAL(nameptr,0,len);
1518 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1521 case SMB_FIND_EA_LIST:
1523 struct ea_list *file_list = NULL;
1526 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1530 if(requires_resume_key) {
1534 srv_put_dos_date2(p,0,create_date);
1535 srv_put_dos_date2(p,4,adate);
1536 srv_put_dos_date2(p,8,mdate);
1537 SIVAL(p,12,(uint32)file_size);
1538 SIVAL(p,16,(uint32)allocation_size);
1540 p += 22; /* p now points to the EA area. */
1542 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1543 name_list = ea_list_union(name_list, file_list, &ea_len);
1545 /* We need to determine if this entry will fit in the space available. */
1546 /* Max string size is 255 bytes. */
1547 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1548 /* Move the dirptr back to prev_dirpos */
1549 dptr_SeekDir(conn->dirptr, prev_dirpos);
1550 *out_of_space = True;
1551 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1552 return False; /* Not finished - just out of space */
1555 /* Push the ea_data followed by the name. */
1556 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1558 len = srvstr_push(base_data, flags2,
1559 p + 1, fname, PTR_DIFF(end_data, p+1),
1560 STR_TERMINATE | STR_NOALIGN);
1561 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1574 SCVAL(nameptr,0,len);
1576 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1580 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1581 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1582 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1584 SIVAL(p,0,reskey); p += 4;
1585 put_long_date_timespec(p,create_date_ts); p += 8;
1586 put_long_date_timespec(p,adate_ts); p += 8;
1587 put_long_date_timespec(p,mdate_ts); p += 8;
1588 put_long_date_timespec(p,mdate_ts); p += 8;
1589 SOFF_T(p,0,file_size); p += 8;
1590 SOFF_T(p,0,allocation_size); p += 8;
1591 SIVAL(p,0,nt_extmode); p += 4;
1592 q = p; p += 4; /* q is placeholder for name length. */
1594 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1595 SIVAL(p,0,ea_size); /* Extended attributes */
1598 /* Clear the short name buffer. This is
1599 * IMPORTANT as not doing so will trigger
1600 * a Win2k client bug. JRA.
1602 if (!was_8_3 && check_mangled_names) {
1603 if (!name_to_8_3(fname,mangled_name,True,
1605 /* Error - mangle failed ! */
1606 memset(mangled_name,'\0',12);
1608 mangled_name[12] = 0;
1609 len = srvstr_push(base_data, flags2,
1610 p+2, mangled_name, 24,
1611 STR_UPPER|STR_UNICODE);
1613 memset(p + 2 + len,'\0',24 - len);
1620 len = srvstr_push(base_data, flags2, p,
1621 fname, PTR_DIFF(end_data, p),
1622 STR_TERMINATE_ASCII);
1625 SIVAL(p,0,0); /* Ensure any padding is null. */
1626 len = PTR_DIFF(p, pdata);
1627 len = (len + 3) & ~3;
1632 case SMB_FIND_FILE_DIRECTORY_INFO:
1633 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1635 SIVAL(p,0,reskey); p += 4;
1636 put_long_date_timespec(p,create_date_ts); p += 8;
1637 put_long_date_timespec(p,adate_ts); p += 8;
1638 put_long_date_timespec(p,mdate_ts); p += 8;
1639 put_long_date_timespec(p,mdate_ts); p += 8;
1640 SOFF_T(p,0,file_size); p += 8;
1641 SOFF_T(p,0,allocation_size); p += 8;
1642 SIVAL(p,0,nt_extmode); p += 4;
1643 len = srvstr_push(base_data, flags2,
1644 p + 4, fname, PTR_DIFF(end_data, p+4),
1645 STR_TERMINATE_ASCII);
1648 SIVAL(p,0,0); /* Ensure any padding is null. */
1649 len = PTR_DIFF(p, pdata);
1650 len = (len + 3) & ~3;
1655 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1656 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1658 SIVAL(p,0,reskey); p += 4;
1659 put_long_date_timespec(p,create_date_ts); p += 8;
1660 put_long_date_timespec(p,adate_ts); p += 8;
1661 put_long_date_timespec(p,mdate_ts); p += 8;
1662 put_long_date_timespec(p,mdate_ts); p += 8;
1663 SOFF_T(p,0,file_size); p += 8;
1664 SOFF_T(p,0,allocation_size); p += 8;
1665 SIVAL(p,0,nt_extmode); p += 4;
1666 q = p; p += 4; /* q is placeholder for name length. */
1668 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1669 SIVAL(p,0,ea_size); /* Extended attributes */
1672 len = srvstr_push(base_data, flags2, p,
1673 fname, PTR_DIFF(end_data, p),
1674 STR_TERMINATE_ASCII);
1678 SIVAL(p,0,0); /* Ensure any padding is null. */
1679 len = PTR_DIFF(p, pdata);
1680 len = (len + 3) & ~3;
1685 case SMB_FIND_FILE_NAMES_INFO:
1686 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1688 SIVAL(p,0,reskey); p += 4;
1690 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1691 acl on a dir (tridge) */
1692 len = srvstr_push(base_data, flags2, p,
1693 fname, PTR_DIFF(end_data, p),
1694 STR_TERMINATE_ASCII);
1697 SIVAL(p,0,0); /* Ensure any padding is null. */
1698 len = PTR_DIFF(p, pdata);
1699 len = (len + 3) & ~3;
1704 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1705 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1707 SIVAL(p,0,reskey); p += 4;
1708 put_long_date_timespec(p,create_date_ts); p += 8;
1709 put_long_date_timespec(p,adate_ts); p += 8;
1710 put_long_date_timespec(p,mdate_ts); p += 8;
1711 put_long_date_timespec(p,mdate_ts); p += 8;
1712 SOFF_T(p,0,file_size); p += 8;
1713 SOFF_T(p,0,allocation_size); p += 8;
1714 SIVAL(p,0,nt_extmode); p += 4;
1715 q = p; p += 4; /* q is placeholder for name length. */
1717 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1718 SIVAL(p,0,ea_size); /* Extended attributes */
1721 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1722 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1723 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1724 len = srvstr_push(base_data, flags2, p,
1725 fname, PTR_DIFF(end_data, p),
1726 STR_TERMINATE_ASCII);
1729 SIVAL(p,0,0); /* Ensure any padding is null. */
1730 len = PTR_DIFF(p, pdata);
1731 len = (len + 3) & ~3;
1736 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1737 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1738 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1740 SIVAL(p,0,reskey); p += 4;
1741 put_long_date_timespec(p,create_date_ts); p += 8;
1742 put_long_date_timespec(p,adate_ts); p += 8;
1743 put_long_date_timespec(p,mdate_ts); p += 8;
1744 put_long_date_timespec(p,mdate_ts); p += 8;
1745 SOFF_T(p,0,file_size); p += 8;
1746 SOFF_T(p,0,allocation_size); p += 8;
1747 SIVAL(p,0,nt_extmode); p += 4;
1748 q = p; p += 4; /* q is placeholder for name length */
1750 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1751 SIVAL(p,0,ea_size); /* Extended attributes */
1754 /* Clear the short name buffer. This is
1755 * IMPORTANT as not doing so will trigger
1756 * a Win2k client bug. JRA.
1758 if (!was_8_3 && check_mangled_names) {
1759 if (!name_to_8_3(fname,mangled_name,True,
1761 /* Error - mangle failed ! */
1762 memset(mangled_name,'\0',12);
1764 mangled_name[12] = 0;
1765 len = srvstr_push(base_data, flags2,
1766 p+2, mangled_name, 24,
1767 STR_UPPER|STR_UNICODE);
1770 memset(p + 2 + len,'\0',24 - len);
1777 SSVAL(p,0,0); p += 2; /* Reserved ? */
1778 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1779 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1780 len = srvstr_push(base_data, flags2, p,
1781 fname, PTR_DIFF(end_data, p),
1782 STR_TERMINATE_ASCII);
1785 SIVAL(p,0,0); /* Ensure any padding is null. */
1786 len = PTR_DIFF(p, pdata);
1787 len = (len + 3) & ~3;
1792 /* CIFS UNIX Extension. */
1794 case SMB_FIND_FILE_UNIX:
1795 case SMB_FIND_FILE_UNIX_INFO2:
1797 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1799 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1801 if (info_level == SMB_FIND_FILE_UNIX) {
1802 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1803 p = store_file_unix_basic(conn, p,
1805 len = srvstr_push(base_data, flags2, p,
1806 fname, PTR_DIFF(end_data, p),
1809 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1810 p = store_file_unix_basic_info2(conn, p,
1814 len = srvstr_push(base_data, flags2, p, fname,
1815 PTR_DIFF(end_data, p), 0);
1816 SIVAL(nameptr, 0, len);
1820 SIVAL(p,0,0); /* Ensure any padding is null. */
1822 len = PTR_DIFF(p, pdata);
1823 len = (len + 3) & ~3;
1824 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1826 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1835 if (PTR_DIFF(p,pdata) > space_remaining) {
1836 /* Move the dirptr back to prev_dirpos */
1837 dptr_SeekDir(conn->dirptr, prev_dirpos);
1838 *out_of_space = True;
1839 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1840 return False; /* Not finished - just out of space */
1843 /* Setup the last entry pointer, as an offset from base_data */
1844 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1845 /* Advance the data pointer to the next slot */
1851 /****************************************************************************
1852 Reply to a TRANS2_FINDFIRST.
1853 ****************************************************************************/
1855 static void call_trans2findfirst(connection_struct *conn,
1856 struct smb_request *req,
1857 char **pparams, int total_params,
1858 char **ppdata, int total_data,
1859 unsigned int max_data_bytes)
1861 /* We must be careful here that we don't return more than the
1862 allowed number of data bytes. If this means returning fewer than
1863 maxentries then so be it. We assume that the redirector has
1864 enough room for the fixed number of parameter bytes it has
1866 char *params = *pparams;
1867 char *pdata = *ppdata;
1871 uint16 findfirst_flags;
1872 bool close_after_first;
1874 bool requires_resume_key;
1876 char *directory = NULL;
1879 int last_entry_off=0;
1883 bool finished = False;
1884 bool dont_descend = False;
1885 bool out_of_space = False;
1886 int space_remaining;
1887 bool mask_contains_wcard = False;
1888 SMB_STRUCT_STAT sbuf;
1889 struct ea_list *ea_list = NULL;
1890 NTSTATUS ntstatus = NT_STATUS_OK;
1891 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1892 TALLOC_CTX *ctx = talloc_tos();
1894 if (total_params < 13) {
1895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1899 dirtype = SVAL(params,0);
1900 maxentries = SVAL(params,2);
1901 findfirst_flags = SVAL(params,4);
1902 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1903 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1904 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1905 info_level = SVAL(params,6);
1907 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1908 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1909 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1910 info_level, max_data_bytes));
1913 /* W2K3 seems to treat zero as 1. */
1917 switch (info_level) {
1918 case SMB_FIND_INFO_STANDARD:
1919 case SMB_FIND_EA_SIZE:
1920 case SMB_FIND_EA_LIST:
1921 case SMB_FIND_FILE_DIRECTORY_INFO:
1922 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1923 case SMB_FIND_FILE_NAMES_INFO:
1924 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1925 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1926 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1928 case SMB_FIND_FILE_UNIX:
1929 case SMB_FIND_FILE_UNIX_INFO2:
1930 /* Always use filesystem for UNIX mtime query. */
1931 ask_sharemode = false;
1932 if (!lp_unix_extensions()) {
1933 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1938 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1942 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1943 params+12, total_params - 12,
1944 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1945 if (!NT_STATUS_IS_OK(ntstatus)) {
1946 reply_nterror(req, ntstatus);
1950 ntstatus = resolve_dfspath_wcard(ctx, conn,
1951 req->flags2 & FLAGS2_DFS_PATHNAMES,
1954 &mask_contains_wcard);
1955 if (!NT_STATUS_IS_OK(ntstatus)) {
1956 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1957 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1958 ERRSRV, ERRbadpath);
1961 reply_nterror(req, ntstatus);
1965 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1966 if (!NT_STATUS_IS_OK(ntstatus)) {
1967 reply_nterror(req, ntstatus);
1971 ntstatus = check_name(conn, directory);
1972 if (!NT_STATUS_IS_OK(ntstatus)) {
1973 reply_nterror(req, ntstatus);
1977 p = strrchr_m(directory,'/');
1979 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1980 if((directory[0] == '.') && (directory[1] == '\0')) {
1981 mask = talloc_strdup(ctx,"*");
1983 reply_nterror(req, NT_STATUS_NO_MEMORY);
1986 mask_contains_wcard = True;
1988 directory = talloc_strdup(talloc_tos(), "./");
1990 reply_nterror(req, NT_STATUS_NO_MEMORY);
1997 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
1999 if (info_level == SMB_FIND_EA_LIST) {
2002 if (total_data < 4) {
2003 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2007 ea_size = IVAL(pdata,0);
2008 if (ea_size != total_data) {
2009 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2010 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2011 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2015 if (!lp_ea_support(SNUM(conn))) {
2016 reply_doserror(req, ERRDOS, ERReasnotsupported);
2020 /* Pull out the list of names. */
2021 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2023 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2028 *ppdata = (char *)SMB_REALLOC(
2029 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2030 if(*ppdata == NULL ) {
2031 reply_nterror(req, NT_STATUS_NO_MEMORY);
2035 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2037 /* Realloc the params space */
2038 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2039 if (*pparams == NULL) {
2040 reply_nterror(req, NT_STATUS_NO_MEMORY);
2045 /* Save the wildcard match and attribs we are using on this directory -
2046 needed as lanman2 assumes these are being saved between calls */
2048 ntstatus = dptr_create(conn,
2054 mask_contains_wcard,
2058 if (!NT_STATUS_IS_OK(ntstatus)) {
2059 reply_nterror(req, ntstatus);
2063 dptr_num = dptr_dnum(conn->dirptr);
2064 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2066 /* We don't need to check for VOL here as this is returned by
2067 a different TRANS2 call. */
2069 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2070 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2071 dont_descend = True;
2074 space_remaining = max_data_bytes;
2075 out_of_space = False;
2077 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2078 bool got_exact_match = False;
2080 /* this is a heuristic to avoid seeking the dirptr except when
2081 absolutely necessary. It allows for a filename of about 40 chars */
2082 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2083 out_of_space = True;
2086 finished = !get_lanman2_dir_entry(ctx,
2089 mask,dirtype,info_level,
2090 requires_resume_key,dont_descend,
2093 space_remaining, &out_of_space,
2095 &last_entry_off, ea_list);
2098 if (finished && out_of_space)
2101 if (!finished && !out_of_space)
2105 * As an optimisation if we know we aren't looking
2106 * for a wildcard name (ie. the name matches the wildcard exactly)
2107 * then we can finish on any (first) match.
2108 * This speeds up large directory searches. JRA.
2114 /* Ensure space_remaining never goes -ve. */
2115 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2116 space_remaining = 0;
2117 out_of_space = true;
2119 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2123 /* Check if we can close the dirptr */
2124 if(close_after_first || (finished && close_if_end)) {
2125 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2126 dptr_close(&dptr_num);
2130 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2131 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2132 * the protocol level is less than NT1. Tested with smbclient. JRA.
2133 * This should fix the OS/2 client bug #2335.
2136 if(numentries == 0) {
2137 dptr_close(&dptr_num);
2138 if (Protocol < PROTOCOL_NT1) {
2139 reply_doserror(req, ERRDOS, ERRnofiles);
2142 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2143 ERRDOS, ERRbadfile);
2148 /* At this point pdata points to numentries directory entries. */
2150 /* Set up the return parameter block */
2151 SSVAL(params,0,dptr_num);
2152 SSVAL(params,2,numentries);
2153 SSVAL(params,4,finished);
2154 SSVAL(params,6,0); /* Never an EA error */
2155 SSVAL(params,8,last_entry_off);
2157 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2160 if ((! *directory) && dptr_path(dptr_num)) {
2161 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2163 reply_nterror(req, NT_STATUS_NO_MEMORY);
2167 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2168 smb_fn_name(req->cmd),
2169 mask, directory, dirtype, numentries ) );
2172 * Force a name mangle here to ensure that the
2173 * mask as an 8.3 name is top of the mangled cache.
2174 * The reasons for this are subtle. Don't remove
2175 * this code unless you know what you are doing
2176 * (see PR#13758). JRA.
2179 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2180 char mangled_name[13];
2181 name_to_8_3(mask, mangled_name, True, conn->params);
2187 /****************************************************************************
2188 Reply to a TRANS2_FINDNEXT.
2189 ****************************************************************************/
2191 static void call_trans2findnext(connection_struct *conn,
2192 struct smb_request *req,
2193 char **pparams, int total_params,
2194 char **ppdata, int total_data,
2195 unsigned int max_data_bytes)
2197 /* We must be careful here that we don't return more than the
2198 allowed number of data bytes. If this means returning fewer than
2199 maxentries then so be it. We assume that the redirector has
2200 enough room for the fixed number of parameter bytes it has
2202 char *params = *pparams;
2203 char *pdata = *ppdata;
2209 uint16 findnext_flags;
2210 bool close_after_request;
2212 bool requires_resume_key;
2214 bool mask_contains_wcard = False;
2215 char *resume_name = NULL;
2216 const char *mask = NULL;
2217 const char *directory = NULL;
2221 int i, last_entry_off=0;
2222 bool finished = False;
2223 bool dont_descend = False;
2224 bool out_of_space = False;
2225 int space_remaining;
2226 struct ea_list *ea_list = NULL;
2227 NTSTATUS ntstatus = NT_STATUS_OK;
2228 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2229 TALLOC_CTX *ctx = talloc_tos();
2231 if (total_params < 13) {
2232 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2236 dptr_num = SVAL(params,0);
2237 maxentries = SVAL(params,2);
2238 info_level = SVAL(params,4);
2239 resume_key = IVAL(params,6);
2240 findnext_flags = SVAL(params,10);
2241 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2242 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2243 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2244 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2246 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2248 total_params - 12, STR_TERMINATE, &ntstatus,
2249 &mask_contains_wcard);
2250 if (!NT_STATUS_IS_OK(ntstatus)) {
2251 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2252 complain (it thinks we're asking for the directory above the shared
2253 path or an invalid name). Catch this as the resume name is only compared, never used in
2254 a file access. JRA. */
2255 srvstr_pull_talloc(ctx, params, req->flags2,
2256 &resume_name, params+12,
2260 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2261 reply_nterror(req, ntstatus);
2266 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2267 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2268 resume_key = %d resume name = %s continue=%d level = %d\n",
2269 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2270 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2273 /* W2K3 seems to treat zero as 1. */
2277 switch (info_level) {
2278 case SMB_FIND_INFO_STANDARD:
2279 case SMB_FIND_EA_SIZE:
2280 case SMB_FIND_EA_LIST:
2281 case SMB_FIND_FILE_DIRECTORY_INFO:
2282 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2283 case SMB_FIND_FILE_NAMES_INFO:
2284 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2285 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2286 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2288 case SMB_FIND_FILE_UNIX:
2289 case SMB_FIND_FILE_UNIX_INFO2:
2290 /* Always use filesystem for UNIX mtime query. */
2291 ask_sharemode = false;
2292 if (!lp_unix_extensions()) {
2293 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2298 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2302 if (info_level == SMB_FIND_EA_LIST) {
2305 if (total_data < 4) {
2306 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2310 ea_size = IVAL(pdata,0);
2311 if (ea_size != total_data) {
2312 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2313 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2314 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2318 if (!lp_ea_support(SNUM(conn))) {
2319 reply_doserror(req, ERRDOS, ERReasnotsupported);
2323 /* Pull out the list of names. */
2324 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2331 *ppdata = (char *)SMB_REALLOC(
2332 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2333 if(*ppdata == NULL) {
2334 reply_nterror(req, NT_STATUS_NO_MEMORY);
2339 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2341 /* Realloc the params space */
2342 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2343 if(*pparams == NULL ) {
2344 reply_nterror(req, NT_STATUS_NO_MEMORY);
2350 /* Check that the dptr is valid */
2351 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2352 reply_doserror(req, ERRDOS, ERRnofiles);
2356 string_set(&conn->dirpath,dptr_path(dptr_num));
2358 /* Get the wildcard mask from the dptr */
2359 if((p = dptr_wcard(dptr_num))== NULL) {
2360 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2361 reply_doserror(req, ERRDOS, ERRnofiles);
2366 directory = conn->dirpath;
2368 /* Get the attr mask from the dptr */
2369 dirtype = dptr_attr(dptr_num);
2371 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2372 dptr_num, mask, dirtype,
2374 dptr_TellDir(conn->dirptr)));
2376 /* We don't need to check for VOL here as this is returned by
2377 a different TRANS2 call. */
2379 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2380 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2381 dont_descend = True;
2384 space_remaining = max_data_bytes;
2385 out_of_space = False;
2388 * Seek to the correct position. We no longer use the resume key but
2389 * depend on the last file name instead.
2392 if(*resume_name && !continue_bit) {
2395 long current_pos = 0;
2397 * Remember, name_to_8_3 is called by
2398 * get_lanman2_dir_entry(), so the resume name
2399 * could be mangled. Ensure we check the unmangled name.
2402 if (mangle_is_mangled(resume_name, conn->params)) {
2403 char *new_resume_name = NULL;
2404 mangle_lookup_name_from_8_3(ctx,
2408 if (new_resume_name) {
2409 resume_name = new_resume_name;
2414 * Fix for NT redirector problem triggered by resume key indexes
2415 * changing between directory scans. We now return a resume key of 0
2416 * and instead look for the filename to continue from (also given
2417 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2418 * findfirst/findnext (as is usual) then the directory pointer
2419 * should already be at the correct place.
2422 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2423 } /* end if resume_name && !continue_bit */
2425 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2426 bool got_exact_match = False;
2428 /* this is a heuristic to avoid seeking the dirptr except when
2429 absolutely necessary. It allows for a filename of about 40 chars */
2430 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2431 out_of_space = True;
2434 finished = !get_lanman2_dir_entry(ctx,
2437 mask,dirtype,info_level,
2438 requires_resume_key,dont_descend,
2441 space_remaining, &out_of_space,
2443 &last_entry_off, ea_list);
2446 if (finished && out_of_space)
2449 if (!finished && !out_of_space)
2453 * As an optimisation if we know we aren't looking
2454 * for a wildcard name (ie. the name matches the wildcard exactly)
2455 * then we can finish on any (first) match.
2456 * This speeds up large directory searches. JRA.
2462 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2465 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2466 smb_fn_name(req->cmd),
2467 mask, directory, dirtype, numentries ) );
2469 /* Check if we can close the dirptr */
2470 if(close_after_request || (finished && close_if_end)) {
2471 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2472 dptr_close(&dptr_num); /* This frees up the saved mask */
2475 /* Set up the return parameter block */
2476 SSVAL(params,0,numentries);
2477 SSVAL(params,2,finished);
2478 SSVAL(params,4,0); /* Never an EA error */
2479 SSVAL(params,6,last_entry_off);
2481 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2487 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2489 E_md4hash(lp_servicename(SNUM(conn)),objid);
2493 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2495 SMB_ASSERT(extended_info != NULL);
2497 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2498 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2499 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2500 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2501 #ifdef SAMBA_VERSION_REVISION
2502 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2504 extended_info->samba_subversion = 0;
2505 #ifdef SAMBA_VERSION_RC_RELEASE
2506 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2508 #ifdef SAMBA_VERSION_PRE_RELEASE
2509 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2512 #ifdef SAMBA_VERSION_VENDOR_PATCH
2513 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2515 extended_info->samba_gitcommitdate = 0;
2516 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2517 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2520 memset(extended_info->samba_version_string, 0,
2521 sizeof(extended_info->samba_version_string));
2523 snprintf (extended_info->samba_version_string,
2524 sizeof(extended_info->samba_version_string),
2525 "%s", samba_version_string());
2528 /****************************************************************************
2529 Reply to a TRANS2_QFSINFO (query filesystem info).
2530 ****************************************************************************/
2532 static void call_trans2qfsinfo(connection_struct *conn,
2533 struct smb_request *req,
2534 char **pparams, int total_params,
2535 char **ppdata, int total_data,
2536 unsigned int max_data_bytes)
2538 char *pdata, *end_data;
2539 char *params = *pparams;
2543 const char *vname = volume_label(SNUM(conn));
2544 int snum = SNUM(conn);
2545 char *fstype = lp_fstype(SNUM(conn));
2546 uint32 additional_flags = 0;
2548 if (total_params < 2) {
2549 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2553 info_level = SVAL(params,0);
2556 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2557 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2558 "info level (0x%x) on IPC$.\n",
2559 (unsigned int)info_level));
2560 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2565 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2566 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2567 DEBUG(0,("call_trans2qfsinfo: encryption required "
2568 "and info level 0x%x sent.\n",
2569 (unsigned int)info_level));
2570 exit_server_cleanly("encryption required "
2576 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2578 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2579 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2580 reply_doserror(req, ERRSRV, ERRinvdevice);
2584 *ppdata = (char *)SMB_REALLOC(
2585 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2586 if (*ppdata == NULL ) {
2587 reply_nterror(req, NT_STATUS_NO_MEMORY);
2592 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2593 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2595 switch (info_level) {
2596 case SMB_INFO_ALLOCATION:
2598 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2600 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2601 reply_unixerror(req, ERRHRD, ERRgeneral);
2605 block_size = lp_block_size(snum);
2606 if (bsize < block_size) {
2607 uint64_t factor = block_size/bsize;
2612 if (bsize > block_size) {
2613 uint64_t factor = bsize/block_size;
2618 bytes_per_sector = 512;
2619 sectors_per_unit = bsize/bytes_per_sector;
2621 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2622 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2623 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2625 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2626 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2627 SIVAL(pdata,l1_cUnit,dsize);
2628 SIVAL(pdata,l1_cUnitAvail,dfree);
2629 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2633 case SMB_INFO_VOLUME:
2634 /* Return volume name */
2636 * Add volume serial number - hash of a combination of
2637 * the called hostname and the service name.
2639 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2641 * Win2k3 and previous mess this up by sending a name length
2642 * one byte short. I believe only older clients (OS/2 Win9x) use
2643 * this call so try fixing this by adding a terminating null to
2644 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2648 pdata+l2_vol_szVolLabel, vname,
2649 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2650 STR_NOALIGN|STR_TERMINATE);
2651 SCVAL(pdata,l2_vol_cch,len);
2652 data_len = l2_vol_szVolLabel + len;
2653 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2654 (unsigned)st.st_ctime, len, vname));
2657 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2658 case SMB_FS_ATTRIBUTE_INFORMATION:
2660 additional_flags = 0;
2661 #if defined(HAVE_SYS_QUOTAS)
2662 additional_flags |= FILE_VOLUME_QUOTAS;
2665 if(lp_nt_acl_support(SNUM(conn))) {
2666 additional_flags |= FILE_PERSISTENT_ACLS;
2669 /* Capabilities are filled in at connection time through STATVFS call */
2670 additional_flags |= conn->fs_capabilities;
2672 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2673 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2674 additional_flags); /* FS ATTRIBUTES */
2676 SIVAL(pdata,4,255); /* Max filename component length */
2677 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2678 and will think we can't do long filenames */
2679 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2680 PTR_DIFF(end_data, pdata+12),
2683 data_len = 12 + len;
2686 case SMB_QUERY_FS_LABEL_INFO:
2687 case SMB_FS_LABEL_INFORMATION:
2688 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2689 PTR_DIFF(end_data, pdata+4), 0);
2694 case SMB_QUERY_FS_VOLUME_INFO:
2695 case SMB_FS_VOLUME_INFORMATION:
2698 * Add volume serial number - hash of a combination of
2699 * the called hostname and the service name.
2701 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2702 (str_checksum(get_local_machine_name())<<16));
2704 /* Max label len is 32 characters. */
2705 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2706 PTR_DIFF(end_data, pdata+18),
2708 SIVAL(pdata,12,len);
2711 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2712 (int)strlen(vname),vname, lp_servicename(snum)));
2715 case SMB_QUERY_FS_SIZE_INFO:
2716 case SMB_FS_SIZE_INFORMATION:
2718 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2720 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2721 reply_unixerror(req, ERRHRD, ERRgeneral);
2724 block_size = lp_block_size(snum);
2725 if (bsize < block_size) {
2726 uint64_t factor = block_size/bsize;
2731 if (bsize > block_size) {
2732 uint64_t factor = bsize/block_size;
2737 bytes_per_sector = 512;
2738 sectors_per_unit = bsize/bytes_per_sector;
2739 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2740 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2741 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2742 SBIG_UINT(pdata,0,dsize);
2743 SBIG_UINT(pdata,8,dfree);
2744 SIVAL(pdata,16,sectors_per_unit);
2745 SIVAL(pdata,20,bytes_per_sector);
2749 case SMB_FS_FULL_SIZE_INFORMATION:
2751 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2753 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2754 reply_unixerror(req, ERRHRD, ERRgeneral);
2757 block_size = lp_block_size(snum);
2758 if (bsize < block_size) {
2759 uint64_t factor = block_size/bsize;
2764 if (bsize > block_size) {
2765 uint64_t factor = bsize/block_size;
2770 bytes_per_sector = 512;
2771 sectors_per_unit = bsize/bytes_per_sector;
2772 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2773 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2774 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2775 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2776 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2777 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2778 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2779 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2783 case SMB_QUERY_FS_DEVICE_INFO:
2784 case SMB_FS_DEVICE_INFORMATION:
2786 SIVAL(pdata,0,0); /* dev type */
2787 SIVAL(pdata,4,0); /* characteristics */
2790 #ifdef HAVE_SYS_QUOTAS
2791 case SMB_FS_QUOTA_INFORMATION:
2793 * what we have to send --metze:
2795 * Unknown1: 24 NULL bytes
2796 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2797 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2798 * Quota Flags: 2 byte :
2799 * Unknown3: 6 NULL bytes
2803 * details for Quota Flags:
2805 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2806 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2807 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2808 * 0x0001 Enable Quotas: enable quota for this fs
2812 /* we need to fake up a fsp here,
2813 * because its not send in this call
2816 SMB_NTQUOTA_STRUCT quotas;
2819 ZERO_STRUCT(quotas);
2825 if (conn->server_info->utok.uid != 0) {
2826 DEBUG(0,("set_user_quota: access_denied "
2827 "service [%s] user [%s]\n",
2828 lp_servicename(SNUM(conn)),
2829 conn->server_info->unix_name));
2830 reply_doserror(req, ERRDOS, ERRnoaccess);
2834 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2835 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2836 reply_doserror(req, ERRSRV, ERRerror);
2842 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2844 /* Unknown1 24 NULL bytes*/
2845 SBIG_UINT(pdata,0,(uint64_t)0);
2846 SBIG_UINT(pdata,8,(uint64_t)0);
2847 SBIG_UINT(pdata,16,(uint64_t)0);
2849 /* Default Soft Quota 8 bytes */
2850 SBIG_UINT(pdata,24,quotas.softlim);
2852 /* Default Hard Quota 8 bytes */
2853 SBIG_UINT(pdata,32,quotas.hardlim);
2855 /* Quota flag 2 bytes */
2856 SSVAL(pdata,40,quotas.qflags);
2858 /* Unknown3 6 NULL bytes */
2864 #endif /* HAVE_SYS_QUOTAS */
2865 case SMB_FS_OBJECTID_INFORMATION:
2867 unsigned char objid[16];
2868 struct smb_extended_info extended_info;
2869 memcpy(pdata,create_volume_objectid(conn, objid),16);
2870 samba_extended_info_version (&extended_info);
2871 SIVAL(pdata,16,extended_info.samba_magic);
2872 SIVAL(pdata,20,extended_info.samba_version);
2873 SIVAL(pdata,24,extended_info.samba_subversion);
2874 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2875 memcpy(pdata+36,extended_info.samba_version_string,28);
2881 * Query the version and capabilities of the CIFS UNIX extensions
2885 case SMB_QUERY_CIFS_UNIX_INFO:
2887 bool large_write = lp_min_receive_file_size() &&
2888 !srv_is_signing_active();
2889 bool large_read = !srv_is_signing_active();
2890 int encrypt_caps = 0;
2892 if (!lp_unix_extensions()) {
2893 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2897 switch (conn->encrypt_level) {
2903 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2906 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2907 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2908 large_write = false;
2914 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2915 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2917 /* We have POSIX ACLs, pathname, encryption,
2918 * large read/write, and locking capability. */
2920 SBIG_UINT(pdata,4,((uint64_t)(
2921 CIFS_UNIX_POSIX_ACLS_CAP|
2922 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2923 CIFS_UNIX_FCNTL_LOCKS_CAP|
2924 CIFS_UNIX_EXTATTR_CAP|
2925 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2927 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2929 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2933 case SMB_QUERY_POSIX_FS_INFO:
2936 vfs_statvfs_struct svfs;
2938 if (!lp_unix_extensions()) {
2939 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2943 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2947 SIVAL(pdata,0,svfs.OptimalTransferSize);
2948 SIVAL(pdata,4,svfs.BlockSize);
2949 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2950 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2951 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2952 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2953 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2954 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2955 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2957 } else if (rc == EOPNOTSUPP) {
2958 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2960 #endif /* EOPNOTSUPP */
2962 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2963 reply_doserror(req, ERRSRV, ERRerror);
2969 case SMB_QUERY_POSIX_WHOAMI:
2975 if (!lp_unix_extensions()) {
2976 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2980 if (max_data_bytes < 40) {
2981 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
2985 /* We ARE guest if global_sid_Builtin_Guests is
2986 * in our list of SIDs.
2988 if (nt_token_check_sid(&global_sid_Builtin_Guests,
2989 conn->server_info->ptok)) {
2990 flags |= SMB_WHOAMI_GUEST;
2993 /* We are NOT guest if global_sid_Authenticated_Users
2994 * is in our list of SIDs.
2996 if (nt_token_check_sid(&global_sid_Authenticated_Users,
2997 conn->server_info->ptok)) {
2998 flags &= ~SMB_WHOAMI_GUEST;
3001 /* NOTE: 8 bytes for UID/GID, irrespective of native
3002 * platform size. This matches
3003 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3005 data_len = 4 /* flags */
3012 + 4 /* pad/reserved */
3013 + (conn->server_info->utok.ngroups * 8)
3015 + (conn->server_info->ptok->num_sids *
3019 SIVAL(pdata, 0, flags);
3020 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3022 (uint64_t)conn->server_info->utok.uid);
3023 SBIG_UINT(pdata, 16,
3024 (uint64_t)conn->server_info->utok.gid);
3027 if (data_len >= max_data_bytes) {
3028 /* Potential overflow, skip the GIDs and SIDs. */
3030 SIVAL(pdata, 24, 0); /* num_groups */
3031 SIVAL(pdata, 28, 0); /* num_sids */
3032 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3033 SIVAL(pdata, 36, 0); /* reserved */
3039 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3040 SIVAL(pdata, 28, conn->server_info->num_sids);
3042 /* We walk the SID list twice, but this call is fairly
3043 * infrequent, and I don't expect that it's performance
3044 * sensitive -- jpeach
3046 for (i = 0, sid_bytes = 0;
3047 i < conn->server_info->ptok->num_sids; ++i) {
3048 sid_bytes += ndr_size_dom_sid(
3049 &conn->server_info->ptok->user_sids[i],
3054 /* SID list byte count */
3055 SIVAL(pdata, 32, sid_bytes);
3057 /* 4 bytes pad/reserved - must be zero */
3058 SIVAL(pdata, 36, 0);
3062 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3063 SBIG_UINT(pdata, data_len,
3064 (uint64_t)conn->server_info->utok.groups[i]);
3070 i < conn->server_info->ptok->num_sids; ++i) {
3071 int sid_len = ndr_size_dom_sid(
3072 &conn->server_info->ptok->user_sids[i],
3076 sid_linearize(pdata + data_len, sid_len,
3077 &conn->server_info->ptok->user_sids[i]);
3078 data_len += sid_len;
3084 case SMB_MAC_QUERY_FS_INFO:
3086 * Thursby MAC extension... ONLY on NTFS filesystems
3087 * once we do streams then we don't need this
3089 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3091 SIVAL(pdata,84,0x100); /* Don't support mac... */
3096 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3101 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3104 DEBUG( 4, ( "%s info_level = %d\n",
3105 smb_fn_name(req->cmd), info_level) );
3110 /****************************************************************************
3111 Reply to a TRANS2_SETFSINFO (set filesystem info).
3112 ****************************************************************************/
3114 static void call_trans2setfsinfo(connection_struct *conn,
3115 struct smb_request *req,
3116 char **pparams, int total_params,
3117 char **ppdata, int total_data,
3118 unsigned int max_data_bytes)
3120 char *pdata = *ppdata;
3121 char *params = *pparams;
3124 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3127 if (total_params < 4) {
3128 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3130 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3134 info_level = SVAL(params,2);
3137 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3138 info_level != SMB_SET_CIFS_UNIX_INFO) {
3139 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3140 "info level (0x%x) on IPC$.\n",
3141 (unsigned int)info_level));
3142 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3147 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3148 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3149 DEBUG(0,("call_trans2setfsinfo: encryption required "
3150 "and info level 0x%x sent.\n",
3151 (unsigned int)info_level));
3152 exit_server_cleanly("encryption required "
3158 switch(info_level) {
3159 case SMB_SET_CIFS_UNIX_INFO:
3161 uint16 client_unix_major;
3162 uint16 client_unix_minor;
3163 uint32 client_unix_cap_low;
3164 uint32 client_unix_cap_high;
3166 if (!lp_unix_extensions()) {
3168 NT_STATUS_INVALID_LEVEL);
3172 /* There should be 12 bytes of capabilities set. */
3173 if (total_data < 8) {
3176 NT_STATUS_INVALID_PARAMETER);
3179 client_unix_major = SVAL(pdata,0);
3180 client_unix_minor = SVAL(pdata,2);
3181 client_unix_cap_low = IVAL(pdata,4);
3182 client_unix_cap_high = IVAL(pdata,8);
3183 /* Just print these values for now. */
3184 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3185 cap_low = 0x%x, cap_high = 0x%x\n",
3186 (unsigned int)client_unix_major,
3187 (unsigned int)client_unix_minor,
3188 (unsigned int)client_unix_cap_low,
3189 (unsigned int)client_unix_cap_high ));
3191 /* Here is where we must switch to posix pathname processing... */
3192 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3193 lp_set_posix_pathnames();
3194 mangle_change_to_posix();
3197 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3198 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3199 /* Client that knows how to do posix locks,
3200 * but not posix open/mkdir operations. Set a
3201 * default type for read/write checks. */
3203 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3209 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3212 size_t param_len = 0;
3213 size_t data_len = total_data;
3215 if (!lp_unix_extensions()) {
3218 NT_STATUS_INVALID_LEVEL);
3222 if (lp_smb_encrypt(SNUM(conn)) == false) {
3225 NT_STATUS_NOT_SUPPORTED);
3229 DEBUG( 4,("call_trans2setfsinfo: "
3230 "request transport encryption.\n"));
3232 status = srv_request_encryption_setup(conn,
3233 (unsigned char **)ppdata,
3235 (unsigned char **)pparams,
3238 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3239 !NT_STATUS_IS_OK(status)) {
3240 reply_nterror(req, status);
3244 send_trans2_replies(conn, req,
3251 if (NT_STATUS_IS_OK(status)) {
3252 /* Server-side transport
3253 * encryption is now *on*. */
3254 status = srv_encryption_start(conn);
3255 if (!NT_STATUS_IS_OK(status)) {
3256 exit_server_cleanly(
3257 "Failure in setting "
3258 "up encrypted transport");
3264 case SMB_FS_QUOTA_INFORMATION:
3266 files_struct *fsp = NULL;
3267 SMB_NTQUOTA_STRUCT quotas;
3269 ZERO_STRUCT(quotas);
3272 if ((conn->server_info->utok.uid != 0)
3273 ||!CAN_WRITE(conn)) {
3274 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3275 lp_servicename(SNUM(conn)),
3276 conn->server_info->unix_name));
3277 reply_doserror(req, ERRSRV, ERRaccess);
3281 /* note: normaly there're 48 bytes,
3282 * but we didn't use the last 6 bytes for now
3285 fsp = file_fsp(req, SVAL(params,0));
3287 if (!check_fsp_ntquota_handle(conn, req,
3289 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3291 req, NT_STATUS_INVALID_HANDLE);
3295 if (total_data < 42) {
3296 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3300 NT_STATUS_INVALID_PARAMETER);
3304 /* unknown_1 24 NULL bytes in pdata*/
3306 /* the soft quotas 8 bytes (uint64_t)*/
3307 quotas.softlim = (uint64_t)IVAL(pdata,24);
3308 #ifdef LARGE_SMB_OFF_T
3309 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3310 #else /* LARGE_SMB_OFF_T */
3311 if ((IVAL(pdata,28) != 0)&&
3312 ((quotas.softlim != 0xFFFFFFFF)||
3313 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3314 /* more than 32 bits? */
3317 NT_STATUS_INVALID_PARAMETER);
3320 #endif /* LARGE_SMB_OFF_T */
3322 /* the hard quotas 8 bytes (uint64_t)*/
3323 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3324 #ifdef LARGE_SMB_OFF_T
3325 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3326 #else /* LARGE_SMB_OFF_T */
3327 if ((IVAL(pdata,36) != 0)&&
3328 ((quotas.hardlim != 0xFFFFFFFF)||
3329 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3330 /* more than 32 bits? */
3333 NT_STATUS_INVALID_PARAMETER);
3336 #endif /* LARGE_SMB_OFF_T */
3338 /* quota_flags 2 bytes **/
3339 quotas.qflags = SVAL(pdata,40);
3341 /* unknown_2 6 NULL bytes follow*/
3343 /* now set the quotas */
3344 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3345 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3346 reply_doserror(req, ERRSRV, ERRerror);
3353 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3355 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3361 * sending this reply works fine,
3362 * but I'm not sure it's the same
3363 * like windows do...
3366 reply_outbuf(req, 10, 0);
3369 #if defined(HAVE_POSIX_ACLS)
3370 /****************************************************************************
3371 Utility function to count the number of entries in a POSIX acl.
3372 ****************************************************************************/
3374 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3376 unsigned int ace_count = 0;
3377 int entry_id = SMB_ACL_FIRST_ENTRY;
3378 SMB_ACL_ENTRY_T entry;
3380 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3382 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3383 entry_id = SMB_ACL_NEXT_ENTRY;
3390 /****************************************************************************
3391 Utility function to marshall a POSIX acl into wire format.
3392 ****************************************************************************/
3394 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3396 int entry_id = SMB_ACL_FIRST_ENTRY;
3397 SMB_ACL_ENTRY_T entry;
3399 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3400 SMB_ACL_TAG_T tagtype;
3401 SMB_ACL_PERMSET_T permset;
3402 unsigned char perms = 0;
3403 unsigned int own_grp;
3406 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3407 entry_id = SMB_ACL_NEXT_ENTRY;
3410 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3411 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3415 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3416 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3420 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3421 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3422 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3424 SCVAL(pdata,1,perms);
3427 case SMB_ACL_USER_OBJ:
3428 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3429 own_grp = (unsigned int)pst->st_uid;
3430 SIVAL(pdata,2,own_grp);
3435 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3437 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3440 own_grp = (unsigned int)*puid;
3441 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3442 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3443 SIVAL(pdata,2,own_grp);
3447 case SMB_ACL_GROUP_OBJ:
3448 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3449 own_grp = (unsigned int)pst->st_gid;
3450 SIVAL(pdata,2,own_grp);
3455 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3457 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3460 own_grp = (unsigned int)*pgid;
3461 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3462 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3463 SIVAL(pdata,2,own_grp);
3468 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3469 SIVAL(pdata,2,0xFFFFFFFF);
3470 SIVAL(pdata,6,0xFFFFFFFF);
3473 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3474 SIVAL(pdata,2,0xFFFFFFFF);
3475 SIVAL(pdata,6,0xFFFFFFFF);
3478 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3481 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3488 /****************************************************************************
3489 Store the FILE_UNIX_BASIC info.
3490 ****************************************************************************/
3492 static char *store_file_unix_basic(connection_struct *conn,
3495 const SMB_STRUCT_STAT *psbuf)
3497 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3498 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3500 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3503 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3506 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3507 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3508 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3511 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3515 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3519 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3522 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3526 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3530 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3533 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3537 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3544 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3545 * the chflags(2) (or equivalent) flags.
3547 * XXX: this really should be behind the VFS interface. To do this, we would
3548 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3549 * Each VFS module could then implement its own mapping as appropriate for the
3550 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3552 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3556 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3560 { UF_IMMUTABLE, EXT_IMMUTABLE },
3564 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3568 { UF_HIDDEN, EXT_HIDDEN },
3571 /* Do not remove. We need to guarantee that this array has at least one
3572 * entry to build on HP-UX.
3578 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3579 uint32 *smb_fflags, uint32 *smb_fmask)
3581 #ifdef HAVE_STAT_ST_FLAGS
3584 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3585 *smb_fmask |= info2_flags_map[i].smb_fflag;
3586 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3587 *smb_fflags |= info2_flags_map[i].smb_fflag;
3590 #endif /* HAVE_STAT_ST_FLAGS */
3593 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3594 const uint32 smb_fflags,
3595 const uint32 smb_fmask,
3598 #ifdef HAVE_STAT_ST_FLAGS
3599 uint32 max_fmask = 0;
3602 *stat_fflags = psbuf->st_flags;
3604 /* For each flags requested in smb_fmask, check the state of the
3605 * corresponding flag in smb_fflags and set or clear the matching
3609 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3610 max_fmask |= info2_flags_map[i].smb_fflag;
3611 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3612 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3613 *stat_fflags |= info2_flags_map[i].stat_fflag;
3615 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3620 /* If smb_fmask is asking to set any bits that are not supported by
3621 * our flag mappings, we should fail.
3623 if ((smb_fmask & max_fmask) != smb_fmask) {
3630 #endif /* HAVE_STAT_ST_FLAGS */
3634 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3635 * of file flags and birth (create) time.
3637 static char *store_file_unix_basic_info2(connection_struct *conn,
3640 const SMB_STRUCT_STAT *psbuf)
3642 uint32 file_flags = 0;
3643 uint32 flags_mask = 0;
3645 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3647 /* Create (birth) time 64 bit */
3648 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3651 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3652 SIVAL(pdata, 0, file_flags); /* flags */
3653 SIVAL(pdata, 4, flags_mask); /* mask */
3659 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3660 const struct stream_struct *streams,
3662 unsigned int max_data_bytes,
3663 unsigned int *data_size)
3666 unsigned int ofs = 0;
3668 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3669 unsigned int next_offset;
3671 smb_ucs2_t *namebuf;
3673 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3674 streams[i].name, &namelen) ||
3677 return NT_STATUS_INVALID_PARAMETER;
3681 * name_buf is now null-terminated, we need to marshall as not
3687 SIVAL(data, ofs+4, namelen);
3688 SOFF_T(data, ofs+8, streams[i].size);
3689 SOFF_T(data, ofs+16, streams[i].alloc_size);
3690 memcpy(data+ofs+24, namebuf, namelen);
3691 TALLOC_FREE(namebuf);
3693 next_offset = ofs + 24 + namelen;
3695 if (i == num_streams-1) {
3696 SIVAL(data, ofs, 0);
3699 unsigned int align = ndr_align_size(next_offset, 8);
3701 memset(data+next_offset, 0, align);
3702 next_offset += align;
3704 SIVAL(data, ofs, next_offset - ofs);
3713 return NT_STATUS_OK;
3716 /****************************************************************************
3717 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3718 ****************************************************************************/
3720 static void call_trans2qpipeinfo(connection_struct *conn,
3721 struct smb_request *req,
3722 unsigned int tran_call,
3723 char **pparams, int total_params,
3724 char **ppdata, int total_data,
3725 unsigned int max_data_bytes)
3727 char *params = *pparams;
3728 char *pdata = *ppdata;
3729 unsigned int data_size = 0;
3730 unsigned int param_size = 2;
3735 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3739 if (total_params < 4) {
3740 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3744 fsp = file_fsp(req, SVAL(params,0));
3745 if (!fsp_is_np(fsp)) {
3746 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3750 info_level = SVAL(params,2);
3752 *pparams = (char *)SMB_REALLOC(*pparams,2);
3753 if (*pparams == NULL) {
3754 reply_nterror(req, NT_STATUS_NO_MEMORY);
3759 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3760 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3761 if (*ppdata == NULL ) {
3762 reply_nterror(req, NT_STATUS_NO_MEMORY);
3767 switch (info_level) {
3768 case SMB_FILE_STANDARD_INFORMATION:
3770 SOFF_T(pdata,0,4096LL);
3777 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3781 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3787 /****************************************************************************
3788 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3789 file name or file id).
3790 ****************************************************************************/
3792 static void call_trans2qfilepathinfo(connection_struct *conn,
3793 struct smb_request *req,
3794 unsigned int tran_call,
3795 char **pparams, int total_params,
3796 char **ppdata, int total_data,
3797 unsigned int max_data_bytes)
3799 char *params = *pparams;
3800 char *pdata = *ppdata;
3801 char *dstart, *dend;
3805 SMB_OFF_T file_size=0;
3806 uint64_t allocation_size=0;
3807 unsigned int data_size = 0;
3808 unsigned int param_size = 2;
3809 SMB_STRUCT_STAT sbuf;
3810 char *dos_fname = NULL;
3816 bool delete_pending = False;
3818 time_t create_time, mtime, atime;
3819 struct timespec create_time_ts, mtime_ts, atime_ts;
3820 struct timespec write_time_ts;
3821 files_struct *fsp = NULL;
3822 struct file_id fileid;
3823 struct ea_list *ea_list = NULL;
3824 char *lock_data = NULL;
3825 bool ms_dfs_link = false;
3826 TALLOC_CTX *ctx = talloc_tos();
3829 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3834 ZERO_STRUCT(write_time_ts);
3836 if (tran_call == TRANSACT2_QFILEINFO) {
3837 if (total_params < 4) {
3838 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3843 call_trans2qpipeinfo(conn, req, tran_call,
3844 pparams, total_params,
3850 fsp = file_fsp(req, SVAL(params,0));
3851 info_level = SVAL(params,2);
3853 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3855 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3856 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3860 /* Initial check for valid fsp ptr. */
3861 if (!check_fsp_open(conn, req, fsp)) {
3865 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3867 reply_nterror(req, NT_STATUS_NO_MEMORY);
3871 if(fsp->fake_file_handle) {
3873 * This is actually for the QUOTA_FAKE_FILE --metze
3876 /* We know this name is ok, it's already passed the checks. */
3878 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3880 * This is actually a QFILEINFO on a directory
3881 * handle (returned from an NT SMB). NT5.0 seems
3882 * to do this call. JRA.
3885 if (INFO_LEVEL_IS_UNIX(info_level)) {
3886 /* Always do lstat for UNIX calls. */
3887 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3888 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3889 reply_unixerror(req,ERRDOS,ERRbadpath);
3892 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3893 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3894 reply_unixerror(req, ERRDOS, ERRbadpath);
3898 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3899 get_file_infos(fileid, &delete_pending, &write_time_ts);
3902 * Original code - this is an open file.
3904 if (!check_fsp(conn, req, fsp)) {
3908 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3909 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3910 reply_unixerror(req, ERRDOS, ERRbadfid);
3913 pos = fsp->fh->position_information;
3914 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3915 get_file_infos(fileid, &delete_pending, &write_time_ts);
3919 NTSTATUS status = NT_STATUS_OK;
3922 if (total_params < 7) {
3923 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3927 info_level = SVAL(params,0);
3929 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3931 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3932 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3936 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3938 STR_TERMINATE, &status);
3939 if (!NT_STATUS_IS_OK(status)) {
3940 reply_nterror(req, status);
3944 status = resolve_dfspath(ctx,
3946 req->flags2 & FLAGS2_DFS_PATHNAMES,
3949 if (!NT_STATUS_IS_OK(status)) {
3950 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3951 reply_botherror(req,
3952 NT_STATUS_PATH_NOT_COVERED,
3953 ERRSRV, ERRbadpath);
3955 reply_nterror(req, status);
3959 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3960 if (!NT_STATUS_IS_OK(status)) {
3961 reply_nterror(req, status);
3964 status = check_name(conn, fname);
3965 if (!NT_STATUS_IS_OK(status)) {
3966 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3967 reply_nterror(req, status);
3971 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
3972 && is_ntfs_stream_name(fname)) {
3974 SMB_STRUCT_STAT bsbuf;
3976 status = split_ntfs_stream_name(talloc_tos(), fname,
3978 if (!NT_STATUS_IS_OK(status)) {
3979 DEBUG(10, ("create_file_unixpath: "
3980 "split_ntfs_stream_name failed: %s\n",
3981 nt_errstr(status)));
3982 reply_nterror(req, status);
3986 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
3988 if (INFO_LEVEL_IS_UNIX(info_level)) {
3989 /* Always do lstat for UNIX calls. */
3990 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
3991 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
3992 reply_unixerror(req,ERRDOS,ERRbadpath);
3996 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
3997 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
3998 reply_unixerror(req,ERRDOS,ERRbadpath);
4003 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4004 get_file_infos(fileid, &delete_pending, NULL);
4005 if (delete_pending) {
4006 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4011 if (INFO_LEVEL_IS_UNIX(info_level)) {
4012 /* Always do lstat for UNIX calls. */
4013 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4014 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4015 reply_unixerror(req, ERRDOS, ERRbadpath);
4019 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4020 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4023 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4024 reply_unixerror(req, ERRDOS, ERRbadpath);
4029 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4030 get_file_infos(fileid, &delete_pending, &write_time_ts);
4031 if (delete_pending) {
4032 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4037 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4038 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4042 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4043 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4045 p = strrchr_m(fname,'/');
4052 mode = dos_mode_msdfs(conn,fname,&sbuf);
4054 mode = dos_mode(conn,fname,&sbuf);
4057 mode = FILE_ATTRIBUTE_NORMAL;
4059 nlink = sbuf.st_nlink;
4061 if (nlink && (mode&aDIR)) {
4065 if ((nlink > 0) && delete_pending) {
4069 fullpathname = fname;
4071 file_size = get_file_size_stat(&sbuf);
4073 /* Pull out any data sent here before we realloc. */
4074 switch (info_level) {
4075 case SMB_INFO_QUERY_EAS_FROM_LIST:
4077 /* Pull any EA list from the data portion. */
4080 if (total_data < 4) {
4082 req, NT_STATUS_INVALID_PARAMETER);
4085 ea_size = IVAL(pdata,0);
4087 if (total_data > 0 && ea_size != total_data) {
4088 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4089 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4091 req, NT_STATUS_INVALID_PARAMETER);
4095 if (!lp_ea_support(SNUM(conn))) {
4096 reply_doserror(req, ERRDOS,
4097 ERReasnotsupported);
4101 /* Pull out the list of names. */
4102 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4105 req, NT_STATUS_INVALID_PARAMETER);
4111 case SMB_QUERY_POSIX_LOCK:
4113 if (fsp == NULL || fsp->fh->fd == -1) {
4114 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4118 if (total_data != POSIX_LOCK_DATA_SIZE) {
4120 req, NT_STATUS_INVALID_PARAMETER);
4124 /* Copy the lock range data. */
4125 lock_data = (char *)TALLOC_MEMDUP(
4126 ctx, pdata, total_data);
4128 reply_nterror(req, NT_STATUS_NO_MEMORY);
4136 *pparams = (char *)SMB_REALLOC(*pparams,2);
4137 if (*pparams == NULL) {
4138 reply_nterror(req, NT_STATUS_NO_MEMORY);
4143 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4144 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4145 if (*ppdata == NULL ) {
4146 reply_nterror(req, NT_STATUS_NO_MEMORY);
4151 dend = dstart + data_size - 1;
4153 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4154 mtime_ts = get_mtimespec(&sbuf);
4155 atime_ts = get_atimespec(&sbuf);
4157 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4160 /* Do we have this path open ? */
4162 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4163 fsp1 = file_find_di_first(fileid);
4164 if (fsp1 && fsp1->initial_allocation_size) {
4165 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4169 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4170 mtime_ts = write_time_ts;
4173 if (lp_dos_filetime_resolution(SNUM(conn))) {
4174 dos_filetime_timespec(&create_time_ts);
4175 dos_filetime_timespec(&mtime_ts);
4176 dos_filetime_timespec(&atime_ts);
4179 create_time = convert_timespec_to_time_t(create_time_ts);
4180 mtime = convert_timespec_to_time_t(mtime_ts);
4181 atime = convert_timespec_to_time_t(atime_ts);
4183 /* NT expects the name to be in an exact form of the *full*
4184 filename. See the trans2 torture test */
4185 if (ISDOT(base_name)) {
4186 dos_fname = talloc_strdup(ctx, "\\");
4188 reply_nterror(req, NT_STATUS_NO_MEMORY);
4192 dos_fname = talloc_asprintf(ctx,
4196 reply_nterror(req, NT_STATUS_NO_MEMORY);
4199 string_replace(dos_fname, '/', '\\');
4202 switch (info_level) {
4203 case SMB_INFO_STANDARD:
4204 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4206 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4207 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4208 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4209 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4210 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4211 SSVAL(pdata,l1_attrFile,mode);
4214 case SMB_INFO_QUERY_EA_SIZE:
4216 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4217 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4219 srv_put_dos_date2(pdata,0,create_time);
4220 srv_put_dos_date2(pdata,4,atime);
4221 srv_put_dos_date2(pdata,8,mtime); /* write time */
4222 SIVAL(pdata,12,(uint32)file_size);
4223 SIVAL(pdata,16,(uint32)allocation_size);
4224 SSVAL(pdata,20,mode);
4225 SIVAL(pdata,22,ea_size);
4229 case SMB_INFO_IS_NAME_VALID:
4230 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4231 if (tran_call == TRANSACT2_QFILEINFO) {
4232 /* os/2 needs this ? really ?*/
4233 reply_doserror(req, ERRDOS, ERRbadfunc);
4240 case SMB_INFO_QUERY_EAS_FROM_LIST:
4242 size_t total_ea_len = 0;
4243 struct ea_list *ea_file_list = NULL;
4245 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4247 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4248 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4250 if (!ea_list || (total_ea_len > data_size)) {
4252 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4256 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4260 case SMB_INFO_QUERY_ALL_EAS:
4262 /* We have data_size bytes to put EA's into. */
4263 size_t total_ea_len = 0;
4265 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4267 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4268 if (!ea_list || (total_ea_len > data_size)) {
4270 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4274 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4278 case SMB_FILE_BASIC_INFORMATION:
4279 case SMB_QUERY_FILE_BASIC_INFO:
4281 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4282 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4283 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4285 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4289 put_long_date_timespec(pdata,create_time_ts);
4290 put_long_date_timespec(pdata+8,atime_ts);
4291 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4292 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4293 SIVAL(pdata,32,mode);
4295 DEBUG(5,("SMB_QFBI - "));
4296 DEBUG(5,("create: %s ", ctime(&create_time)));
4297 DEBUG(5,("access: %s ", ctime(&atime)));
4298 DEBUG(5,("write: %s ", ctime(&mtime)));
4299 DEBUG(5,("change: %s ", ctime(&mtime)));
4300 DEBUG(5,("mode: %x\n", mode));
4303 case SMB_FILE_STANDARD_INFORMATION:
4304 case SMB_QUERY_FILE_STANDARD_INFO:
4306 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4308 SOFF_T(pdata,0,allocation_size);
4309 SOFF_T(pdata,8,file_size);
4310 SIVAL(pdata,16,nlink);
4311 SCVAL(pdata,20,delete_pending?1:0);
4312 SCVAL(pdata,21,(mode&aDIR)?1:0);
4313 SSVAL(pdata,22,0); /* Padding. */
4316 case SMB_FILE_EA_INFORMATION:
4317 case SMB_QUERY_FILE_EA_INFO:
4319 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4320 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4322 SIVAL(pdata,0,ea_size);
4326 /* Get the 8.3 name - used if NT SMB was negotiated. */
4327 case SMB_QUERY_FILE_ALT_NAME_INFO:
4328 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4330 char mangled_name[13];
4331 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4332 if (!name_to_8_3(base_name,mangled_name,
4333 True,conn->params)) {
4336 NT_STATUS_NO_MEMORY);
4338 len = srvstr_push(dstart, req->flags2,
4339 pdata+4, mangled_name,
4340 PTR_DIFF(dend, pdata+4),
4342 data_size = 4 + len;
4347 case SMB_QUERY_FILE_NAME_INFO:
4349 this must be *exactly* right for ACLs on mapped drives to work
4351 len = srvstr_push(dstart, req->flags2,
4353 PTR_DIFF(dend, pdata+4),
4355 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4356 data_size = 4 + len;
4360 case SMB_FILE_ALLOCATION_INFORMATION:
4361 case SMB_QUERY_FILE_ALLOCATION_INFO:
4362 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4364 SOFF_T(pdata,0,allocation_size);
4367 case SMB_FILE_END_OF_FILE_INFORMATION:
4368 case SMB_QUERY_FILE_END_OF_FILEINFO:
4369 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4371 SOFF_T(pdata,0,file_size);
4374 case SMB_QUERY_FILE_ALL_INFO:
4375 case SMB_FILE_ALL_INFORMATION:
4377 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4378 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4379 put_long_date_timespec(pdata,create_time_ts);
4380 put_long_date_timespec(pdata+8,atime_ts);
4381 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4382 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4383 SIVAL(pdata,32,mode);
4384 SIVAL(pdata,36,0); /* padding. */
4386 SOFF_T(pdata,0,allocation_size);
4387 SOFF_T(pdata,8,file_size);
4388 SIVAL(pdata,16,nlink);
4389 SCVAL(pdata,20,delete_pending);
4390 SCVAL(pdata,21,(mode&aDIR)?1:0);
4393 SIVAL(pdata,0,ea_size);
4394 pdata += 4; /* EA info */
4395 len = srvstr_push(dstart, req->flags2,
4397 PTR_DIFF(dend, pdata+4),
4401 data_size = PTR_DIFF(pdata,(*ppdata));
4404 case SMB_FILE_INTERNAL_INFORMATION:
4405 /* This should be an index number - looks like
4408 I think this causes us to fail the IFSKIT
4409 BasicFileInformationTest. -tpot */
4411 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4412 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4413 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4417 case SMB_FILE_ACCESS_INFORMATION:
4418 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4420 SIVAL(pdata,0,fsp->access_mask);
4422 /* GENERIC_EXECUTE mapping from Windows */
4423 SIVAL(pdata,0,0x12019F);
4428 case SMB_FILE_NAME_INFORMATION:
4429 /* Pathname with leading '\'. */
4432 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4433 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4434 SIVAL(pdata,0,byte_len);
4435 data_size = 4 + byte_len;
4439 case SMB_FILE_DISPOSITION_INFORMATION:
4440 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4442 SCVAL(pdata,0,delete_pending);
4445 case SMB_FILE_POSITION_INFORMATION:
4446 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4448 SOFF_T(pdata,0,pos);
4451 case SMB_FILE_MODE_INFORMATION:
4452 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4453 SIVAL(pdata,0,mode);
4457 case SMB_FILE_ALIGNMENT_INFORMATION:
4458 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4459 SIVAL(pdata,0,0); /* No alignment needed. */
4464 * NT4 server just returns "invalid query" to this - if we try
4465 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4468 /* The first statement above is false - verified using Thursby
4469 * client against NT4 -- gcolley.
4471 case SMB_QUERY_FILE_STREAM_INFO:
4472 case SMB_FILE_STREAM_INFORMATION: {
4473 unsigned int num_streams;
4474 struct stream_struct *streams;
4477 DEBUG(10,("call_trans2qfilepathinfo: "
4478 "SMB_FILE_STREAM_INFORMATION\n"));
4480 status = SMB_VFS_STREAMINFO(
4481 conn, fsp, fname, talloc_tos(),
4482 &num_streams, &streams);
4484 if (!NT_STATUS_IS_OK(status)) {
4485 DEBUG(10, ("could not get stream info: %s\n",
4486 nt_errstr(status)));
4487 reply_nterror(req, status);
4491 status = marshall_stream_info(num_streams, streams,
4492 pdata, max_data_bytes,
4495 if (!NT_STATUS_IS_OK(status)) {
4496 DEBUG(10, ("marshall_stream_info failed: %s\n",
4497 nt_errstr(status)));
4498 reply_nterror(req, status);
4502 TALLOC_FREE(streams);
4506 case SMB_QUERY_COMPRESSION_INFO:
4507 case SMB_FILE_COMPRESSION_INFORMATION:
4508 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4509 SOFF_T(pdata,0,file_size);
4510 SIVAL(pdata,8,0); /* ??? */
4511 SIVAL(pdata,12,0); /* ??? */
4515 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4516 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4517 put_long_date_timespec(pdata,create_time_ts);
4518 put_long_date_timespec(pdata+8,atime_ts);
4519 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4520 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4521 SOFF_T(pdata,32,allocation_size);
4522 SOFF_T(pdata,40,file_size);
4523 SIVAL(pdata,48,mode);
4524 SIVAL(pdata,52,0); /* ??? */
4528 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4529 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4530 SIVAL(pdata,0,mode);
4536 * CIFS UNIX Extensions.
4539 case SMB_QUERY_FILE_UNIX_BASIC:
4541 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4542 data_size = PTR_DIFF(pdata,(*ppdata));
4546 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4548 for (i=0; i<100; i++)
4549 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4555 case SMB_QUERY_FILE_UNIX_INFO2:
4557 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4558 data_size = PTR_DIFF(pdata,(*ppdata));
4562 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4564 for (i=0; i<100; i++)
4565 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4571 case SMB_QUERY_FILE_UNIX_LINK:
4573 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4576 reply_nterror(req, NT_STATUS_NO_MEMORY);
4580 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4582 if(!S_ISLNK(sbuf.st_mode)) {
4583 reply_unixerror(req, ERRSRV,
4588 reply_unixerror(req, ERRDOS, ERRbadlink);
4591 len = SMB_VFS_READLINK(conn,fullpathname,
4594 reply_unixerror(req, ERRDOS,
4599 len = srvstr_push(dstart, req->flags2,
4601 PTR_DIFF(dend, pdata),
4604 data_size = PTR_DIFF(pdata,(*ppdata));
4609 #if defined(HAVE_POSIX_ACLS)
4610 case SMB_QUERY_POSIX_ACL:
4612 SMB_ACL_T file_acl = NULL;
4613 SMB_ACL_T def_acl = NULL;
4614 uint16 num_file_acls = 0;
4615 uint16 num_def_acls = 0;
4617 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4618 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4620 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4623 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4624 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4628 NT_STATUS_NOT_IMPLEMENTED);
4632 if (S_ISDIR(sbuf.st_mode)) {
4633 if (fsp && fsp->is_directory) {
4634 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4636 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4638 def_acl = free_empty_sys_acl(conn, def_acl);
4641 num_file_acls = count_acl_entries(conn, file_acl);
4642 num_def_acls = count_acl_entries(conn, def_acl);
4644 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4645 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4647 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4648 SMB_POSIX_ACL_HEADER_SIZE) ));
4650 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4653 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4657 NT_STATUS_BUFFER_TOO_SMALL);
4661 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4662 SSVAL(pdata,2,num_file_acls);
4663 SSVAL(pdata,4,num_def_acls);
4664 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4666 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4669 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4672 req, NT_STATUS_INTERNAL_ERROR);
4675 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4677 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4680 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4684 NT_STATUS_INTERNAL_ERROR);
4689 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4692 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4694 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4700 case SMB_QUERY_POSIX_LOCK:
4702 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4706 enum brl_type lock_type;
4708 if (total_data != POSIX_LOCK_DATA_SIZE) {
4710 req, NT_STATUS_INVALID_PARAMETER);
4714 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4715 case POSIX_LOCK_TYPE_READ:
4716 lock_type = READ_LOCK;
4718 case POSIX_LOCK_TYPE_WRITE:
4719 lock_type = WRITE_LOCK;
4721 case POSIX_LOCK_TYPE_UNLOCK:
4723 /* There's no point in asking for an unlock... */
4726 NT_STATUS_INVALID_PARAMETER);
4730 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4731 #if defined(HAVE_LONGLONG)
4732 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4733 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4734 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4735 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4736 #else /* HAVE_LONGLONG */
4737 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4738 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4739 #endif /* HAVE_LONGLONG */
4741 status = query_lock(fsp,
4748 if (ERROR_WAS_LOCK_DENIED(status)) {
4749 /* Here we need to report who has it locked... */
4750 data_size = POSIX_LOCK_DATA_SIZE;
4752 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4753 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4754 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4755 #if defined(HAVE_LONGLONG)
4756 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4757 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4758 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4759 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4760 #else /* HAVE_LONGLONG */
4761 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4762 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4763 #endif /* HAVE_LONGLONG */
4765 } else if (NT_STATUS_IS_OK(status)) {
4766 /* For success we just return a copy of what we sent
4767 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4768 data_size = POSIX_LOCK_DATA_SIZE;
4769 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4770 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4772 reply_nterror(req, status);
4779 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4783 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4789 /****************************************************************************
4790 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4792 ****************************************************************************/
4794 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4795 connection_struct *conn,
4796 const char *oldname_in,
4797 const char *newname_in)
4799 SMB_STRUCT_STAT sbuf1, sbuf2;
4800 char *last_component_oldname = NULL;
4801 char *last_component_newname = NULL;
4802 char *oldname = NULL;
4803 char *newname = NULL;
4804 NTSTATUS status = NT_STATUS_OK;
4809 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4810 &last_component_oldname, &sbuf1);
4811 if (!NT_STATUS_IS_OK(status)) {
4815 status = check_name(conn, oldname);
4816 if (!NT_STATUS_IS_OK(status)) {
4820 /* source must already exist. */
4821 if (!VALID_STAT(sbuf1)) {
4822 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4825 status = unix_convert(ctx, conn, newname_in, False, &newname,
4826 &last_component_newname, &sbuf2);
4827 if (!NT_STATUS_IS_OK(status)) {
4831 status = check_name(conn, newname);
4832 if (!NT_STATUS_IS_OK(status)) {
4836 /* Disallow if newname already exists. */
4837 if (VALID_STAT(sbuf2)) {
4838 return NT_STATUS_OBJECT_NAME_COLLISION;
4841 /* No links from a directory. */
4842 if (S_ISDIR(sbuf1.st_mode)) {
4843 return NT_STATUS_FILE_IS_A_DIRECTORY;
4846 /* Ensure this is within the share. */
4847 status = check_reduced_name(conn, oldname);
4848 if (!NT_STATUS_IS_OK(status)) {
4852 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4854 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4855 status = map_nt_error_from_unix(errno);
4856 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4857 nt_errstr(status), newname, oldname));
4863 /****************************************************************************
4864 Deal with setting the time from any of the setfilepathinfo functions.
4865 ****************************************************************************/
4867 NTSTATUS smb_set_file_time(connection_struct *conn,
4870 const SMB_STRUCT_STAT *psbuf,
4871 struct smb_file_time *ft,
4872 bool setting_write_time)
4875 FILE_NOTIFY_CHANGE_LAST_ACCESS
4876 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4878 if (!VALID_STAT(*psbuf)) {
4879 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4882 /* get some defaults (no modifications) if any info is zero or -1. */
4883 if (null_timespec(ft->atime)) {
4884 ft->atime= get_atimespec(psbuf);
4885 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4888 if (null_timespec(ft->mtime)) {
4889 ft->mtime = get_mtimespec(psbuf);
4890 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4893 if (!setting_write_time) {
4894 /* ft->mtime comes from change time, not write time. */
4895 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4898 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4899 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4900 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4901 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4902 if (!null_timespec(ft->create_time)) {
4903 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4904 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4908 * Try and set the times of this file if
4909 * they are different from the current values.
4913 struct timespec mts = get_mtimespec(psbuf);
4914 struct timespec ats = get_atimespec(psbuf);
4915 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4916 (timespec_compare(&ft->mtime, &mts) == 0)) {
4917 return NT_STATUS_OK;
4921 if (setting_write_time) {
4923 * This was a setfileinfo on an open file.
4924 * NT does this a lot. We also need to
4925 * set the time here, as it can be read by
4926 * FindFirst/FindNext and with the patch for bug #2045
4927 * in smbd/fileio.c it ensures that this timestamp is
4928 * kept sticky even after a write. We save the request
4929 * away and will set it on file close and after a write. JRA.
4932 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4933 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4936 if (fsp->base_fsp) {
4937 set_sticky_write_time_fsp(fsp->base_fsp,
4940 set_sticky_write_time_fsp(fsp, ft->mtime);
4943 set_sticky_write_time_path(conn, fname,
4944 vfs_file_id_from_sbuf(conn, psbuf),
4949 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4951 if (fsp && fsp->base_fsp) {
4952 fname = fsp->base_fsp->fsp_name;
4955 if(file_ntimes(conn, fname, ft)!=0) {
4956 return map_nt_error_from_unix(errno);
4958 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4960 return NT_STATUS_OK;
4963 /****************************************************************************
4964 Deal with setting the dosmode from any of the setfilepathinfo functions.
4965 ****************************************************************************/
4967 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4969 SMB_STRUCT_STAT *psbuf,
4972 if (!VALID_STAT(*psbuf)) {
4973 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4977 if (S_ISDIR(psbuf->st_mode)) {
4984 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4986 /* check the mode isn't different, before changing it */
4987 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4989 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4990 fname, (unsigned int)dosmode ));
4992 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4993 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4994 fname, strerror(errno)));
4995 return map_nt_error_from_unix(errno);
4998 return NT_STATUS_OK;
5001 /****************************************************************************
5002 Deal with setting the size from any of the setfilepathinfo functions.
5003 ****************************************************************************/
5005 static NTSTATUS smb_set_file_size(connection_struct *conn,
5006 struct smb_request *req,
5009 SMB_STRUCT_STAT *psbuf,
5012 NTSTATUS status = NT_STATUS_OK;
5013 files_struct *new_fsp = NULL;
5015 if (!VALID_STAT(*psbuf)) {
5016 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5019 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5021 if (size == get_file_size_stat(psbuf)) {
5022 return NT_STATUS_OK;
5025 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5026 fname, (double)size ));
5028 if (fsp && fsp->fh->fd != -1) {
5029 /* Handle based call. */
5030 if (vfs_set_filelen(fsp, size) == -1) {
5031 return map_nt_error_from_unix(errno);
5033 trigger_write_time_update_immediate(fsp);
5034 return NT_STATUS_OK;
5037 status = SMB_VFS_CREATE_FILE(
5040 0, /* root_dir_fid */
5042 0, /* create_file_flags */
5043 FILE_WRITE_ATTRIBUTES, /* access_mask */
5044 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5046 FILE_OPEN, /* create_disposition*/
5047 0, /* create_options */
5048 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5049 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5050 0, /* allocation_size */
5053 &new_fsp, /* result */
5057 if (!NT_STATUS_IS_OK(status)) {
5058 /* NB. We check for open_was_deferred in the caller. */
5062 if (vfs_set_filelen(new_fsp, size) == -1) {
5063 status = map_nt_error_from_unix(errno);
5064 close_file(req, new_fsp,NORMAL_CLOSE);
5068 trigger_write_time_update_immediate(new_fsp);
5069 close_file(req, new_fsp,NORMAL_CLOSE);
5070 return NT_STATUS_OK;
5073 /****************************************************************************
5074 Deal with SMB_INFO_SET_EA.
5075 ****************************************************************************/
5077 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5083 struct ea_list *ea_list = NULL;
5084 TALLOC_CTX *ctx = NULL;
5085 NTSTATUS status = NT_STATUS_OK;
5087 if (total_data < 10) {
5089 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5090 length. They seem to have no effect. Bug #3212. JRA */
5092 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5093 /* We're done. We only get EA info in this call. */
5094 return NT_STATUS_OK;
5097 return NT_STATUS_INVALID_PARAMETER;
5100 if (IVAL(pdata,0) > total_data) {
5101 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5102 IVAL(pdata,0), (unsigned int)total_data));
5103 return NT_STATUS_INVALID_PARAMETER;
5107 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5109 return NT_STATUS_INVALID_PARAMETER;
5111 status = set_ea(conn, fsp, fname, ea_list);
5116 /****************************************************************************
5117 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5118 ****************************************************************************/
5120 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5125 SMB_STRUCT_STAT *psbuf)
5127 NTSTATUS status = NT_STATUS_OK;
5128 bool delete_on_close;
5131 if (total_data < 1) {
5132 return NT_STATUS_INVALID_PARAMETER;
5136 return NT_STATUS_INVALID_HANDLE;
5139 delete_on_close = (CVAL(pdata,0) ? True : False);
5140 dosmode = dos_mode(conn, fname, psbuf);
5142 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5143 "delete_on_close = %u\n",
5145 (unsigned int)dosmode,
5146 (unsigned int)delete_on_close ));
5148 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5150 if (!NT_STATUS_IS_OK(status)) {
5154 /* The set is across all open files on this dev/inode pair. */
5155 if (!set_delete_on_close(fsp, delete_on_close,
5156 &conn->server_info->utok)) {
5157 return NT_STATUS_ACCESS_DENIED;
5159 return NT_STATUS_OK;
5162 /****************************************************************************
5163 Deal with SMB_FILE_POSITION_INFORMATION.
5164 ****************************************************************************/
5166 static NTSTATUS smb_file_position_information(connection_struct *conn,
5171 uint64_t position_information;
5173 if (total_data < 8) {
5174 return NT_STATUS_INVALID_PARAMETER;
5178 /* Ignore on pathname based set. */
5179 return NT_STATUS_OK;
5182 position_information = (uint64_t)IVAL(pdata,0);
5183 #ifdef LARGE_SMB_OFF_T
5184 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5185 #else /* LARGE_SMB_OFF_T */
5186 if (IVAL(pdata,4) != 0) {
5187 /* more than 32 bits? */
5188 return NT_STATUS_INVALID_PARAMETER;
5190 #endif /* LARGE_SMB_OFF_T */
5192 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5193 fsp->fsp_name, (double)position_information ));
5194 fsp->fh->position_information = position_information;
5195 return NT_STATUS_OK;
5198 /****************************************************************************
5199 Deal with SMB_FILE_MODE_INFORMATION.
5200 ****************************************************************************/
5202 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5208 if (total_data < 4) {
5209 return NT_STATUS_INVALID_PARAMETER;
5211 mode = IVAL(pdata,0);
5212 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5213 return NT_STATUS_INVALID_PARAMETER;
5215 return NT_STATUS_OK;
5218 /****************************************************************************
5219 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5220 ****************************************************************************/
5222 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5223 struct smb_request *req,
5228 char *link_target = NULL;
5229 const char *newname = fname;
5230 NTSTATUS status = NT_STATUS_OK;
5231 TALLOC_CTX *ctx = talloc_tos();
5233 /* Set a symbolic link. */
5234 /* Don't allow this if follow links is false. */
5236 if (total_data == 0) {
5237 return NT_STATUS_INVALID_PARAMETER;
5240 if (!lp_symlinks(SNUM(conn))) {
5241 return NT_STATUS_ACCESS_DENIED;
5244 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5245 total_data, STR_TERMINATE);
5248 return NT_STATUS_INVALID_PARAMETER;
5251 /* !widelinks forces the target path to be within the share. */
5252 /* This means we can interpret the target as a pathname. */
5253 if (!lp_widelinks(SNUM(conn))) {
5254 char *rel_name = NULL;
5255 char *last_dirp = NULL;
5257 if (*link_target == '/') {
5258 /* No absolute paths allowed. */
5259 return NT_STATUS_ACCESS_DENIED;
5261 rel_name = talloc_strdup(ctx,newname);
5263 return NT_STATUS_NO_MEMORY;
5265 last_dirp = strrchr_m(rel_name, '/');
5267 last_dirp[1] = '\0';
5269 rel_name = talloc_strdup(ctx,"./");
5271 return NT_STATUS_NO_MEMORY;
5274 rel_name = talloc_asprintf_append(rel_name,
5278 return NT_STATUS_NO_MEMORY;
5281 status = check_name(conn, rel_name);
5282 if (!NT_STATUS_IS_OK(status)) {
5287 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5288 newname, link_target ));
5290 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5291 return map_nt_error_from_unix(errno);
5294 return NT_STATUS_OK;
5297 /****************************************************************************
5298 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5299 ****************************************************************************/
5301 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5302 struct smb_request *req,
5303 const char *pdata, int total_data,
5306 char *oldname = NULL;
5307 TALLOC_CTX *ctx = talloc_tos();
5308 NTSTATUS status = NT_STATUS_OK;
5310 /* Set a hard link. */
5311 if (total_data == 0) {
5312 return NT_STATUS_INVALID_PARAMETER;
5315 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5316 total_data, STR_TERMINATE, &status);
5317 if (!NT_STATUS_IS_OK(status)) {
5321 status = resolve_dfspath(ctx, conn,
5322 req->flags2 & FLAGS2_DFS_PATHNAMES,
5325 if (!NT_STATUS_IS_OK(status)) {
5329 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5332 return hardlink_internals(ctx, conn, oldname, fname);
5335 /****************************************************************************
5336 Deal with SMB_FILE_RENAME_INFORMATION.
5337 ****************************************************************************/
5339 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5340 struct smb_request *req,
5349 char *newname = NULL;
5350 char *base_name = NULL;
5351 bool dest_has_wcard = False;
5352 SMB_STRUCT_STAT sbuf;
5353 char *newname_last_component = NULL;
5354 NTSTATUS status = NT_STATUS_OK;
5356 TALLOC_CTX *ctx = talloc_tos();
5358 if (total_data < 13) {
5359 return NT_STATUS_INVALID_PARAMETER;
5364 overwrite = (CVAL(pdata,0) ? True : False);
5365 root_fid = IVAL(pdata,4);
5366 len = IVAL(pdata,8);
5368 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5369 return NT_STATUS_INVALID_PARAMETER;
5372 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5375 if (!NT_STATUS_IS_OK(status)) {
5379 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5382 status = resolve_dfspath_wcard(ctx, conn,
5383 req->flags2 & FLAGS2_DFS_PATHNAMES,
5387 if (!NT_STATUS_IS_OK(status)) {
5391 /* Check the new name has no '/' characters. */
5392 if (strchr_m(newname, '/')) {
5393 return NT_STATUS_NOT_SUPPORTED;
5396 if (fsp && fsp->base_fsp) {
5397 /* newname must be a stream name. */
5398 if (newname[0] != ':') {
5399 return NT_STATUS_NOT_SUPPORTED;
5401 base_name = talloc_asprintf(ctx, "%s%s",
5402 fsp->base_fsp->fsp_name,
5405 return NT_STATUS_NO_MEMORY;
5408 /* newname must *not* be a stream name. */
5409 if (is_ntfs_stream_name(newname)) {
5410 return NT_STATUS_NOT_SUPPORTED;
5413 /* Create the base directory. */
5414 base_name = talloc_strdup(ctx, fname);
5416 return NT_STATUS_NO_MEMORY;
5418 p = strrchr_m(base_name, '/');
5422 base_name = talloc_strdup(ctx, "./");
5424 return NT_STATUS_NO_MEMORY;
5427 /* Append the new name. */
5428 base_name = talloc_asprintf_append(base_name,
5432 return NT_STATUS_NO_MEMORY;
5435 status = unix_convert(ctx, conn, newname, False,
5437 &newname_last_component,
5440 /* If an error we expect this to be
5441 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5443 if (!NT_STATUS_IS_OK(status)
5444 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5451 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5452 fsp->fnum, fsp->fsp_name, base_name ));
5453 status = rename_internals_fsp(conn, fsp, base_name,
5454 newname_last_component, 0,
5457 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5458 fname, base_name ));
5459 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5460 overwrite, False, dest_has_wcard,
5461 FILE_WRITE_ATTRIBUTES);
5467 /****************************************************************************
5468 Deal with SMB_SET_POSIX_ACL.
5469 ****************************************************************************/
5471 #if defined(HAVE_POSIX_ACLS)
5472 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5477 SMB_STRUCT_STAT *psbuf)
5479 uint16 posix_acl_version;
5480 uint16 num_file_acls;
5481 uint16 num_def_acls;
5482 bool valid_file_acls = True;
5483 bool valid_def_acls = True;
5485 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5486 return NT_STATUS_INVALID_PARAMETER;
5488 posix_acl_version = SVAL(pdata,0);
5489 num_file_acls = SVAL(pdata,2);
5490 num_def_acls = SVAL(pdata,4);
5492 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5493 valid_file_acls = False;
5497 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5498 valid_def_acls = False;
5502 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5503 return NT_STATUS_INVALID_PARAMETER;
5506 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5507 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5508 return NT_STATUS_INVALID_PARAMETER;
5511 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5512 fname ? fname : fsp->fsp_name,
5513 (unsigned int)num_file_acls,
5514 (unsigned int)num_def_acls));
5516 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5517 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5518 return map_nt_error_from_unix(errno);
5521 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5522 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5523 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5524 return map_nt_error_from_unix(errno);
5526 return NT_STATUS_OK;
5530 /****************************************************************************
5531 Deal with SMB_SET_POSIX_LOCK.
5532 ****************************************************************************/
5534 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5535 struct smb_request *req,
5543 bool blocking_lock = False;
5544 enum brl_type lock_type;
5546 NTSTATUS status = NT_STATUS_OK;
5548 if (fsp == NULL || fsp->fh->fd == -1) {
5549 return NT_STATUS_INVALID_HANDLE;
5552 if (total_data != POSIX_LOCK_DATA_SIZE) {
5553 return NT_STATUS_INVALID_PARAMETER;
5556 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5557 case POSIX_LOCK_TYPE_READ:
5558 lock_type = READ_LOCK;
5560 case POSIX_LOCK_TYPE_WRITE:
5561 /* Return the right POSIX-mappable error code for files opened read-only. */
5562 if (!fsp->can_write) {
5563 return NT_STATUS_INVALID_HANDLE;
5565 lock_type = WRITE_LOCK;
5567 case POSIX_LOCK_TYPE_UNLOCK:
5568 lock_type = UNLOCK_LOCK;
5571 return NT_STATUS_INVALID_PARAMETER;
5574 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5575 blocking_lock = False;
5576 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5577 blocking_lock = True;
5579 return NT_STATUS_INVALID_PARAMETER;
5582 if (!lp_blocking_locks(SNUM(conn))) {
5583 blocking_lock = False;
5586 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5587 #if defined(HAVE_LONGLONG)
5588 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5589 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5590 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5591 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5592 #else /* HAVE_LONGLONG */
5593 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5594 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5595 #endif /* HAVE_LONGLONG */
5597 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5598 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5600 (unsigned int)lock_type,
5601 (unsigned int)lock_pid,
5605 if (lock_type == UNLOCK_LOCK) {
5606 status = do_unlock(smbd_messaging_context(),
5613 uint32 block_smbpid;
5615 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5626 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5628 * A blocking lock was requested. Package up
5629 * this smb into a queued request and push it
5630 * onto the blocking lock queue.
5632 if(push_blocking_lock_request(br_lck,
5635 -1, /* infinite timeout. */
5643 TALLOC_FREE(br_lck);
5647 TALLOC_FREE(br_lck);
5653 /****************************************************************************
5654 Deal with SMB_INFO_STANDARD.
5655 ****************************************************************************/
5657 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5662 const SMB_STRUCT_STAT *psbuf)
5664 struct smb_file_time ft;
5667 if (total_data < 12) {
5668 return NT_STATUS_INVALID_PARAMETER;
5672 ft.create_time = interpret_long_date(pdata);
5675 ft.atime = interpret_long_date(pdata + 8);
5678 ft.mtime = interpret_long_date(pdata + 16);
5680 DEBUG(10,("smb_set_info_standard: file %s\n",
5681 fname ? fname : fsp->fsp_name ));
5683 return smb_set_file_time(conn,
5691 /****************************************************************************
5692 Deal with SMB_SET_FILE_BASIC_INFO.
5693 ****************************************************************************/
5695 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5700 SMB_STRUCT_STAT *psbuf)
5702 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5703 struct timespec write_time;
5704 struct timespec changed_time;
5705 struct smb_file_time ft;
5707 NTSTATUS status = NT_STATUS_OK;
5708 bool setting_write_time = true;
5712 if (total_data < 36) {
5713 return NT_STATUS_INVALID_PARAMETER;
5716 /* Set the attributes */
5717 dosmode = IVAL(pdata,32);
5718 status = smb_set_file_dosmode(conn, fname, psbuf, dosmode);
5719 if (!NT_STATUS_IS_OK(status)) {
5725 ft.atime = interpret_long_date(pdata+8);
5727 write_time = interpret_long_date(pdata+16);
5728 changed_time = interpret_long_date(pdata+24);
5731 ft.mtime = timespec_min(&write_time, &changed_time);
5734 ft.create_time = interpret_long_date(pdata);
5736 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5737 !null_timespec(write_time)) {
5738 ft.mtime = write_time;
5741 /* Prefer a defined time to an undefined one. */
5742 if (null_timespec(ft.mtime)) {
5743 if (null_timespec(write_time)) {
5744 ft.mtime = changed_time;
5745 setting_write_time = false;
5747 ft.mtime = write_time;
5751 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5752 fname ? fname : fsp->fsp_name ));
5754 return smb_set_file_time(conn,
5759 setting_write_time);
5762 /****************************************************************************
5763 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5764 ****************************************************************************/
5766 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5767 struct smb_request *req,
5772 SMB_STRUCT_STAT *psbuf)
5774 uint64_t allocation_size = 0;
5775 NTSTATUS status = NT_STATUS_OK;
5776 files_struct *new_fsp = NULL;
5778 if (!VALID_STAT(*psbuf)) {
5779 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5782 if (total_data < 8) {
5783 return NT_STATUS_INVALID_PARAMETER;
5786 allocation_size = (uint64_t)IVAL(pdata,0);
5787 #ifdef LARGE_SMB_OFF_T
5788 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5789 #else /* LARGE_SMB_OFF_T */
5790 if (IVAL(pdata,4) != 0) {
5791 /* more than 32 bits? */
5792 return NT_STATUS_INVALID_PARAMETER;
5794 #endif /* LARGE_SMB_OFF_T */
5796 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5797 fname, (double)allocation_size ));
5799 if (allocation_size) {
5800 allocation_size = smb_roundup(conn, allocation_size);
5803 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5804 fname, (double)allocation_size ));
5806 if (fsp && fsp->fh->fd != -1) {
5807 /* Open file handle. */
5808 /* Only change if needed. */
5809 if (allocation_size != get_file_size_stat(psbuf)) {
5810 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5811 return map_nt_error_from_unix(errno);
5814 /* But always update the time. */
5816 * This is equivalent to a write. Ensure it's seen immediately
5817 * if there are no pending writes.
5819 trigger_write_time_update_immediate(fsp);
5820 return NT_STATUS_OK;
5823 /* Pathname or stat or directory file. */
5825 status = SMB_VFS_CREATE_FILE(
5828 0, /* root_dir_fid */
5830 0, /* create_file_flags */
5831 FILE_WRITE_DATA, /* access_mask */
5832 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5834 FILE_OPEN, /* create_disposition*/
5835 0, /* create_options */
5836 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5837 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5838 0, /* allocation_size */
5841 &new_fsp, /* result */
5845 if (!NT_STATUS_IS_OK(status)) {
5846 /* NB. We check for open_was_deferred in the caller. */
5850 /* Only change if needed. */
5851 if (allocation_size != get_file_size_stat(psbuf)) {
5852 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5853 status = map_nt_error_from_unix(errno);
5854 close_file(req, new_fsp, NORMAL_CLOSE);
5859 /* Changing the allocation size should set the last mod time. */
5861 * This is equivalent to a write. Ensure it's seen immediately
5862 * if there are no pending writes.
5864 trigger_write_time_update_immediate(new_fsp);
5866 close_file(req, new_fsp, NORMAL_CLOSE);
5867 return NT_STATUS_OK;
5870 /****************************************************************************
5871 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5872 ****************************************************************************/
5874 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5875 struct smb_request *req,
5880 SMB_STRUCT_STAT *psbuf)
5884 if (total_data < 8) {
5885 return NT_STATUS_INVALID_PARAMETER;
5888 size = IVAL(pdata,0);
5889 #ifdef LARGE_SMB_OFF_T
5890 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5891 #else /* LARGE_SMB_OFF_T */
5892 if (IVAL(pdata,4) != 0) {
5893 /* more than 32 bits? */
5894 return NT_STATUS_INVALID_PARAMETER;
5896 #endif /* LARGE_SMB_OFF_T */
5897 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5898 "file %s to %.0f\n", fname, (double)size ));
5900 return smb_set_file_size(conn, req,
5907 /****************************************************************************
5908 Allow a UNIX info mknod.
5909 ****************************************************************************/
5911 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5915 SMB_STRUCT_STAT *psbuf)
5917 uint32 file_type = IVAL(pdata,56);
5918 #if defined(HAVE_MAKEDEV)
5919 uint32 dev_major = IVAL(pdata,60);
5920 uint32 dev_minor = IVAL(pdata,68);
5922 SMB_DEV_T dev = (SMB_DEV_T)0;
5923 uint32 raw_unixmode = IVAL(pdata,84);
5927 if (total_data < 100) {
5928 return NT_STATUS_INVALID_PARAMETER;
5931 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5932 if (!NT_STATUS_IS_OK(status)) {
5936 #if defined(HAVE_MAKEDEV)
5937 dev = makedev(dev_major, dev_minor);
5940 switch (file_type) {
5941 #if defined(S_IFIFO)
5942 case UNIX_TYPE_FIFO:
5943 unixmode |= S_IFIFO;
5946 #if defined(S_IFSOCK)
5947 case UNIX_TYPE_SOCKET:
5948 unixmode |= S_IFSOCK;
5951 #if defined(S_IFCHR)
5952 case UNIX_TYPE_CHARDEV:
5953 unixmode |= S_IFCHR;
5956 #if defined(S_IFBLK)
5957 case UNIX_TYPE_BLKDEV:
5958 unixmode |= S_IFBLK;
5962 return NT_STATUS_INVALID_PARAMETER;
5965 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5966 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5968 /* Ok - do the mknod. */
5969 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5970 return map_nt_error_from_unix(errno);
5973 /* If any of the other "set" calls fail we
5974 * don't want to end up with a half-constructed mknod.
5977 if (lp_inherit_perms(SNUM(conn))) {
5979 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
5980 return NT_STATUS_NO_MEMORY;
5982 inherit_access_posix_acl(conn, parent, fname, unixmode);
5983 TALLOC_FREE(parent);
5986 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5987 status = map_nt_error_from_unix(errno);
5988 SMB_VFS_UNLINK(conn,fname);
5991 return NT_STATUS_OK;
5994 /****************************************************************************
5995 Deal with SMB_SET_FILE_UNIX_BASIC.
5996 ****************************************************************************/
5998 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5999 struct smb_request *req,
6004 SMB_STRUCT_STAT *psbuf)
6006 struct smb_file_time ft;
6007 uint32 raw_unixmode;
6010 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6011 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6012 NTSTATUS status = NT_STATUS_OK;
6013 bool delete_on_fail = False;
6014 enum perm_type ptype;
6018 if (total_data < 100) {
6019 return NT_STATUS_INVALID_PARAMETER;
6022 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6023 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6024 size=IVAL(pdata,0); /* first 8 Bytes are size */
6025 #ifdef LARGE_SMB_OFF_T
6026 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6027 #else /* LARGE_SMB_OFF_T */
6028 if (IVAL(pdata,4) != 0) {
6029 /* more than 32 bits? */
6030 return NT_STATUS_INVALID_PARAMETER;
6032 #endif /* LARGE_SMB_OFF_T */
6035 ft.atime = interpret_long_date(pdata+24); /* access_time */
6036 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6037 set_owner = (uid_t)IVAL(pdata,40);
6038 set_grp = (gid_t)IVAL(pdata,48);
6039 raw_unixmode = IVAL(pdata,84);
6041 if (VALID_STAT(*psbuf)) {
6042 if (S_ISDIR(psbuf->st_mode)) {
6043 ptype = PERM_EXISTING_DIR;
6045 ptype = PERM_EXISTING_FILE;
6048 ptype = PERM_NEW_FILE;
6051 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6052 if (!NT_STATUS_IS_OK(status)) {
6056 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6057 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6058 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6060 if (!VALID_STAT(*psbuf)) {
6062 * The only valid use of this is to create character and block
6063 * devices, and named pipes. This is deprecated (IMHO) and
6064 * a new info level should be used for mknod. JRA.
6067 status = smb_unix_mknod(conn,
6072 if (!NT_STATUS_IS_OK(status)) {
6076 /* Ensure we don't try and change anything else. */
6077 raw_unixmode = SMB_MODE_NO_CHANGE;
6078 size = get_file_size_stat(psbuf);
6079 ft.atime = get_atimespec(psbuf);
6080 ft.mtime = get_mtimespec(psbuf);
6082 * We continue here as we might want to change the
6085 delete_on_fail = True;
6089 /* Horrible backwards compatibility hack as an old server bug
6090 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6094 size = get_file_size_stat(psbuf);
6099 * Deal with the UNIX specific mode set.
6102 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6103 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6104 (unsigned int)unixmode, fname ));
6105 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6106 return map_nt_error_from_unix(errno);
6111 * Deal with the UNIX specific uid set.
6114 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6117 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6118 (unsigned int)set_owner, fname ));
6120 if (S_ISLNK(psbuf->st_mode)) {
6121 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6123 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6127 status = map_nt_error_from_unix(errno);
6128 if (delete_on_fail) {
6129 SMB_VFS_UNLINK(conn,fname);
6136 * Deal with the UNIX specific gid set.
6139 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6140 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6141 (unsigned int)set_owner, fname ));
6142 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6143 status = map_nt_error_from_unix(errno);
6144 if (delete_on_fail) {
6145 SMB_VFS_UNLINK(conn,fname);
6151 /* Deal with any size changes. */
6153 status = smb_set_file_size(conn, req,
6158 if (!NT_STATUS_IS_OK(status)) {
6162 /* Deal with any time changes. */
6164 return smb_set_file_time(conn,
6172 /****************************************************************************
6173 Deal with SMB_SET_FILE_UNIX_INFO2.
6174 ****************************************************************************/
6176 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6177 struct smb_request *req,
6182 SMB_STRUCT_STAT *psbuf)
6188 if (total_data < 116) {
6189 return NT_STATUS_INVALID_PARAMETER;
6192 /* Start by setting all the fields that are common between UNIX_BASIC
6195 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6197 if (!NT_STATUS_IS_OK(status)) {
6201 smb_fflags = IVAL(pdata, 108);
6202 smb_fmask = IVAL(pdata, 112);
6204 /* NB: We should only attempt to alter the file flags if the client
6205 * sends a non-zero mask.
6207 if (smb_fmask != 0) {
6208 int stat_fflags = 0;
6210 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6212 /* Client asked to alter a flag we don't understand. */
6213 return NT_STATUS_INVALID_PARAMETER;
6216 if (fsp && fsp->fh->fd != -1) {
6217 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6218 return NT_STATUS_NOT_SUPPORTED;
6220 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6221 return map_nt_error_from_unix(errno);
6226 /* XXX: need to add support for changing the create_time here. You
6227 * can do this for paths on Darwin with setattrlist(2). The right way
6228 * to hook this up is probably by extending the VFS utimes interface.
6231 return NT_STATUS_OK;
6234 /****************************************************************************
6235 Create a directory with POSIX semantics.
6236 ****************************************************************************/
6238 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6239 struct smb_request *req,
6243 SMB_STRUCT_STAT *psbuf,
6244 int *pdata_return_size)
6246 NTSTATUS status = NT_STATUS_OK;
6247 uint32 raw_unixmode = 0;
6248 uint32 mod_unixmode = 0;
6249 mode_t unixmode = (mode_t)0;
6250 files_struct *fsp = NULL;
6251 uint16 info_level_return = 0;
6253 char *pdata = *ppdata;
6255 if (total_data < 18) {
6256 return NT_STATUS_INVALID_PARAMETER;
6259 raw_unixmode = IVAL(pdata,8);
6260 /* Next 4 bytes are not yet defined. */
6262 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6263 if (!NT_STATUS_IS_OK(status)) {
6267 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6269 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6270 fname, (unsigned int)unixmode ));
6272 status = SMB_VFS_CREATE_FILE(
6275 0, /* root_dir_fid */
6277 0, /* create_file_flags */
6278 FILE_READ_ATTRIBUTES, /* access_mask */
6279 FILE_SHARE_NONE, /* share_access */
6280 FILE_CREATE, /* create_disposition*/
6281 FILE_DIRECTORY_FILE, /* create_options */
6282 mod_unixmode, /* file_attributes */
6283 0, /* oplock_request */
6284 0, /* allocation_size */
6291 if (NT_STATUS_IS_OK(status)) {
6292 close_file(req, fsp, NORMAL_CLOSE);
6295 info_level_return = SVAL(pdata,16);
6297 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6298 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6299 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6300 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6302 *pdata_return_size = 12;
6305 /* Realloc the data size */
6306 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6307 if (*ppdata == NULL) {
6308 *pdata_return_size = 0;
6309 return NT_STATUS_NO_MEMORY;
6313 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6314 SSVAL(pdata,2,0); /* No fnum. */
6315 SIVAL(pdata,4,info); /* Was directory created. */
6317 switch (info_level_return) {
6318 case SMB_QUERY_FILE_UNIX_BASIC:
6319 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6320 SSVAL(pdata,10,0); /* Padding. */
6321 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6323 case SMB_QUERY_FILE_UNIX_INFO2:
6324 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6325 SSVAL(pdata,10,0); /* Padding. */
6326 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6329 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6330 SSVAL(pdata,10,0); /* Padding. */
6337 /****************************************************************************
6338 Open/Create a file with POSIX semantics.
6339 ****************************************************************************/
6341 static NTSTATUS smb_posix_open(connection_struct *conn,
6342 struct smb_request *req,
6346 SMB_STRUCT_STAT *psbuf,
6347 int *pdata_return_size)
6349 bool extended_oplock_granted = False;
6350 char *pdata = *ppdata;
6352 uint32 wire_open_mode = 0;
6353 uint32 raw_unixmode = 0;
6354 uint32 mod_unixmode = 0;
6355 uint32 create_disp = 0;
6356 uint32 access_mask = 0;
6357 uint32 create_options = 0;
6358 NTSTATUS status = NT_STATUS_OK;
6359 mode_t unixmode = (mode_t)0;
6360 files_struct *fsp = NULL;
6361 int oplock_request = 0;
6363 uint16 info_level_return = 0;
6365 if (total_data < 18) {
6366 return NT_STATUS_INVALID_PARAMETER;
6369 flags = IVAL(pdata,0);
6370 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6371 if (oplock_request) {
6372 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6375 wire_open_mode = IVAL(pdata,4);
6377 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6378 return smb_posix_mkdir(conn, req,
6386 switch (wire_open_mode & SMB_ACCMODE) {
6388 access_mask = FILE_READ_DATA;
6391 access_mask = FILE_WRITE_DATA;
6394 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6397 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6398 (unsigned int)wire_open_mode ));
6399 return NT_STATUS_INVALID_PARAMETER;
6402 wire_open_mode &= ~SMB_ACCMODE;
6404 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6405 create_disp = FILE_CREATE;
6406 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6407 create_disp = FILE_OVERWRITE_IF;
6408 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6409 create_disp = FILE_OPEN_IF;
6411 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6412 (unsigned int)wire_open_mode ));
6413 return NT_STATUS_INVALID_PARAMETER;
6416 raw_unixmode = IVAL(pdata,8);
6417 /* Next 4 bytes are not yet defined. */
6419 status = unix_perms_from_wire(conn,
6422 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6425 if (!NT_STATUS_IS_OK(status)) {
6429 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6431 if (wire_open_mode & SMB_O_SYNC) {
6432 create_options |= FILE_WRITE_THROUGH;
6434 if (wire_open_mode & SMB_O_APPEND) {
6435 access_mask |= FILE_APPEND_DATA;
6437 if (wire_open_mode & SMB_O_DIRECT) {
6438 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6441 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6443 (unsigned int)wire_open_mode,
6444 (unsigned int)unixmode ));
6446 status = SMB_VFS_CREATE_FILE(
6449 0, /* root_dir_fid */
6451 0, /* create_file_flags */
6452 access_mask, /* access_mask */
6453 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6455 create_disp, /* create_disposition*/
6456 0, /* create_options */
6457 mod_unixmode, /* file_attributes */
6458 oplock_request, /* oplock_request */
6459 0, /* allocation_size */
6466 if (!NT_STATUS_IS_OK(status)) {
6470 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6471 extended_oplock_granted = True;
6474 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6475 extended_oplock_granted = True;
6478 info_level_return = SVAL(pdata,16);
6480 /* Allocate the correct return size. */
6482 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6483 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6484 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6485 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6487 *pdata_return_size = 12;
6490 /* Realloc the data size */
6491 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6492 if (*ppdata == NULL) {
6493 close_file(req, fsp, ERROR_CLOSE);
6494 *pdata_return_size = 0;
6495 return NT_STATUS_NO_MEMORY;
6499 if (extended_oplock_granted) {
6500 if (flags & REQUEST_BATCH_OPLOCK) {
6501 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6503 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6505 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6506 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6508 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6511 SSVAL(pdata,2,fsp->fnum);
6512 SIVAL(pdata,4,info); /* Was file created etc. */
6514 switch (info_level_return) {
6515 case SMB_QUERY_FILE_UNIX_BASIC:
6516 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6517 SSVAL(pdata,10,0); /* padding. */
6518 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6520 case SMB_QUERY_FILE_UNIX_INFO2:
6521 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6522 SSVAL(pdata,10,0); /* padding. */
6523 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6526 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6527 SSVAL(pdata,10,0); /* padding. */
6530 return NT_STATUS_OK;
6533 /****************************************************************************
6534 Delete a file with POSIX semantics.
6535 ****************************************************************************/
6537 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6538 struct smb_request *req,
6542 SMB_STRUCT_STAT *psbuf)
6544 NTSTATUS status = NT_STATUS_OK;
6545 files_struct *fsp = NULL;
6549 int create_options = 0;
6551 struct share_mode_lock *lck = NULL;
6553 if (total_data < 2) {
6554 return NT_STATUS_INVALID_PARAMETER;
6557 flags = SVAL(pdata,0);
6559 if (!VALID_STAT(*psbuf)) {
6560 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6563 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6564 !VALID_STAT_OF_DIR(*psbuf)) {
6565 return NT_STATUS_NOT_A_DIRECTORY;
6568 DEBUG(10,("smb_posix_unlink: %s %s\n",
6569 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6572 if (VALID_STAT_OF_DIR(*psbuf)) {
6573 create_options |= FILE_DIRECTORY_FILE;
6576 status = SMB_VFS_CREATE_FILE(
6579 0, /* root_dir_fid */
6581 0, /* create_file_flags */
6582 DELETE_ACCESS, /* access_mask */
6583 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6585 FILE_OPEN, /* create_disposition*/
6586 create_options, /* create_options */
6587 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6588 0, /* oplock_request */
6589 0, /* allocation_size */
6596 if (!NT_STATUS_IS_OK(status)) {
6601 * Don't lie to client. If we can't really delete due to
6602 * non-POSIX opens return SHARING_VIOLATION.
6605 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6608 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6609 "lock for file %s\n", fsp->fsp_name));
6610 close_file(req, fsp, NORMAL_CLOSE);
6611 return NT_STATUS_INVALID_PARAMETER;
6615 * See if others still have the file open. If this is the case, then
6616 * don't delete. If all opens are POSIX delete we can set the delete
6617 * on close disposition.
6619 for (i=0; i<lck->num_share_modes; i++) {
6620 struct share_mode_entry *e = &lck->share_modes[i];
6621 if (is_valid_share_mode_entry(e)) {
6622 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6625 /* Fail with sharing violation. */
6626 close_file(req, fsp, NORMAL_CLOSE);
6628 return NT_STATUS_SHARING_VIOLATION;
6633 * Set the delete on close.
6635 status = smb_set_file_disposition_info(conn,
6642 if (!NT_STATUS_IS_OK(status)) {
6643 close_file(req, fsp, NORMAL_CLOSE);
6648 return close_file(req, fsp, NORMAL_CLOSE);
6651 /****************************************************************************
6652 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6653 ****************************************************************************/
6655 static void call_trans2setfilepathinfo(connection_struct *conn,
6656 struct smb_request *req,
6657 unsigned int tran_call,
6658 char **pparams, int total_params,
6659 char **ppdata, int total_data,
6660 unsigned int max_data_bytes)
6662 char *params = *pparams;
6663 char *pdata = *ppdata;
6665 SMB_STRUCT_STAT sbuf;
6667 files_struct *fsp = NULL;
6668 NTSTATUS status = NT_STATUS_OK;
6669 int data_return_size = 0;
6670 TALLOC_CTX *ctx = talloc_tos();
6673 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6679 if (tran_call == TRANSACT2_SETFILEINFO) {
6680 if (total_params < 4) {
6681 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6685 fsp = file_fsp(req, SVAL(params,0));
6686 /* Basic check for non-null fsp. */
6687 if (!check_fsp_open(conn, req, fsp)) {
6690 info_level = SVAL(params,2);
6692 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6694 reply_nterror(req, NT_STATUS_NO_MEMORY);
6698 if(fsp->is_directory || fsp->fh->fd == -1) {
6700 * This is actually a SETFILEINFO on a directory
6701 * handle (returned from an NT SMB). NT5.0 seems
6702 * to do this call. JRA.
6704 if (INFO_LEVEL_IS_UNIX(info_level)) {
6705 /* Always do lstat for UNIX calls. */
6706 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6707 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6708 reply_unixerror(req,ERRDOS,ERRbadpath);
6712 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6713 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6714 reply_unixerror(req,ERRDOS,ERRbadpath);
6718 } else if (fsp->print_file) {
6720 * Doing a DELETE_ON_CLOSE should cancel a print job.
6722 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6723 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6725 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6728 send_trans2_replies(conn, req, params, 2,
6733 reply_unixerror(req, ERRDOS, ERRbadpath);
6738 * Original code - this is an open file.
6740 if (!check_fsp(conn, req, fsp)) {
6744 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6745 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6746 reply_unixerror(req, ERRDOS, ERRbadfid);
6752 if (total_params < 7) {
6753 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6757 info_level = SVAL(params,0);
6758 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6759 total_params - 6, STR_TERMINATE,
6761 if (!NT_STATUS_IS_OK(status)) {
6762 reply_nterror(req, status);
6766 status = resolve_dfspath(ctx, conn,
6767 req->flags2 & FLAGS2_DFS_PATHNAMES,
6770 if (!NT_STATUS_IS_OK(status)) {
6771 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6772 reply_botherror(req,
6773 NT_STATUS_PATH_NOT_COVERED,
6774 ERRSRV, ERRbadpath);
6777 reply_nterror(req, status);
6781 status = unix_convert(ctx, conn, fname, False,
6782 &fname, NULL, &sbuf);
6783 if (!NT_STATUS_IS_OK(status)) {
6784 reply_nterror(req, status);
6788 status = check_name(conn, fname);
6789 if (!NT_STATUS_IS_OK(status)) {
6790 reply_nterror(req, status);
6794 if (INFO_LEVEL_IS_UNIX(info_level)) {
6796 * For CIFS UNIX extensions the target name may not exist.
6799 /* Always do lstat for UNIX calls. */
6800 SMB_VFS_LSTAT(conn,fname,&sbuf);
6802 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6803 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6804 reply_unixerror(req, ERRDOS, ERRbadpath);
6809 if (!CAN_WRITE(conn)) {
6810 reply_doserror(req, ERRSRV, ERRaccess);
6814 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6815 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6819 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6820 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6822 /* Realloc the parameter size */
6823 *pparams = (char *)SMB_REALLOC(*pparams,2);
6824 if (*pparams == NULL) {
6825 reply_nterror(req, NT_STATUS_NO_MEMORY);
6832 switch (info_level) {
6834 case SMB_INFO_STANDARD:
6836 status = smb_set_info_standard(conn,
6845 case SMB_INFO_SET_EA:
6847 status = smb_info_set_ea(conn,
6855 case SMB_SET_FILE_BASIC_INFO:
6856 case SMB_FILE_BASIC_INFORMATION:
6858 status = smb_set_file_basic_info(conn,
6867 case SMB_FILE_ALLOCATION_INFORMATION:
6868 case SMB_SET_FILE_ALLOCATION_INFO:
6870 status = smb_set_file_allocation_info(conn, req,
6879 case SMB_FILE_END_OF_FILE_INFORMATION:
6880 case SMB_SET_FILE_END_OF_FILE_INFO:
6882 status = smb_set_file_end_of_file_info(conn, req,
6891 case SMB_FILE_DISPOSITION_INFORMATION:
6892 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6895 /* JRA - We used to just ignore this on a path ?
6896 * Shouldn't this be invalid level on a pathname
6899 if (tran_call != TRANSACT2_SETFILEINFO) {
6900 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6903 status = smb_set_file_disposition_info(conn,
6912 case SMB_FILE_POSITION_INFORMATION:
6914 status = smb_file_position_information(conn,
6921 /* From tridge Samba4 :
6922 * MODE_INFORMATION in setfileinfo (I have no
6923 * idea what "mode information" on a file is - it takes a value of 0,
6924 * 2, 4 or 6. What could it be?).
6927 case SMB_FILE_MODE_INFORMATION:
6929 status = smb_file_mode_information(conn,
6936 * CIFS UNIX extensions.
6939 case SMB_SET_FILE_UNIX_BASIC:
6941 status = smb_set_file_unix_basic(conn, req,
6950 case SMB_SET_FILE_UNIX_INFO2:
6952 status = smb_set_file_unix_info2(conn, req,
6961 case SMB_SET_FILE_UNIX_LINK:
6963 if (tran_call != TRANSACT2_SETPATHINFO) {
6964 /* We must have a pathname for this. */
6965 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6968 status = smb_set_file_unix_link(conn, req, pdata,
6973 case SMB_SET_FILE_UNIX_HLINK:
6975 if (tran_call != TRANSACT2_SETPATHINFO) {
6976 /* We must have a pathname for this. */
6977 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6980 status = smb_set_file_unix_hlink(conn, req,
6986 case SMB_FILE_RENAME_INFORMATION:
6988 status = smb_file_rename_information(conn, req,
6994 #if defined(HAVE_POSIX_ACLS)
6995 case SMB_SET_POSIX_ACL:
6997 status = smb_set_posix_acl(conn,
7007 case SMB_SET_POSIX_LOCK:
7009 if (tran_call != TRANSACT2_SETFILEINFO) {
7010 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7013 status = smb_set_posix_lock(conn, req,
7014 pdata, total_data, fsp);
7018 case SMB_POSIX_PATH_OPEN:
7020 if (tran_call != TRANSACT2_SETPATHINFO) {
7021 /* We must have a pathname for this. */
7022 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7026 status = smb_posix_open(conn, req,
7035 case SMB_POSIX_PATH_UNLINK:
7037 if (tran_call != TRANSACT2_SETPATHINFO) {
7038 /* We must have a pathname for this. */
7039 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7043 status = smb_posix_unlink(conn, req,
7052 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7057 if (!NT_STATUS_IS_OK(status)) {
7058 if (open_was_deferred(req->mid)) {
7059 /* We have re-scheduled this call. */
7062 if (blocking_lock_was_deferred(req->mid)) {
7063 /* We have re-scheduled this call. */
7066 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7067 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7068 ERRSRV, ERRbadpath);
7071 if (info_level == SMB_POSIX_PATH_OPEN) {
7072 reply_openerror(req, status);
7076 reply_nterror(req, status);
7081 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7087 /****************************************************************************
7088 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7089 ****************************************************************************/
7091 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7092 char **pparams, int total_params,
7093 char **ppdata, int total_data,
7094 unsigned int max_data_bytes)
7096 char *params = *pparams;
7097 char *pdata = *ppdata;
7098 char *directory = NULL;
7099 SMB_STRUCT_STAT sbuf;
7100 NTSTATUS status = NT_STATUS_OK;
7101 struct ea_list *ea_list = NULL;
7102 TALLOC_CTX *ctx = talloc_tos();
7104 if (!CAN_WRITE(conn)) {
7105 reply_doserror(req, ERRSRV, ERRaccess);
7109 if (total_params < 5) {
7110 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7114 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7115 total_params - 4, STR_TERMINATE,
7117 if (!NT_STATUS_IS_OK(status)) {
7118 reply_nterror(req, status);
7122 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7124 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7125 if (!NT_STATUS_IS_OK(status)) {
7126 reply_nterror(req, status);
7130 status = check_name(conn, directory);
7131 if (!NT_STATUS_IS_OK(status)) {
7132 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7133 reply_nterror(req, status);
7137 /* Any data in this call is an EA list. */
7138 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7139 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7144 * OS/2 workplace shell seems to send SET_EA requests of "null"
7145 * length (4 bytes containing IVAL 4).
7146 * They seem to have no effect. Bug #3212. JRA.
7149 if (total_data != 4) {
7150 if (total_data < 10) {
7151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7155 if (IVAL(pdata,0) > total_data) {
7156 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7157 IVAL(pdata,0), (unsigned int)total_data));
7158 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7162 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7165 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7169 /* If total_data == 4 Windows doesn't care what values
7170 * are placed in that field, it just ignores them.
7171 * The System i QNTC IBM SMB client puts bad values here,
7172 * so ignore them. */
7174 status = create_directory(conn, req, directory);
7176 if (!NT_STATUS_IS_OK(status)) {
7177 reply_nterror(req, status);
7181 /* Try and set any given EA. */
7183 status = set_ea(conn, NULL, directory, ea_list);
7184 if (!NT_STATUS_IS_OK(status)) {
7185 reply_nterror(req, status);
7190 /* Realloc the parameter and data sizes */
7191 *pparams = (char *)SMB_REALLOC(*pparams,2);
7192 if(*pparams == NULL) {
7193 reply_nterror(req, NT_STATUS_NO_MEMORY);
7200 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7205 /****************************************************************************
7206 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7207 We don't actually do this - we just send a null response.
7208 ****************************************************************************/
7210 static void call_trans2findnotifyfirst(connection_struct *conn,
7211 struct smb_request *req,
7212 char **pparams, int total_params,
7213 char **ppdata, int total_data,
7214 unsigned int max_data_bytes)
7216 char *params = *pparams;
7219 if (total_params < 6) {
7220 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7224 info_level = SVAL(params,4);
7225 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7227 switch (info_level) {
7232 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7236 /* Realloc the parameter and data sizes */
7237 *pparams = (char *)SMB_REALLOC(*pparams,6);
7238 if (*pparams == NULL) {
7239 reply_nterror(req, NT_STATUS_NO_MEMORY);
7244 SSVAL(params,0,fnf_handle);
7245 SSVAL(params,2,0); /* No changes */
7246 SSVAL(params,4,0); /* No EA errors */
7253 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7258 /****************************************************************************
7259 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7260 changes). Currently this does nothing.
7261 ****************************************************************************/
7263 static void call_trans2findnotifynext(connection_struct *conn,
7264 struct smb_request *req,
7265 char **pparams, int total_params,
7266 char **ppdata, int total_data,
7267 unsigned int max_data_bytes)
7269 char *params = *pparams;
7271 DEBUG(3,("call_trans2findnotifynext\n"));
7273 /* Realloc the parameter and data sizes */
7274 *pparams = (char *)SMB_REALLOC(*pparams,4);
7275 if (*pparams == NULL) {
7276 reply_nterror(req, NT_STATUS_NO_MEMORY);
7281 SSVAL(params,0,0); /* No changes */
7282 SSVAL(params,2,0); /* No EA errors */
7284 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7289 /****************************************************************************
7290 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7291 ****************************************************************************/
7293 static void call_trans2getdfsreferral(connection_struct *conn,
7294 struct smb_request *req,
7295 char **pparams, int total_params,
7296 char **ppdata, int total_data,
7297 unsigned int max_data_bytes)
7299 char *params = *pparams;
7300 char *pathname = NULL;
7302 int max_referral_level;
7303 NTSTATUS status = NT_STATUS_OK;
7304 TALLOC_CTX *ctx = talloc_tos();
7306 DEBUG(10,("call_trans2getdfsreferral\n"));
7308 if (total_params < 3) {
7309 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7313 max_referral_level = SVAL(params,0);
7315 if(!lp_host_msdfs()) {
7316 reply_doserror(req, ERRDOS, ERRbadfunc);
7320 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7321 total_params - 2, STR_TERMINATE);
7323 reply_nterror(req, NT_STATUS_NOT_FOUND);
7326 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7327 ppdata,&status)) < 0) {
7328 reply_nterror(req, status);
7332 SSVAL(req->inbuf, smb_flg2,
7333 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7334 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7339 #define LMCAT_SPL 0x53
7340 #define LMFUNC_GETJOBID 0x60
7342 /****************************************************************************
7343 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7344 ****************************************************************************/
7346 static void call_trans2ioctl(connection_struct *conn,
7347 struct smb_request *req,
7348 char **pparams, int total_params,
7349 char **ppdata, int total_data,
7350 unsigned int max_data_bytes)
7352 char *pdata = *ppdata;
7353 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7355 /* check for an invalid fid before proceeding */
7358 reply_doserror(req, ERRDOS, ERRbadfid);
7362 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7363 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7364 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7365 if (*ppdata == NULL) {
7366 reply_nterror(req, NT_STATUS_NO_MEMORY);
7371 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7372 CAN ACCEPT THIS IN UNICODE. JRA. */
7374 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7375 srvstr_push(pdata, req->flags2, pdata + 2,
7376 global_myname(), 15,
7377 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7378 srvstr_push(pdata, req->flags2, pdata+18,
7379 lp_servicename(SNUM(conn)), 13,
7380 STR_ASCII|STR_TERMINATE); /* Service name */
7381 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7386 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7387 reply_doserror(req, ERRSRV, ERRerror);
7390 /****************************************************************************
7391 Reply to a SMBfindclose (stop trans2 directory search).
7392 ****************************************************************************/
7394 void reply_findclose(struct smb_request *req)
7398 START_PROFILE(SMBfindclose);
7401 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7402 END_PROFILE(SMBfindclose);
7406 dptr_num = SVALS(req->vwv+0, 0);
7408 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7410 dptr_close(&dptr_num);
7412 reply_outbuf(req, 0, 0);
7414 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7416 END_PROFILE(SMBfindclose);
7420 /****************************************************************************
7421 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7422 ****************************************************************************/
7424 void reply_findnclose(struct smb_request *req)
7428 START_PROFILE(SMBfindnclose);
7431 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7432 END_PROFILE(SMBfindnclose);
7436 dptr_num = SVAL(req->vwv+0, 0);
7438 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7440 /* We never give out valid handles for a
7441 findnotifyfirst - so any dptr_num is ok here.
7444 reply_outbuf(req, 0, 0);
7446 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7448 END_PROFILE(SMBfindnclose);
7452 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7453 struct trans_state *state)
7455 if (Protocol >= PROTOCOL_NT1) {
7456 req->flags2 |= 0x40; /* IS_LONG_NAME */
7457 SSVAL(req->inbuf,smb_flg2,req->flags2);
7460 if (conn->encrypt_level == Required && !req->encrypted) {
7461 if (state->call != TRANSACT2_QFSINFO &&
7462 state->call != TRANSACT2_SETFSINFO) {
7463 DEBUG(0,("handle_trans2: encryption required "
7465 (unsigned int)state->call));
7466 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7471 /* Now we must call the relevant TRANS2 function */
7472 switch(state->call) {
7473 case TRANSACT2_OPEN:
7475 START_PROFILE(Trans2_open);
7476 call_trans2open(conn, req,
7477 &state->param, state->total_param,
7478 &state->data, state->total_data,
7479 state->max_data_return);
7480 END_PROFILE(Trans2_open);
7484 case TRANSACT2_FINDFIRST:
7486 START_PROFILE(Trans2_findfirst);
7487 call_trans2findfirst(conn, req,
7488 &state->param, state->total_param,
7489 &state->data, state->total_data,
7490 state->max_data_return);
7491 END_PROFILE(Trans2_findfirst);
7495 case TRANSACT2_FINDNEXT:
7497 START_PROFILE(Trans2_findnext);
7498 call_trans2findnext(conn, req,
7499 &state->param, state->total_param,
7500 &state->data, state->total_data,
7501 state->max_data_return);
7502 END_PROFILE(Trans2_findnext);
7506 case TRANSACT2_QFSINFO:
7508 START_PROFILE(Trans2_qfsinfo);
7509 call_trans2qfsinfo(conn, req,
7510 &state->param, state->total_param,
7511 &state->data, state->total_data,
7512 state->max_data_return);
7513 END_PROFILE(Trans2_qfsinfo);
7517 case TRANSACT2_SETFSINFO:
7519 START_PROFILE(Trans2_setfsinfo);
7520 call_trans2setfsinfo(conn, req,
7521 &state->param, state->total_param,
7522 &state->data, state->total_data,
7523 state->max_data_return);
7524 END_PROFILE(Trans2_setfsinfo);
7528 case TRANSACT2_QPATHINFO:
7529 case TRANSACT2_QFILEINFO:
7531 START_PROFILE(Trans2_qpathinfo);
7532 call_trans2qfilepathinfo(conn, req, state->call,
7533 &state->param, state->total_param,
7534 &state->data, state->total_data,
7535 state->max_data_return);
7536 END_PROFILE(Trans2_qpathinfo);
7540 case TRANSACT2_SETPATHINFO:
7541 case TRANSACT2_SETFILEINFO:
7543 START_PROFILE(Trans2_setpathinfo);
7544 call_trans2setfilepathinfo(conn, req, state->call,
7545 &state->param, state->total_param,
7546 &state->data, state->total_data,
7547 state->max_data_return);
7548 END_PROFILE(Trans2_setpathinfo);
7552 case TRANSACT2_FINDNOTIFYFIRST:
7554 START_PROFILE(Trans2_findnotifyfirst);
7555 call_trans2findnotifyfirst(conn, req,
7556 &state->param, state->total_param,
7557 &state->data, state->total_data,
7558 state->max_data_return);
7559 END_PROFILE(Trans2_findnotifyfirst);
7563 case TRANSACT2_FINDNOTIFYNEXT:
7565 START_PROFILE(Trans2_findnotifynext);
7566 call_trans2findnotifynext(conn, req,
7567 &state->param, state->total_param,
7568 &state->data, state->total_data,
7569 state->max_data_return);
7570 END_PROFILE(Trans2_findnotifynext);
7574 case TRANSACT2_MKDIR:
7576 START_PROFILE(Trans2_mkdir);
7577 call_trans2mkdir(conn, req,
7578 &state->param, state->total_param,
7579 &state->data, state->total_data,
7580 state->max_data_return);
7581 END_PROFILE(Trans2_mkdir);
7585 case TRANSACT2_GET_DFS_REFERRAL:
7587 START_PROFILE(Trans2_get_dfs_referral);
7588 call_trans2getdfsreferral(conn, req,
7589 &state->param, state->total_param,
7590 &state->data, state->total_data,
7591 state->max_data_return);
7592 END_PROFILE(Trans2_get_dfs_referral);
7596 case TRANSACT2_IOCTL:
7598 START_PROFILE(Trans2_ioctl);
7599 call_trans2ioctl(conn, req,
7600 &state->param, state->total_param,
7601 &state->data, state->total_data,
7602 state->max_data_return);
7603 END_PROFILE(Trans2_ioctl);
7608 /* Error in request */
7609 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7610 reply_doserror(req, ERRSRV,ERRerror);
7614 /****************************************************************************
7615 Reply to a SMBtrans2.
7616 ****************************************************************************/
7618 void reply_trans2(struct smb_request *req)
7620 connection_struct *conn = req->conn;
7625 unsigned int tran_call;
7626 struct trans_state *state;
7629 START_PROFILE(SMBtrans2);
7631 if (req->wct < 14) {
7632 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7633 END_PROFILE(SMBtrans2);
7637 dsoff = SVAL(req->vwv+12, 0);
7638 dscnt = SVAL(req->vwv+11, 0);
7639 psoff = SVAL(req->vwv+10, 0);
7640 pscnt = SVAL(req->vwv+9, 0);
7641 tran_call = SVAL(req->vwv+14, 0);
7643 result = allow_new_trans(conn->pending_trans, req->mid);
7644 if (!NT_STATUS_IS_OK(result)) {
7645 DEBUG(2, ("Got invalid trans2 request: %s\n",
7646 nt_errstr(result)));
7647 reply_nterror(req, result);
7648 END_PROFILE(SMBtrans2);
7653 switch (tran_call) {
7654 /* List the allowed trans2 calls on IPC$ */
7655 case TRANSACT2_OPEN:
7656 case TRANSACT2_GET_DFS_REFERRAL:
7657 case TRANSACT2_QFILEINFO:
7658 case TRANSACT2_QFSINFO:
7659 case TRANSACT2_SETFSINFO:
7662 reply_doserror(req, ERRSRV, ERRaccess);
7663 END_PROFILE(SMBtrans2);
7668 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7669 DEBUG(0, ("talloc failed\n"));
7670 reply_nterror(req, NT_STATUS_NO_MEMORY);
7671 END_PROFILE(SMBtrans2);
7675 state->cmd = SMBtrans2;
7677 state->mid = req->mid;
7678 state->vuid = req->vuid;
7679 state->setup_count = SVAL(req->vwv+13, 0);
7680 state->setup = NULL;
7681 state->total_param = SVAL(req->vwv+0, 0);
7682 state->param = NULL;
7683 state->total_data = SVAL(req->vwv+1, 0);
7685 state->max_param_return = SVAL(req->vwv+2, 0);
7686 state->max_data_return = SVAL(req->vwv+3, 0);
7687 state->max_setup_return = SVAL(req->vwv+4, 0);
7688 state->close_on_completion = BITSETW(req->vwv+5, 0);
7689 state->one_way = BITSETW(req->vwv+5, 1);
7691 state->call = tran_call;
7693 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7694 is so as a sanity check */
7695 if (state->setup_count != 1) {
7697 * Need to have rc=0 for ioctl to get job id for OS/2.
7698 * Network printing will fail if function is not successful.
7699 * Similar function in reply.c will be used if protocol
7700 * is LANMAN1.0 instead of LM1.2X002.
7701 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7702 * outbuf doesn't have to be set(only job id is used).
7704 if ( (state->setup_count == 4)
7705 && (tran_call == TRANSACT2_IOCTL)
7706 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7707 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7708 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7710 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7711 DEBUG(2,("Transaction is %d\n",tran_call));
7713 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7714 END_PROFILE(SMBtrans2);
7719 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7722 if (state->total_data) {
7724 if (trans_oob(state->total_data, 0, dscnt)
7725 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7729 /* Can't use talloc here, the core routines do realloc on the
7730 * params and data. */
7731 state->data = (char *)SMB_MALLOC(state->total_data);
7732 if (state->data == NULL) {
7733 DEBUG(0,("reply_trans2: data malloc fail for %u "
7734 "bytes !\n", (unsigned int)state->total_data));
7736 reply_nterror(req, NT_STATUS_NO_MEMORY);
7737 END_PROFILE(SMBtrans2);
7741 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7744 if (state->total_param) {
7746 if (trans_oob(state->total_param, 0, pscnt)
7747 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7751 /* Can't use talloc here, the core routines do realloc on the
7752 * params and data. */
7753 state->param = (char *)SMB_MALLOC(state->total_param);
7754 if (state->param == NULL) {
7755 DEBUG(0,("reply_trans: param malloc fail for %u "
7756 "bytes !\n", (unsigned int)state->total_param));
7757 SAFE_FREE(state->data);
7759 reply_nterror(req, NT_STATUS_NO_MEMORY);
7760 END_PROFILE(SMBtrans2);
7764 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7767 state->received_data = dscnt;
7768 state->received_param = pscnt;
7770 if ((state->received_param == state->total_param) &&
7771 (state->received_data == state->total_data)) {
7773 handle_trans2(conn, req, state);
7775 SAFE_FREE(state->data);
7776 SAFE_FREE(state->param);
7778 END_PROFILE(SMBtrans2);
7782 DLIST_ADD(conn->pending_trans, state);
7784 /* We need to send an interim response then receive the rest
7785 of the parameter/data bytes */
7786 reply_outbuf(req, 0, 0);
7787 show_msg((char *)req->outbuf);
7788 END_PROFILE(SMBtrans2);
7793 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7794 SAFE_FREE(state->data);
7795 SAFE_FREE(state->param);
7797 END_PROFILE(SMBtrans2);
7798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7802 /****************************************************************************
7803 Reply to a SMBtranss2
7804 ****************************************************************************/
7806 void reply_transs2(struct smb_request *req)
7808 connection_struct *conn = req->conn;
7809 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7810 struct trans_state *state;
7812 START_PROFILE(SMBtranss2);
7814 show_msg((char *)req->inbuf);
7817 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7818 END_PROFILE(SMBtranss2);
7822 for (state = conn->pending_trans; state != NULL;
7823 state = state->next) {
7824 if (state->mid == req->mid) {
7829 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7831 END_PROFILE(SMBtranss2);
7835 /* Revise state->total_param and state->total_data in case they have
7836 changed downwards */
7838 if (SVAL(req->vwv+0, 0) < state->total_param)
7839 state->total_param = SVAL(req->vwv+0, 0);
7840 if (SVAL(req->vwv+1, 0) < state->total_data)
7841 state->total_data = SVAL(req->vwv+1, 0);
7843 pcnt = SVAL(req->vwv+2, 0);
7844 poff = SVAL(req->vwv+3, 0);
7845 pdisp = SVAL(req->vwv+4, 0);
7847 dcnt = SVAL(req->vwv+5, 0);
7848 doff = SVAL(req->vwv+6, 0);
7849 ddisp = SVAL(req->vwv+7, 0);
7851 state->received_param += pcnt;
7852 state->received_data += dcnt;
7854 if ((state->received_data > state->total_data) ||
7855 (state->received_param > state->total_param))
7859 if (trans_oob(state->total_param, pdisp, pcnt)
7860 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7863 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7867 if (trans_oob(state->total_data, ddisp, dcnt)
7868 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7871 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7874 if ((state->received_param < state->total_param) ||
7875 (state->received_data < state->total_data)) {
7876 END_PROFILE(SMBtranss2);
7880 handle_trans2(conn, req, state);
7882 DLIST_REMOVE(conn->pending_trans, state);
7883 SAFE_FREE(state->data);
7884 SAFE_FREE(state->param);
7887 END_PROFILE(SMBtranss2);
7892 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7893 DLIST_REMOVE(conn->pending_trans, state);
7894 SAFE_FREE(state->data);
7895 SAFE_FREE(state->param);
7897 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7898 END_PROFILE(SMBtranss2);