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(),
836 IS_CONN_ENCRYPTED(conn),
838 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
840 TALLOC_FREE(req->outbuf);
842 pp += params_sent_thistime;
843 pd += data_sent_thistime;
845 params_to_send -= params_sent_thistime;
846 data_to_send -= data_sent_thistime;
849 if(params_to_send < 0 || data_to_send < 0) {
850 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
851 params_to_send, data_to_send));
859 /****************************************************************************
860 Reply to a TRANSACT2_OPEN.
861 ****************************************************************************/
863 static void call_trans2open(connection_struct *conn,
864 struct smb_request *req,
865 char **pparams, int total_params,
866 char **ppdata, int total_data,
867 unsigned int max_data_bytes)
869 char *params = *pparams;
870 char *pdata = *ppdata;
875 bool return_additional_info;
886 SMB_STRUCT_STAT sbuf;
889 struct ea_list *ea_list = NULL;
894 uint32 create_disposition;
895 uint32 create_options = 0;
896 TALLOC_CTX *ctx = talloc_tos();
898 SET_STAT_INVALID(sbuf);
901 * Ensure we have enough parameters to perform the operation.
904 if (total_params < 29) {
905 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
909 flags = SVAL(params, 0);
910 deny_mode = SVAL(params, 2);
911 open_attr = SVAL(params,6);
912 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
913 if (oplock_request) {
914 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
918 return_additional_info = BITSETW(params,0);
919 open_sattr = SVAL(params, 4);
920 open_time = make_unix_date3(params+8);
922 open_ofun = SVAL(params,12);
923 open_size = IVAL(params,14);
927 reply_doserror(req, ERRSRV, ERRaccess);
931 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
932 total_params - 28, STR_TERMINATE,
934 if (!NT_STATUS_IS_OK(status)) {
935 reply_nterror(req, status);
939 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
940 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
941 (unsigned int)open_ofun, open_size));
943 if (open_ofun == 0) {
944 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
948 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
953 reply_doserror(req, ERRDOS, ERRbadaccess);
957 /* Any data in this call is an EA list. */
958 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
959 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
963 if (total_data != 4) {
964 if (total_data < 10) {
965 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
969 if (IVAL(pdata,0) > total_data) {
970 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
971 IVAL(pdata,0), (unsigned int)total_data));
972 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
976 ea_list = read_ea_list(talloc_tos(), pdata + 4,
979 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
982 } else if (IVAL(pdata,0) != 4) {
983 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
987 status = SMB_VFS_CREATE_FILE(
990 0, /* root_dir_fid */
992 CFF_DOS_PATH, /* create_file_flags */
993 access_mask, /* access_mask */
994 share_mode, /* share_access */
995 create_disposition, /* create_disposition*/
996 create_options, /* create_options */
997 open_attr, /* file_attributes */
998 oplock_request, /* oplock_request */
999 open_size, /* allocation_size */
1001 ea_list, /* ea_list */
1003 &smb_action, /* pinfo */
1006 if (!NT_STATUS_IS_OK(status)) {
1007 if (open_was_deferred(req->mid)) {
1008 /* We have re-scheduled this call. */
1011 reply_openerror(req, status);
1015 size = get_file_size_stat(&sbuf);
1016 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1017 mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime);
1018 inode = sbuf.st_ex_ino;
1020 close_file(req, fsp, ERROR_CLOSE);
1021 reply_doserror(req, ERRDOS,ERRnoaccess);
1025 /* Realloc the size of parameters and data we will return */
1026 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1027 if(*pparams == NULL ) {
1028 reply_nterror(req, NT_STATUS_NO_MEMORY);
1033 SSVAL(params,0,fsp->fnum);
1034 SSVAL(params,2,fattr);
1035 srv_put_dos_date2(params,4, mtime);
1036 SIVAL(params,8, (uint32)size);
1037 SSVAL(params,12,deny_mode);
1038 SSVAL(params,14,0); /* open_type - file or directory. */
1039 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1041 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1042 smb_action |= EXTENDED_OPLOCK_GRANTED;
1045 SSVAL(params,18,smb_action);
1048 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1050 SIVAL(params,20,inode);
1051 SSVAL(params,24,0); /* Padding. */
1053 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1054 SIVAL(params, 26, ea_size);
1056 SIVAL(params, 26, 0);
1059 /* Send the required number of replies */
1060 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1063 /*********************************************************
1064 Routine to check if a given string matches exactly.
1065 as a special case a mask of "." does NOT match. That
1066 is required for correct wildcard semantics
1067 Case can be significant or not.
1068 **********************************************************/
1070 static bool exact_match(connection_struct *conn,
1074 if (mask[0] == '.' && mask[1] == 0)
1076 if (dptr_has_wild(conn->dirptr)) {
1079 if (conn->case_sensitive)
1080 return strcmp(str,mask)==0;
1082 return StrCaseCmp(str,mask) == 0;
1085 /****************************************************************************
1086 Return the filetype for UNIX extensions.
1087 ****************************************************************************/
1089 static uint32 unix_filetype(mode_t mode)
1092 return UNIX_TYPE_FILE;
1093 else if(S_ISDIR(mode))
1094 return UNIX_TYPE_DIR;
1096 else if(S_ISLNK(mode))
1097 return UNIX_TYPE_SYMLINK;
1100 else if(S_ISCHR(mode))
1101 return UNIX_TYPE_CHARDEV;
1104 else if(S_ISBLK(mode))
1105 return UNIX_TYPE_BLKDEV;
1108 else if(S_ISFIFO(mode))
1109 return UNIX_TYPE_FIFO;
1112 else if(S_ISSOCK(mode))
1113 return UNIX_TYPE_SOCKET;
1116 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1117 return UNIX_TYPE_UNKNOWN;
1120 /****************************************************************************
1121 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1122 ****************************************************************************/
1124 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1126 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1127 SMB_STRUCT_STAT *psbuf,
1129 enum perm_type ptype,
1134 if (perms == SMB_MODE_NO_CHANGE) {
1135 if (!VALID_STAT(*psbuf)) {
1136 return NT_STATUS_INVALID_PARAMETER;
1138 *ret_perms = psbuf->st_ex_mode;
1139 return NT_STATUS_OK;
1143 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1144 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1145 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1146 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1147 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1148 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1149 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1150 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1151 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1153 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1156 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1159 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1164 /* Apply mode mask */
1165 ret &= lp_create_mask(SNUM(conn));
1166 /* Add in force bits */
1167 ret |= lp_force_create_mode(SNUM(conn));
1170 ret &= lp_dir_mask(SNUM(conn));
1171 /* Add in force bits */
1172 ret |= lp_force_dir_mode(SNUM(conn));
1174 case PERM_EXISTING_FILE:
1175 /* Apply mode mask */
1176 ret &= lp_security_mask(SNUM(conn));
1177 /* Add in force bits */
1178 ret |= lp_force_security_mode(SNUM(conn));
1180 case PERM_EXISTING_DIR:
1181 /* Apply mode mask */
1182 ret &= lp_dir_security_mask(SNUM(conn));
1183 /* Add in force bits */
1184 ret |= lp_force_dir_security_mode(SNUM(conn));
1189 return NT_STATUS_OK;
1192 /****************************************************************************
1193 Needed to show the msdfs symlinks as directories. Modifies psbuf
1194 to be a directory if it's a msdfs link.
1195 ****************************************************************************/
1197 static bool check_msdfs_link(connection_struct *conn,
1198 const char *pathname,
1199 SMB_STRUCT_STAT *psbuf)
1201 int saved_errno = errno;
1202 if(lp_host_msdfs() &&
1203 lp_msdfs_root(SNUM(conn)) &&
1204 is_msdfs_link(conn, pathname, psbuf)) {
1206 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1209 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1210 errno = saved_errno;
1213 errno = saved_errno;
1218 /****************************************************************************
1219 Get a level dependent lanman2 dir entry.
1220 ****************************************************************************/
1222 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1223 connection_struct *conn,
1225 const char *path_mask,
1228 int requires_resume_key,
1234 int space_remaining,
1236 bool *got_exact_match,
1237 int *last_entry_off,
1238 struct ea_list *name_list)
1242 SMB_STRUCT_STAT sbuf;
1243 const char *mask = NULL;
1244 char *pathreal = NULL;
1246 char *p, *q, *pdata = *ppdata;
1250 SMB_OFF_T file_size = 0;
1251 uint64_t allocation_size = 0;
1253 struct timespec mdate_ts, adate_ts, create_date_ts;
1254 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1256 char *last_entry_ptr;
1258 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1259 bool check_mangled_names = lp_manglednames(conn->params);
1260 char mangled_name[13]; /* mangled 8.3 name. */
1262 *out_of_space = False;
1263 *got_exact_match = False;
1265 ZERO_STRUCT(mdate_ts);
1266 ZERO_STRUCT(adate_ts);
1267 ZERO_STRUCT(create_date_ts);
1269 if (!conn->dirptr) {
1273 p = strrchr_m(path_mask,'/');
1276 mask = talloc_strdup(ctx,"*.*");
1286 bool ms_dfs_link = False;
1288 /* Needed if we run out of space */
1289 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1290 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1293 * Due to bugs in NT client redirectors we are not using
1294 * resume keys any more - set them to zero.
1295 * Check out the related comments in findfirst/findnext.
1301 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1302 (long)conn->dirptr,curr_dirpos));
1309 * fname may get mangled, dname is never mangled.
1310 * Whenever we're accessing the filesystem we use
1311 * pathreal which is composed from dname.
1317 /* Mangle fname if it's an illegal name. */
1318 if (mangle_must_mangle(dname,conn->params)) {
1319 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1321 continue; /* Error - couldn't mangle. */
1323 fname = talloc_strdup(ctx, mangled_name);
1329 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1330 got_match = mask_match(fname, mask, conn->case_sensitive);
1333 if(!got_match && check_mangled_names &&
1334 !mangle_is_8_3(fname, False, conn->params)) {
1336 * It turns out that NT matches wildcards against
1337 * both long *and* short names. This may explain some
1338 * of the wildcard wierdness from old DOS clients
1339 * that some people have been seeing.... JRA.
1341 /* Force the mangling into 8.3. */
1342 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1344 continue; /* Error - couldn't mangle. */
1347 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1348 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1353 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1355 if (dont_descend && !isdots) {
1362 pathreal = talloc_asprintf(ctx,
1367 pathreal = talloc_asprintf(ctx,
1378 if (INFO_LEVEL_IS_UNIX(info_level)) {
1379 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1380 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1381 pathreal,strerror(errno)));
1382 TALLOC_FREE(pathreal);
1386 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1387 /* Needed to show the msdfs symlinks as
1390 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1392 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1393 pathreal,strerror(errno)));
1394 TALLOC_FREE(pathreal);
1401 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1403 mode = dos_mode(conn,pathreal,&sbuf);
1406 if (!dir_check_ftype(conn,mode,dirtype)) {
1407 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1408 TALLOC_FREE(pathreal);
1413 if (!(mode & aDIR)) {
1414 file_size = get_file_size_stat(&sbuf);
1416 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1418 mdate_ts = sbuf.st_ex_mtime;
1419 adate_ts = sbuf.st_ex_atime;
1420 create_date_ts = sbuf.st_ex_btime;
1422 if (ask_sharemode) {
1423 struct timespec write_time_ts;
1424 struct file_id fileid;
1426 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1427 get_file_infos(fileid, NULL, &write_time_ts);
1428 if (!null_timespec(write_time_ts)) {
1429 mdate_ts = write_time_ts;
1433 if (lp_dos_filetime_resolution(SNUM(conn))) {
1434 dos_filetime_timespec(&create_date_ts);
1435 dos_filetime_timespec(&mdate_ts);
1436 dos_filetime_timespec(&adate_ts);
1439 create_date = convert_timespec_to_time_t(create_date_ts);
1440 mdate = convert_timespec_to_time_t(mdate_ts);
1441 adate = convert_timespec_to_time_t(adate_ts);
1443 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1448 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1458 switch (info_level) {
1459 case SMB_FIND_INFO_STANDARD:
1460 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1461 if(requires_resume_key) {
1465 srv_put_dos_date2(p,0,create_date);
1466 srv_put_dos_date2(p,4,adate);
1467 srv_put_dos_date2(p,8,mdate);
1468 SIVAL(p,12,(uint32)file_size);
1469 SIVAL(p,16,(uint32)allocation_size);
1473 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1474 p += ucs2_align(base_data, p, 0);
1476 len = srvstr_push(base_data, flags2, p,
1477 fname, PTR_DIFF(end_data, p),
1479 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1481 SCVAL(nameptr, -1, len - 2);
1483 SCVAL(nameptr, -1, 0);
1487 SCVAL(nameptr, -1, len - 1);
1489 SCVAL(nameptr, -1, 0);
1495 case SMB_FIND_EA_SIZE:
1496 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1497 if(requires_resume_key) {
1501 srv_put_dos_date2(p,0,create_date);
1502 srv_put_dos_date2(p,4,adate);
1503 srv_put_dos_date2(p,8,mdate);
1504 SIVAL(p,12,(uint32)file_size);
1505 SIVAL(p,16,(uint32)allocation_size);
1508 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1509 SIVAL(p,22,ea_size); /* Extended attributes */
1513 len = srvstr_push(base_data, flags2,
1514 p, fname, PTR_DIFF(end_data, p),
1515 STR_TERMINATE | STR_NOALIGN);
1516 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1529 SCVAL(nameptr,0,len);
1531 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1534 case SMB_FIND_EA_LIST:
1536 struct ea_list *file_list = NULL;
1539 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1543 if(requires_resume_key) {
1547 srv_put_dos_date2(p,0,create_date);
1548 srv_put_dos_date2(p,4,adate);
1549 srv_put_dos_date2(p,8,mdate);
1550 SIVAL(p,12,(uint32)file_size);
1551 SIVAL(p,16,(uint32)allocation_size);
1553 p += 22; /* p now points to the EA area. */
1555 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1556 name_list = ea_list_union(name_list, file_list, &ea_len);
1558 /* We need to determine if this entry will fit in the space available. */
1559 /* Max string size is 255 bytes. */
1560 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1561 /* Move the dirptr back to prev_dirpos */
1562 dptr_SeekDir(conn->dirptr, prev_dirpos);
1563 *out_of_space = True;
1564 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1565 return False; /* Not finished - just out of space */
1568 /* Push the ea_data followed by the name. */
1569 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1571 len = srvstr_push(base_data, flags2,
1572 p + 1, fname, PTR_DIFF(end_data, p+1),
1573 STR_TERMINATE | STR_NOALIGN);
1574 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1587 SCVAL(nameptr,0,len);
1589 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1593 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1594 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1595 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1597 SIVAL(p,0,reskey); p += 4;
1598 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1599 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1600 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1601 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1602 SOFF_T(p,0,file_size); p += 8;
1603 SOFF_T(p,0,allocation_size); p += 8;
1604 SIVAL(p,0,mode); p += 4;
1605 q = p; p += 4; /* q is placeholder for name length. */
1607 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1608 SIVAL(p,0,ea_size); /* Extended attributes */
1611 /* Clear the short name buffer. This is
1612 * IMPORTANT as not doing so will trigger
1613 * a Win2k client bug. JRA.
1615 if (!was_8_3 && check_mangled_names) {
1616 if (!name_to_8_3(fname,mangled_name,True,
1618 /* Error - mangle failed ! */
1619 memset(mangled_name,'\0',12);
1621 mangled_name[12] = 0;
1622 len = srvstr_push(base_data, flags2,
1623 p+2, mangled_name, 24,
1624 STR_UPPER|STR_UNICODE);
1626 memset(p + 2 + len,'\0',24 - len);
1633 len = srvstr_push(base_data, flags2, p,
1634 fname, PTR_DIFF(end_data, p),
1635 STR_TERMINATE_ASCII);
1638 SIVAL(p,0,0); /* Ensure any padding is null. */
1639 len = PTR_DIFF(p, pdata);
1640 len = (len + 3) & ~3;
1645 case SMB_FIND_FILE_DIRECTORY_INFO:
1646 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1648 SIVAL(p,0,reskey); p += 4;
1649 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1650 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1651 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1652 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1653 SOFF_T(p,0,file_size); p += 8;
1654 SOFF_T(p,0,allocation_size); p += 8;
1655 SIVAL(p,0,mode); p += 4;
1656 len = srvstr_push(base_data, flags2,
1657 p + 4, fname, PTR_DIFF(end_data, p+4),
1658 STR_TERMINATE_ASCII);
1661 SIVAL(p,0,0); /* Ensure any padding is null. */
1662 len = PTR_DIFF(p, pdata);
1663 len = (len + 3) & ~3;
1668 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1669 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1671 SIVAL(p,0,reskey); p += 4;
1672 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1673 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1674 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1675 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1676 SOFF_T(p,0,file_size); p += 8;
1677 SOFF_T(p,0,allocation_size); p += 8;
1678 SIVAL(p,0,mode); p += 4;
1679 q = p; p += 4; /* q is placeholder for name length. */
1681 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1682 SIVAL(p,0,ea_size); /* Extended attributes */
1685 len = srvstr_push(base_data, flags2, p,
1686 fname, PTR_DIFF(end_data, p),
1687 STR_TERMINATE_ASCII);
1691 SIVAL(p,0,0); /* Ensure any padding is null. */
1692 len = PTR_DIFF(p, pdata);
1693 len = (len + 3) & ~3;
1698 case SMB_FIND_FILE_NAMES_INFO:
1699 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1701 SIVAL(p,0,reskey); p += 4;
1703 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1704 acl on a dir (tridge) */
1705 len = srvstr_push(base_data, flags2, p,
1706 fname, PTR_DIFF(end_data, p),
1707 STR_TERMINATE_ASCII);
1710 SIVAL(p,0,0); /* Ensure any padding is null. */
1711 len = PTR_DIFF(p, pdata);
1712 len = (len + 3) & ~3;
1717 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1718 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1720 SIVAL(p,0,reskey); p += 4;
1721 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1722 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1723 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1724 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1725 SOFF_T(p,0,file_size); p += 8;
1726 SOFF_T(p,0,allocation_size); p += 8;
1727 SIVAL(p,0,mode); p += 4;
1728 q = p; p += 4; /* q is placeholder for name length. */
1730 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1731 SIVAL(p,0,ea_size); /* Extended attributes */
1734 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1735 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1736 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1737 len = srvstr_push(base_data, flags2, p,
1738 fname, PTR_DIFF(end_data, p),
1739 STR_TERMINATE_ASCII);
1742 SIVAL(p,0,0); /* Ensure any padding is null. */
1743 len = PTR_DIFF(p, pdata);
1744 len = (len + 3) & ~3;
1749 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1750 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1751 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1753 SIVAL(p,0,reskey); p += 4;
1754 put_long_date_timespec(conn->ts_res, p,create_date_ts); p += 8;
1755 put_long_date_timespec(conn->ts_res, p,adate_ts); p += 8;
1756 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1757 put_long_date_timespec(conn->ts_res, p,mdate_ts); p += 8;
1758 SOFF_T(p,0,file_size); p += 8;
1759 SOFF_T(p,0,allocation_size); p += 8;
1760 SIVAL(p,0,mode); p += 4;
1761 q = p; p += 4; /* q is placeholder for name length */
1763 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1764 SIVAL(p,0,ea_size); /* Extended attributes */
1767 /* Clear the short name buffer. This is
1768 * IMPORTANT as not doing so will trigger
1769 * a Win2k client bug. JRA.
1771 if (!was_8_3 && check_mangled_names) {
1772 if (!name_to_8_3(fname,mangled_name,True,
1774 /* Error - mangle failed ! */
1775 memset(mangled_name,'\0',12);
1777 mangled_name[12] = 0;
1778 len = srvstr_push(base_data, flags2,
1779 p+2, mangled_name, 24,
1780 STR_UPPER|STR_UNICODE);
1783 memset(p + 2 + len,'\0',24 - len);
1790 SSVAL(p,0,0); p += 2; /* Reserved ? */
1791 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1792 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1793 len = srvstr_push(base_data, flags2, p,
1794 fname, PTR_DIFF(end_data, p),
1795 STR_TERMINATE_ASCII);
1798 SIVAL(p,0,0); /* Ensure any padding is null. */
1799 len = PTR_DIFF(p, pdata);
1800 len = (len + 3) & ~3;
1805 /* CIFS UNIX Extension. */
1807 case SMB_FIND_FILE_UNIX:
1808 case SMB_FIND_FILE_UNIX_INFO2:
1810 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1812 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1814 if (info_level == SMB_FIND_FILE_UNIX) {
1815 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1816 p = store_file_unix_basic(conn, p,
1818 len = srvstr_push(base_data, flags2, p,
1819 fname, PTR_DIFF(end_data, p),
1822 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1823 p = store_file_unix_basic_info2(conn, p,
1827 len = srvstr_push(base_data, flags2, p, fname,
1828 PTR_DIFF(end_data, p), 0);
1829 SIVAL(nameptr, 0, len);
1833 SIVAL(p,0,0); /* Ensure any padding is null. */
1835 len = PTR_DIFF(p, pdata);
1836 len = (len + 3) & ~3;
1837 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1839 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1849 if (PTR_DIFF(p,pdata) > space_remaining) {
1850 /* Move the dirptr back to prev_dirpos */
1851 dptr_SeekDir(conn->dirptr, prev_dirpos);
1852 *out_of_space = True;
1853 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1854 return False; /* Not finished - just out of space */
1857 /* Setup the last entry pointer, as an offset from base_data */
1858 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1859 /* Advance the data pointer to the next slot */
1865 /****************************************************************************
1866 Reply to a TRANS2_FINDFIRST.
1867 ****************************************************************************/
1869 static void call_trans2findfirst(connection_struct *conn,
1870 struct smb_request *req,
1871 char **pparams, int total_params,
1872 char **ppdata, int total_data,
1873 unsigned int max_data_bytes)
1875 /* We must be careful here that we don't return more than the
1876 allowed number of data bytes. If this means returning fewer than
1877 maxentries then so be it. We assume that the redirector has
1878 enough room for the fixed number of parameter bytes it has
1880 char *params = *pparams;
1881 char *pdata = *ppdata;
1885 uint16 findfirst_flags;
1886 bool close_after_first;
1888 bool requires_resume_key;
1890 char *directory = NULL;
1893 int last_entry_off=0;
1897 bool finished = False;
1898 bool dont_descend = False;
1899 bool out_of_space = False;
1900 int space_remaining;
1901 bool mask_contains_wcard = False;
1902 SMB_STRUCT_STAT sbuf;
1903 struct ea_list *ea_list = NULL;
1904 NTSTATUS ntstatus = NT_STATUS_OK;
1905 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1906 TALLOC_CTX *ctx = talloc_tos();
1908 if (total_params < 13) {
1909 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1913 dirtype = SVAL(params,0);
1914 maxentries = SVAL(params,2);
1915 findfirst_flags = SVAL(params,4);
1916 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1917 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1918 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1919 info_level = SVAL(params,6);
1921 DEBUG(0,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1922 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1923 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1924 info_level, max_data_bytes));
1927 /* W2K3 seems to treat zero as 1. */
1931 switch (info_level) {
1932 case SMB_FIND_INFO_STANDARD:
1933 case SMB_FIND_EA_SIZE:
1934 case SMB_FIND_EA_LIST:
1935 case SMB_FIND_FILE_DIRECTORY_INFO:
1936 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1937 case SMB_FIND_FILE_NAMES_INFO:
1938 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1939 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1940 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1942 case SMB_FIND_FILE_UNIX:
1943 case SMB_FIND_FILE_UNIX_INFO2:
1944 /* Always use filesystem for UNIX mtime query. */
1945 ask_sharemode = false;
1946 if (!lp_unix_extensions()) {
1947 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1952 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1955 DEBUG(0,("call_trans2findfirst: before srvstr_get_path_wcard\n"));
1956 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1957 params+12, total_params - 12,
1958 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1959 if (!NT_STATUS_IS_OK(ntstatus)) {
1960 reply_nterror(req, ntstatus);
1964 DEBUG(0,("call_trans2findfirst: before resolve_dfspath_wcard\n"));
1965 ntstatus = resolve_dfspath_wcard(ctx, conn,
1966 req->flags2 & FLAGS2_DFS_PATHNAMES,
1969 &mask_contains_wcard);
1970 if (!NT_STATUS_IS_OK(ntstatus)) {
1971 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1972 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1973 ERRSRV, ERRbadpath);
1976 reply_nterror(req, ntstatus);
1980 DEBUG(0,("call_trans2findfirst: before unix_convert\n"));
1981 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1982 if (!NT_STATUS_IS_OK(ntstatus)) {
1983 reply_nterror(req, ntstatus);
1987 DEBUG(0,("call_trans2findfirst: before check_name dir[%s] mask[%s]\n",
1989 ntstatus = check_name(conn, directory);
1990 if (!NT_STATUS_IS_OK(ntstatus)) {
1991 reply_nterror(req, ntstatus);
1995 p = strrchr_m(directory,'/');
1997 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
1998 if((directory[0] == '.') && (directory[1] == '\0')) {
1999 mask = talloc_strdup(ctx,"*");
2001 reply_nterror(req, NT_STATUS_NO_MEMORY);
2004 mask_contains_wcard = True;
2006 directory = talloc_strdup(talloc_tos(), "./");
2008 reply_nterror(req, NT_STATUS_NO_MEMORY);
2015 DEBUG(0,("dir=%s, mask = %s\n",directory, mask));
2017 if (info_level == SMB_FIND_EA_LIST) {
2020 if (total_data < 4) {
2021 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2025 ea_size = IVAL(pdata,0);
2026 if (ea_size != total_data) {
2027 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2028 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2033 if (!lp_ea_support(SNUM(conn))) {
2034 reply_doserror(req, ERRDOS, ERReasnotsupported);
2038 /* Pull out the list of names. */
2039 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2041 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2046 *ppdata = (char *)SMB_REALLOC(
2047 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2048 if(*ppdata == NULL ) {
2049 reply_nterror(req, NT_STATUS_NO_MEMORY);
2053 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2055 /* Realloc the params space */
2056 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2057 if (*pparams == NULL) {
2058 reply_nterror(req, NT_STATUS_NO_MEMORY);
2063 /* Save the wildcard match and attribs we are using on this directory -
2064 needed as lanman2 assumes these are being saved between calls */
2066 ntstatus = dptr_create(conn,
2072 mask_contains_wcard,
2076 if (!NT_STATUS_IS_OK(ntstatus)) {
2077 reply_nterror(req, ntstatus);
2081 dptr_num = dptr_dnum(conn->dirptr);
2082 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2084 /* Initialize per TRANS2_FIND_FIRST operation data */
2085 dptr_init_search_op(conn->dirptr);
2087 /* We don't need to check for VOL here as this is returned by
2088 a different TRANS2 call. */
2090 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2091 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2092 dont_descend = True;
2095 space_remaining = max_data_bytes;
2096 out_of_space = False;
2098 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2099 bool got_exact_match = False;
2101 /* this is a heuristic to avoid seeking the dirptr except when
2102 absolutely necessary. It allows for a filename of about 40 chars */
2103 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2104 out_of_space = True;
2107 finished = !get_lanman2_dir_entry(ctx,
2110 mask,dirtype,info_level,
2111 requires_resume_key,dont_descend,
2114 space_remaining, &out_of_space,
2116 &last_entry_off, ea_list);
2119 if (finished && out_of_space)
2122 if (!finished && !out_of_space)
2126 * As an optimisation if we know we aren't looking
2127 * for a wildcard name (ie. the name matches the wildcard exactly)
2128 * then we can finish on any (first) match.
2129 * This speeds up large directory searches. JRA.
2135 /* Ensure space_remaining never goes -ve. */
2136 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2137 space_remaining = 0;
2138 out_of_space = true;
2140 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2144 /* Check if we can close the dirptr */
2145 if(close_after_first || (finished && close_if_end)) {
2146 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2147 dptr_close(&dptr_num);
2151 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2152 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2153 * the protocol level is less than NT1. Tested with smbclient. JRA.
2154 * This should fix the OS/2 client bug #2335.
2157 if(numentries == 0) {
2158 dptr_close(&dptr_num);
2159 if (Protocol < PROTOCOL_NT1) {
2160 reply_doserror(req, ERRDOS, ERRnofiles);
2163 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2164 ERRDOS, ERRbadfile);
2169 /* At this point pdata points to numentries directory entries. */
2171 /* Set up the return parameter block */
2172 SSVAL(params,0,dptr_num);
2173 SSVAL(params,2,numentries);
2174 SSVAL(params,4,finished);
2175 SSVAL(params,6,0); /* Never an EA error */
2176 SSVAL(params,8,last_entry_off);
2178 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2181 if ((! *directory) && dptr_path(dptr_num)) {
2182 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2184 reply_nterror(req, NT_STATUS_NO_MEMORY);
2188 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2189 smb_fn_name(req->cmd),
2190 mask, directory, dirtype, numentries ) );
2193 * Force a name mangle here to ensure that the
2194 * mask as an 8.3 name is top of the mangled cache.
2195 * The reasons for this are subtle. Don't remove
2196 * this code unless you know what you are doing
2197 * (see PR#13758). JRA.
2200 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2201 char mangled_name[13];
2202 name_to_8_3(mask, mangled_name, True, conn->params);
2208 /****************************************************************************
2209 Reply to a TRANS2_FINDNEXT.
2210 ****************************************************************************/
2212 static void call_trans2findnext(connection_struct *conn,
2213 struct smb_request *req,
2214 char **pparams, int total_params,
2215 char **ppdata, int total_data,
2216 unsigned int max_data_bytes)
2218 /* We must be careful here that we don't return more than the
2219 allowed number of data bytes. If this means returning fewer than
2220 maxentries then so be it. We assume that the redirector has
2221 enough room for the fixed number of parameter bytes it has
2223 char *params = *pparams;
2224 char *pdata = *ppdata;
2230 uint16 findnext_flags;
2231 bool close_after_request;
2233 bool requires_resume_key;
2235 bool mask_contains_wcard = False;
2236 char *resume_name = NULL;
2237 const char *mask = NULL;
2238 const char *directory = NULL;
2242 int i, last_entry_off=0;
2243 bool finished = False;
2244 bool dont_descend = False;
2245 bool out_of_space = False;
2246 int space_remaining;
2247 struct ea_list *ea_list = NULL;
2248 NTSTATUS ntstatus = NT_STATUS_OK;
2249 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2250 TALLOC_CTX *ctx = talloc_tos();
2252 if (total_params < 13) {
2253 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2257 dptr_num = SVAL(params,0);
2258 maxentries = SVAL(params,2);
2259 info_level = SVAL(params,4);
2260 resume_key = IVAL(params,6);
2261 findnext_flags = SVAL(params,10);
2262 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2263 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2264 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2265 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2267 if (!continue_bit) {
2268 /* We only need resume_name if continue_bit is zero. */
2269 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2271 total_params - 12, STR_TERMINATE, &ntstatus,
2272 &mask_contains_wcard);
2273 if (!NT_STATUS_IS_OK(ntstatus)) {
2274 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2275 complain (it thinks we're asking for the directory above the shared
2276 path or an invalid name). Catch this as the resume name is only compared, never used in
2277 a file access. JRA. */
2278 srvstr_pull_talloc(ctx, params, req->flags2,
2279 &resume_name, params+12,
2283 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2284 reply_nterror(req, ntstatus);
2290 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2291 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2292 resume_key = %d resume name = %s continue=%d level = %d\n",
2293 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2294 requires_resume_key, resume_key,
2295 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2298 /* W2K3 seems to treat zero as 1. */
2302 switch (info_level) {
2303 case SMB_FIND_INFO_STANDARD:
2304 case SMB_FIND_EA_SIZE:
2305 case SMB_FIND_EA_LIST:
2306 case SMB_FIND_FILE_DIRECTORY_INFO:
2307 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2308 case SMB_FIND_FILE_NAMES_INFO:
2309 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2310 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2311 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2313 case SMB_FIND_FILE_UNIX:
2314 case SMB_FIND_FILE_UNIX_INFO2:
2315 /* Always use filesystem for UNIX mtime query. */
2316 ask_sharemode = false;
2317 if (!lp_unix_extensions()) {
2318 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2323 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2327 if (info_level == SMB_FIND_EA_LIST) {
2330 if (total_data < 4) {
2331 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2335 ea_size = IVAL(pdata,0);
2336 if (ea_size != total_data) {
2337 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2338 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2339 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2343 if (!lp_ea_support(SNUM(conn))) {
2344 reply_doserror(req, ERRDOS, ERReasnotsupported);
2348 /* Pull out the list of names. */
2349 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2351 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2356 *ppdata = (char *)SMB_REALLOC(
2357 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2358 if(*ppdata == NULL) {
2359 reply_nterror(req, NT_STATUS_NO_MEMORY);
2364 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2366 /* Realloc the params space */
2367 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2368 if(*pparams == NULL ) {
2369 reply_nterror(req, NT_STATUS_NO_MEMORY);
2375 /* Check that the dptr is valid */
2376 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2377 reply_doserror(req, ERRDOS, ERRnofiles);
2381 string_set(&conn->dirpath,dptr_path(dptr_num));
2383 /* Get the wildcard mask from the dptr */
2384 if((p = dptr_wcard(dptr_num))== NULL) {
2385 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2386 reply_doserror(req, ERRDOS, ERRnofiles);
2391 directory = conn->dirpath;
2393 /* Get the attr mask from the dptr */
2394 dirtype = dptr_attr(dptr_num);
2396 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2397 dptr_num, mask, dirtype,
2399 dptr_TellDir(conn->dirptr)));
2401 /* Initialize per TRANS2_FIND_NEXT operation data */
2402 dptr_init_search_op(conn->dirptr);
2404 /* We don't need to check for VOL here as this is returned by
2405 a different TRANS2 call. */
2407 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2408 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2409 dont_descend = True;
2412 space_remaining = max_data_bytes;
2413 out_of_space = False;
2416 * Seek to the correct position. We no longer use the resume key but
2417 * depend on the last file name instead.
2420 if(!continue_bit && resume_name && *resume_name) {
2423 long current_pos = 0;
2425 * Remember, name_to_8_3 is called by
2426 * get_lanman2_dir_entry(), so the resume name
2427 * could be mangled. Ensure we check the unmangled name.
2430 if (mangle_is_mangled(resume_name, conn->params)) {
2431 char *new_resume_name = NULL;
2432 mangle_lookup_name_from_8_3(ctx,
2436 if (new_resume_name) {
2437 resume_name = new_resume_name;
2442 * Fix for NT redirector problem triggered by resume key indexes
2443 * changing between directory scans. We now return a resume key of 0
2444 * and instead look for the filename to continue from (also given
2445 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2446 * findfirst/findnext (as is usual) then the directory pointer
2447 * should already be at the correct place.
2450 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2451 } /* end if resume_name && !continue_bit */
2453 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2454 bool got_exact_match = False;
2456 /* this is a heuristic to avoid seeking the dirptr except when
2457 absolutely necessary. It allows for a filename of about 40 chars */
2458 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2459 out_of_space = True;
2462 finished = !get_lanman2_dir_entry(ctx,
2465 mask,dirtype,info_level,
2466 requires_resume_key,dont_descend,
2469 space_remaining, &out_of_space,
2471 &last_entry_off, ea_list);
2474 if (finished && out_of_space)
2477 if (!finished && !out_of_space)
2481 * As an optimisation if we know we aren't looking
2482 * for a wildcard name (ie. the name matches the wildcard exactly)
2483 * then we can finish on any (first) match.
2484 * This speeds up large directory searches. JRA.
2490 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2493 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2494 smb_fn_name(req->cmd),
2495 mask, directory, dirtype, numentries ) );
2497 /* Check if we can close the dirptr */
2498 if(close_after_request || (finished && close_if_end)) {
2499 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2500 dptr_close(&dptr_num); /* This frees up the saved mask */
2503 /* Set up the return parameter block */
2504 SSVAL(params,0,numentries);
2505 SSVAL(params,2,finished);
2506 SSVAL(params,4,0); /* Never an EA error */
2507 SSVAL(params,6,last_entry_off);
2509 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2515 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2517 E_md4hash(lp_servicename(SNUM(conn)),objid);
2521 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2523 SMB_ASSERT(extended_info != NULL);
2525 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2526 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2527 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2528 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2529 #ifdef SAMBA_VERSION_REVISION
2530 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2532 extended_info->samba_subversion = 0;
2533 #ifdef SAMBA_VERSION_RC_RELEASE
2534 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2536 #ifdef SAMBA_VERSION_PRE_RELEASE
2537 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2540 #ifdef SAMBA_VERSION_VENDOR_PATCH
2541 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2543 extended_info->samba_gitcommitdate = 0;
2544 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2545 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2548 memset(extended_info->samba_version_string, 0,
2549 sizeof(extended_info->samba_version_string));
2551 snprintf (extended_info->samba_version_string,
2552 sizeof(extended_info->samba_version_string),
2553 "%s", samba_version_string());
2556 /****************************************************************************
2557 Reply to a TRANS2_QFSINFO (query filesystem info).
2558 ****************************************************************************/
2560 static void call_trans2qfsinfo(connection_struct *conn,
2561 struct smb_request *req,
2562 char **pparams, int total_params,
2563 char **ppdata, int total_data,
2564 unsigned int max_data_bytes)
2566 char *pdata, *end_data;
2567 char *params = *pparams;
2571 const char *vname = volume_label(SNUM(conn));
2572 int snum = SNUM(conn);
2573 char *fstype = lp_fstype(SNUM(conn));
2574 uint32 additional_flags = 0;
2576 if (total_params < 2) {
2577 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2581 info_level = SVAL(params,0);
2584 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2585 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2586 "info level (0x%x) on IPC$.\n",
2587 (unsigned int)info_level));
2588 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2593 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2594 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2595 DEBUG(0,("call_trans2qfsinfo: encryption required "
2596 "and info level 0x%x sent.\n",
2597 (unsigned int)info_level));
2598 exit_server_cleanly("encryption required "
2604 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2606 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2607 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2608 reply_doserror(req, ERRSRV, ERRinvdevice);
2612 *ppdata = (char *)SMB_REALLOC(
2613 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2614 if (*ppdata == NULL ) {
2615 reply_nterror(req, NT_STATUS_NO_MEMORY);
2620 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2621 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2623 switch (info_level) {
2624 case SMB_INFO_ALLOCATION:
2626 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2628 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2629 reply_unixerror(req, ERRHRD, ERRgeneral);
2633 block_size = lp_block_size(snum);
2634 if (bsize < block_size) {
2635 uint64_t factor = block_size/bsize;
2640 if (bsize > block_size) {
2641 uint64_t factor = bsize/block_size;
2646 bytes_per_sector = 512;
2647 sectors_per_unit = bsize/bytes_per_sector;
2649 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2650 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2651 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2653 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2654 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2655 SIVAL(pdata,l1_cUnit,dsize);
2656 SIVAL(pdata,l1_cUnitAvail,dfree);
2657 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2661 case SMB_INFO_VOLUME:
2662 /* Return volume name */
2664 * Add volume serial number - hash of a combination of
2665 * the called hostname and the service name.
2667 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2669 * Win2k3 and previous mess this up by sending a name length
2670 * one byte short. I believe only older clients (OS/2 Win9x) use
2671 * this call so try fixing this by adding a terminating null to
2672 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2676 pdata+l2_vol_szVolLabel, vname,
2677 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2678 STR_NOALIGN|STR_TERMINATE);
2679 SCVAL(pdata,l2_vol_cch,len);
2680 data_len = l2_vol_szVolLabel + len;
2681 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2682 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2686 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2687 case SMB_FS_ATTRIBUTE_INFORMATION:
2689 additional_flags = 0;
2690 #if defined(HAVE_SYS_QUOTAS)
2691 additional_flags |= FILE_VOLUME_QUOTAS;
2694 if(lp_nt_acl_support(SNUM(conn))) {
2695 additional_flags |= FILE_PERSISTENT_ACLS;
2698 /* Capabilities are filled in at connection time through STATVFS call */
2699 additional_flags |= conn->fs_capabilities;
2700 additional_flags |= lp_parm_int(conn->params->service,
2701 "share", "fake_fscaps",
2704 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2705 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2706 additional_flags); /* FS ATTRIBUTES */
2708 SIVAL(pdata,4,255); /* Max filename component length */
2709 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2710 and will think we can't do long filenames */
2711 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2712 PTR_DIFF(end_data, pdata+12),
2715 data_len = 12 + len;
2718 case SMB_QUERY_FS_LABEL_INFO:
2719 case SMB_FS_LABEL_INFORMATION:
2720 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2721 PTR_DIFF(end_data, pdata+4), 0);
2726 case SMB_QUERY_FS_VOLUME_INFO:
2727 case SMB_FS_VOLUME_INFORMATION:
2730 * Add volume serial number - hash of a combination of
2731 * the called hostname and the service name.
2733 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2734 (str_checksum(get_local_machine_name())<<16));
2736 /* Max label len is 32 characters. */
2737 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2738 PTR_DIFF(end_data, pdata+18),
2740 SIVAL(pdata,12,len);
2743 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2744 (int)strlen(vname),vname, lp_servicename(snum)));
2747 case SMB_QUERY_FS_SIZE_INFO:
2748 case SMB_FS_SIZE_INFORMATION:
2750 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2752 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2753 reply_unixerror(req, ERRHRD, ERRgeneral);
2756 block_size = lp_block_size(snum);
2757 if (bsize < block_size) {
2758 uint64_t factor = block_size/bsize;
2763 if (bsize > block_size) {
2764 uint64_t factor = bsize/block_size;
2769 bytes_per_sector = 512;
2770 sectors_per_unit = bsize/bytes_per_sector;
2771 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2772 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2773 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2774 SBIG_UINT(pdata,0,dsize);
2775 SBIG_UINT(pdata,8,dfree);
2776 SIVAL(pdata,16,sectors_per_unit);
2777 SIVAL(pdata,20,bytes_per_sector);
2781 case SMB_FS_FULL_SIZE_INFORMATION:
2783 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2785 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2786 reply_unixerror(req, ERRHRD, ERRgeneral);
2789 block_size = lp_block_size(snum);
2790 if (bsize < block_size) {
2791 uint64_t factor = block_size/bsize;
2796 if (bsize > block_size) {
2797 uint64_t factor = bsize/block_size;
2802 bytes_per_sector = 512;
2803 sectors_per_unit = bsize/bytes_per_sector;
2804 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2805 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2806 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2807 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2808 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2809 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2810 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2811 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2815 case SMB_QUERY_FS_DEVICE_INFO:
2816 case SMB_FS_DEVICE_INFORMATION:
2818 SIVAL(pdata,0,0); /* dev type */
2819 SIVAL(pdata,4,0); /* characteristics */
2822 #ifdef HAVE_SYS_QUOTAS
2823 case SMB_FS_QUOTA_INFORMATION:
2825 * what we have to send --metze:
2827 * Unknown1: 24 NULL bytes
2828 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2829 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2830 * Quota Flags: 2 byte :
2831 * Unknown3: 6 NULL bytes
2835 * details for Quota Flags:
2837 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2838 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2839 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2840 * 0x0001 Enable Quotas: enable quota for this fs
2844 /* we need to fake up a fsp here,
2845 * because its not send in this call
2848 SMB_NTQUOTA_STRUCT quotas;
2851 ZERO_STRUCT(quotas);
2857 if (conn->server_info->utok.uid != 0) {
2858 DEBUG(0,("set_user_quota: access_denied "
2859 "service [%s] user [%s]\n",
2860 lp_servicename(SNUM(conn)),
2861 conn->server_info->unix_name));
2862 reply_doserror(req, ERRDOS, ERRnoaccess);
2866 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2867 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2868 reply_doserror(req, ERRSRV, ERRerror);
2874 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2876 /* Unknown1 24 NULL bytes*/
2877 SBIG_UINT(pdata,0,(uint64_t)0);
2878 SBIG_UINT(pdata,8,(uint64_t)0);
2879 SBIG_UINT(pdata,16,(uint64_t)0);
2881 /* Default Soft Quota 8 bytes */
2882 SBIG_UINT(pdata,24,quotas.softlim);
2884 /* Default Hard Quota 8 bytes */
2885 SBIG_UINT(pdata,32,quotas.hardlim);
2887 /* Quota flag 2 bytes */
2888 SSVAL(pdata,40,quotas.qflags);
2890 /* Unknown3 6 NULL bytes */
2896 #endif /* HAVE_SYS_QUOTAS */
2897 case SMB_FS_OBJECTID_INFORMATION:
2899 unsigned char objid[16];
2900 struct smb_extended_info extended_info;
2901 memcpy(pdata,create_volume_objectid(conn, objid),16);
2902 samba_extended_info_version (&extended_info);
2903 SIVAL(pdata,16,extended_info.samba_magic);
2904 SIVAL(pdata,20,extended_info.samba_version);
2905 SIVAL(pdata,24,extended_info.samba_subversion);
2906 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2907 memcpy(pdata+36,extended_info.samba_version_string,28);
2913 * Query the version and capabilities of the CIFS UNIX extensions
2917 case SMB_QUERY_CIFS_UNIX_INFO:
2919 bool large_write = lp_min_receive_file_size() &&
2920 !srv_is_signing_active(smbd_server_conn);
2921 bool large_read = !srv_is_signing_active(smbd_server_conn);
2922 int encrypt_caps = 0;
2924 if (!lp_unix_extensions()) {
2925 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2929 switch (conn->encrypt_level) {
2935 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2938 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2939 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2940 large_write = false;
2946 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2947 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2949 /* We have POSIX ACLs, pathname, encryption,
2950 * large read/write, and locking capability. */
2952 SBIG_UINT(pdata,4,((uint64_t)(
2953 CIFS_UNIX_POSIX_ACLS_CAP|
2954 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2955 CIFS_UNIX_FCNTL_LOCKS_CAP|
2956 CIFS_UNIX_EXTATTR_CAP|
2957 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2959 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2961 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2965 case SMB_QUERY_POSIX_FS_INFO:
2968 vfs_statvfs_struct svfs;
2970 if (!lp_unix_extensions()) {
2971 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2975 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2979 SIVAL(pdata,0,svfs.OptimalTransferSize);
2980 SIVAL(pdata,4,svfs.BlockSize);
2981 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2982 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2983 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2984 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2985 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2986 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2987 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2989 } else if (rc == EOPNOTSUPP) {
2990 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2992 #endif /* EOPNOTSUPP */
2994 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2995 reply_doserror(req, ERRSRV, ERRerror);
3001 case SMB_QUERY_POSIX_WHOAMI:
3007 if (!lp_unix_extensions()) {
3008 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3012 if (max_data_bytes < 40) {
3013 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3017 /* We ARE guest if global_sid_Builtin_Guests is
3018 * in our list of SIDs.
3020 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3021 conn->server_info->ptok)) {
3022 flags |= SMB_WHOAMI_GUEST;
3025 /* We are NOT guest if global_sid_Authenticated_Users
3026 * is in our list of SIDs.
3028 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3029 conn->server_info->ptok)) {
3030 flags &= ~SMB_WHOAMI_GUEST;
3033 /* NOTE: 8 bytes for UID/GID, irrespective of native
3034 * platform size. This matches
3035 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3037 data_len = 4 /* flags */
3044 + 4 /* pad/reserved */
3045 + (conn->server_info->utok.ngroups * 8)
3047 + (conn->server_info->ptok->num_sids *
3051 SIVAL(pdata, 0, flags);
3052 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3054 (uint64_t)conn->server_info->utok.uid);
3055 SBIG_UINT(pdata, 16,
3056 (uint64_t)conn->server_info->utok.gid);
3059 if (data_len >= max_data_bytes) {
3060 /* Potential overflow, skip the GIDs and SIDs. */
3062 SIVAL(pdata, 24, 0); /* num_groups */
3063 SIVAL(pdata, 28, 0); /* num_sids */
3064 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3065 SIVAL(pdata, 36, 0); /* reserved */
3071 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3072 SIVAL(pdata, 28, conn->server_info->num_sids);
3074 /* We walk the SID list twice, but this call is fairly
3075 * infrequent, and I don't expect that it's performance
3076 * sensitive -- jpeach
3078 for (i = 0, sid_bytes = 0;
3079 i < conn->server_info->ptok->num_sids; ++i) {
3080 sid_bytes += ndr_size_dom_sid(
3081 &conn->server_info->ptok->user_sids[i],
3086 /* SID list byte count */
3087 SIVAL(pdata, 32, sid_bytes);
3089 /* 4 bytes pad/reserved - must be zero */
3090 SIVAL(pdata, 36, 0);
3094 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3095 SBIG_UINT(pdata, data_len,
3096 (uint64_t)conn->server_info->utok.groups[i]);
3102 i < conn->server_info->ptok->num_sids; ++i) {
3103 int sid_len = ndr_size_dom_sid(
3104 &conn->server_info->ptok->user_sids[i],
3108 sid_linearize(pdata + data_len, sid_len,
3109 &conn->server_info->ptok->user_sids[i]);
3110 data_len += sid_len;
3116 case SMB_MAC_QUERY_FS_INFO:
3118 * Thursby MAC extension... ONLY on NTFS filesystems
3119 * once we do streams then we don't need this
3121 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3123 SIVAL(pdata,84,0x100); /* Don't support mac... */
3128 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3133 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3136 DEBUG( 4, ( "%s info_level = %d\n",
3137 smb_fn_name(req->cmd), info_level) );
3142 /****************************************************************************
3143 Reply to a TRANS2_SETFSINFO (set filesystem info).
3144 ****************************************************************************/
3146 static void call_trans2setfsinfo(connection_struct *conn,
3147 struct smb_request *req,
3148 char **pparams, int total_params,
3149 char **ppdata, int total_data,
3150 unsigned int max_data_bytes)
3152 char *pdata = *ppdata;
3153 char *params = *pparams;
3156 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3159 if (total_params < 4) {
3160 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3162 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3166 info_level = SVAL(params,2);
3169 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3170 info_level != SMB_SET_CIFS_UNIX_INFO) {
3171 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3172 "info level (0x%x) on IPC$.\n",
3173 (unsigned int)info_level));
3174 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3179 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3180 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3181 DEBUG(0,("call_trans2setfsinfo: encryption required "
3182 "and info level 0x%x sent.\n",
3183 (unsigned int)info_level));
3184 exit_server_cleanly("encryption required "
3190 switch(info_level) {
3191 case SMB_SET_CIFS_UNIX_INFO:
3193 uint16 client_unix_major;
3194 uint16 client_unix_minor;
3195 uint32 client_unix_cap_low;
3196 uint32 client_unix_cap_high;
3198 if (!lp_unix_extensions()) {
3200 NT_STATUS_INVALID_LEVEL);
3204 /* There should be 12 bytes of capabilities set. */
3205 if (total_data < 8) {
3208 NT_STATUS_INVALID_PARAMETER);
3211 client_unix_major = SVAL(pdata,0);
3212 client_unix_minor = SVAL(pdata,2);
3213 client_unix_cap_low = IVAL(pdata,4);
3214 client_unix_cap_high = IVAL(pdata,8);
3215 /* Just print these values for now. */
3216 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3217 cap_low = 0x%x, cap_high = 0x%x\n",
3218 (unsigned int)client_unix_major,
3219 (unsigned int)client_unix_minor,
3220 (unsigned int)client_unix_cap_low,
3221 (unsigned int)client_unix_cap_high ));
3223 /* Here is where we must switch to posix pathname processing... */
3224 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3225 lp_set_posix_pathnames();
3226 mangle_change_to_posix();
3229 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3230 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3231 /* Client that knows how to do posix locks,
3232 * but not posix open/mkdir operations. Set a
3233 * default type for read/write checks. */
3235 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3241 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3244 size_t param_len = 0;
3245 size_t data_len = total_data;
3247 if (!lp_unix_extensions()) {
3250 NT_STATUS_INVALID_LEVEL);
3254 if (lp_smb_encrypt(SNUM(conn)) == false) {
3257 NT_STATUS_NOT_SUPPORTED);
3261 if (smbd_server_conn->smb1.echo_handler.trusted_fde) {
3262 DEBUG( 2,("call_trans2setfsinfo: "
3263 "request transport encryption disabled"
3264 "with 'fork echo handler = yes'\n"));
3267 NT_STATUS_NOT_SUPPORTED);
3271 DEBUG( 4,("call_trans2setfsinfo: "
3272 "request transport encryption.\n"));
3274 status = srv_request_encryption_setup(conn,
3275 (unsigned char **)ppdata,
3277 (unsigned char **)pparams,
3280 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3281 !NT_STATUS_IS_OK(status)) {
3282 reply_nterror(req, status);
3286 send_trans2_replies(conn, req,
3293 if (NT_STATUS_IS_OK(status)) {
3294 /* Server-side transport
3295 * encryption is now *on*. */
3296 status = srv_encryption_start(conn);
3297 if (!NT_STATUS_IS_OK(status)) {
3298 exit_server_cleanly(
3299 "Failure in setting "
3300 "up encrypted transport");
3306 case SMB_FS_QUOTA_INFORMATION:
3308 files_struct *fsp = NULL;
3309 SMB_NTQUOTA_STRUCT quotas;
3311 ZERO_STRUCT(quotas);
3314 if ((conn->server_info->utok.uid != 0)
3315 ||!CAN_WRITE(conn)) {
3316 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3317 lp_servicename(SNUM(conn)),
3318 conn->server_info->unix_name));
3319 reply_doserror(req, ERRSRV, ERRaccess);
3323 /* note: normaly there're 48 bytes,
3324 * but we didn't use the last 6 bytes for now
3327 fsp = file_fsp(req, SVAL(params,0));
3329 if (!check_fsp_ntquota_handle(conn, req,
3331 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3333 req, NT_STATUS_INVALID_HANDLE);
3337 if (total_data < 42) {
3338 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3342 NT_STATUS_INVALID_PARAMETER);
3346 /* unknown_1 24 NULL bytes in pdata*/
3348 /* the soft quotas 8 bytes (uint64_t)*/
3349 quotas.softlim = (uint64_t)IVAL(pdata,24);
3350 #ifdef LARGE_SMB_OFF_T
3351 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3352 #else /* LARGE_SMB_OFF_T */
3353 if ((IVAL(pdata,28) != 0)&&
3354 ((quotas.softlim != 0xFFFFFFFF)||
3355 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3356 /* more than 32 bits? */
3359 NT_STATUS_INVALID_PARAMETER);
3362 #endif /* LARGE_SMB_OFF_T */
3364 /* the hard quotas 8 bytes (uint64_t)*/
3365 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3366 #ifdef LARGE_SMB_OFF_T
3367 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3368 #else /* LARGE_SMB_OFF_T */
3369 if ((IVAL(pdata,36) != 0)&&
3370 ((quotas.hardlim != 0xFFFFFFFF)||
3371 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3372 /* more than 32 bits? */
3375 NT_STATUS_INVALID_PARAMETER);
3378 #endif /* LARGE_SMB_OFF_T */
3380 /* quota_flags 2 bytes **/
3381 quotas.qflags = SVAL(pdata,40);
3383 /* unknown_2 6 NULL bytes follow*/
3385 /* now set the quotas */
3386 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3387 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3388 reply_doserror(req, ERRSRV, ERRerror);
3395 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3397 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3403 * sending this reply works fine,
3404 * but I'm not sure it's the same
3405 * like windows do...
3408 reply_outbuf(req, 10, 0);
3411 #if defined(HAVE_POSIX_ACLS)
3412 /****************************************************************************
3413 Utility function to count the number of entries in a POSIX acl.
3414 ****************************************************************************/
3416 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3418 unsigned int ace_count = 0;
3419 int entry_id = SMB_ACL_FIRST_ENTRY;
3420 SMB_ACL_ENTRY_T entry;
3422 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3424 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3425 entry_id = SMB_ACL_NEXT_ENTRY;
3432 /****************************************************************************
3433 Utility function to marshall a POSIX acl into wire format.
3434 ****************************************************************************/
3436 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3438 int entry_id = SMB_ACL_FIRST_ENTRY;
3439 SMB_ACL_ENTRY_T entry;
3441 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3442 SMB_ACL_TAG_T tagtype;
3443 SMB_ACL_PERMSET_T permset;
3444 unsigned char perms = 0;
3445 unsigned int own_grp;
3448 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3449 entry_id = SMB_ACL_NEXT_ENTRY;
3452 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3453 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3457 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3458 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3462 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3463 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3464 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3466 SCVAL(pdata,1,perms);
3469 case SMB_ACL_USER_OBJ:
3470 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3471 own_grp = (unsigned int)pst->st_ex_uid;
3472 SIVAL(pdata,2,own_grp);
3477 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3479 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3482 own_grp = (unsigned int)*puid;
3483 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3484 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3485 SIVAL(pdata,2,own_grp);
3489 case SMB_ACL_GROUP_OBJ:
3490 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3491 own_grp = (unsigned int)pst->st_ex_gid;
3492 SIVAL(pdata,2,own_grp);
3497 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3499 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3502 own_grp = (unsigned int)*pgid;
3503 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3504 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3505 SIVAL(pdata,2,own_grp);
3510 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3511 SIVAL(pdata,2,0xFFFFFFFF);
3512 SIVAL(pdata,6,0xFFFFFFFF);
3515 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3516 SIVAL(pdata,2,0xFFFFFFFF);
3517 SIVAL(pdata,6,0xFFFFFFFF);
3520 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3523 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3530 /****************************************************************************
3531 Store the FILE_UNIX_BASIC info.
3532 ****************************************************************************/
3534 static char *store_file_unix_basic(connection_struct *conn,
3537 const SMB_STRUCT_STAT *psbuf)
3539 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3540 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3542 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3545 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3548 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3549 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3550 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3553 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3557 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3561 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3564 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3568 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3572 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3575 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3579 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3586 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3587 * the chflags(2) (or equivalent) flags.
3589 * XXX: this really should be behind the VFS interface. To do this, we would
3590 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3591 * Each VFS module could then implement its own mapping as appropriate for the
3592 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3594 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3598 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3602 { UF_IMMUTABLE, EXT_IMMUTABLE },
3606 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3610 { UF_HIDDEN, EXT_HIDDEN },
3613 /* Do not remove. We need to guarantee that this array has at least one
3614 * entry to build on HP-UX.
3620 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3621 uint32 *smb_fflags, uint32 *smb_fmask)
3623 #ifdef HAVE_STAT_ST_FLAGS
3626 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3627 *smb_fmask |= info2_flags_map[i].smb_fflag;
3628 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3629 *smb_fflags |= info2_flags_map[i].smb_fflag;
3632 #endif /* HAVE_STAT_ST_FLAGS */
3635 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3636 const uint32 smb_fflags,
3637 const uint32 smb_fmask,
3640 #ifdef HAVE_STAT_ST_FLAGS
3641 uint32 max_fmask = 0;
3644 *stat_fflags = psbuf->st_ex_flags;
3646 /* For each flags requested in smb_fmask, check the state of the
3647 * corresponding flag in smb_fflags and set or clear the matching
3651 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3652 max_fmask |= info2_flags_map[i].smb_fflag;
3653 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3654 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3655 *stat_fflags |= info2_flags_map[i].stat_fflag;
3657 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3662 /* If smb_fmask is asking to set any bits that are not supported by
3663 * our flag mappings, we should fail.
3665 if ((smb_fmask & max_fmask) != smb_fmask) {
3672 #endif /* HAVE_STAT_ST_FLAGS */
3676 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3677 * of file flags and birth (create) time.
3679 static char *store_file_unix_basic_info2(connection_struct *conn,
3682 const SMB_STRUCT_STAT *psbuf)
3684 uint32 file_flags = 0;
3685 uint32 flags_mask = 0;
3687 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3689 /* Create (birth) time 64 bit */
3690 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_btime);
3693 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3694 SIVAL(pdata, 0, file_flags); /* flags */
3695 SIVAL(pdata, 4, flags_mask); /* mask */
3701 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3702 const struct stream_struct *streams,
3704 unsigned int max_data_bytes,
3705 unsigned int *data_size)
3708 unsigned int ofs = 0;
3710 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
3711 unsigned int next_offset;
3713 smb_ucs2_t *namebuf;
3715 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3716 streams[i].name, &namelen) ||
3719 return NT_STATUS_INVALID_PARAMETER;
3723 * name_buf is now null-terminated, we need to marshall as not
3729 SIVAL(data, ofs+4, namelen);
3730 SOFF_T(data, ofs+8, streams[i].size);
3731 SOFF_T(data, ofs+16, streams[i].alloc_size);
3732 memcpy(data+ofs+24, namebuf, namelen);
3733 TALLOC_FREE(namebuf);
3735 next_offset = ofs + 24 + namelen;
3737 if (i == num_streams-1) {
3738 SIVAL(data, ofs, 0);
3741 unsigned int align = ndr_align_size(next_offset, 8);
3743 memset(data+next_offset, 0, align);
3744 next_offset += align;
3746 SIVAL(data, ofs, next_offset - ofs);
3755 return NT_STATUS_OK;
3758 /****************************************************************************
3759 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3760 ****************************************************************************/
3762 static void call_trans2qpipeinfo(connection_struct *conn,
3763 struct smb_request *req,
3764 unsigned int tran_call,
3765 char **pparams, int total_params,
3766 char **ppdata, int total_data,
3767 unsigned int max_data_bytes)
3769 char *params = *pparams;
3770 char *pdata = *ppdata;
3771 unsigned int data_size = 0;
3772 unsigned int param_size = 2;
3777 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3781 if (total_params < 4) {
3782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3786 fsp = file_fsp(req, SVAL(params,0));
3787 if (!fsp_is_np(fsp)) {
3788 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3792 info_level = SVAL(params,2);
3794 *pparams = (char *)SMB_REALLOC(*pparams,2);
3795 if (*pparams == NULL) {
3796 reply_nterror(req, NT_STATUS_NO_MEMORY);
3801 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3802 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3803 if (*ppdata == NULL ) {
3804 reply_nterror(req, NT_STATUS_NO_MEMORY);
3809 switch (info_level) {
3810 case SMB_FILE_STANDARD_INFORMATION:
3812 SOFF_T(pdata,0,4096LL);
3819 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3823 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3829 /****************************************************************************
3830 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3831 file name or file id).
3832 ****************************************************************************/
3834 static void call_trans2qfilepathinfo(connection_struct *conn,
3835 struct smb_request *req,
3836 unsigned int tran_call,
3837 char **pparams, int total_params,
3838 char **ppdata, int total_data,
3839 unsigned int max_data_bytes)
3841 char *params = *pparams;
3842 char *pdata = *ppdata;
3843 char *dstart, *dend;
3847 SMB_OFF_T file_size=0;
3848 uint64_t allocation_size=0;
3849 unsigned int data_size = 0;
3850 unsigned int param_size = 2;
3851 SMB_STRUCT_STAT sbuf;
3852 char *dos_fname = NULL;
3858 bool delete_pending = False;
3860 time_t create_time, mtime, atime;
3861 struct timespec create_time_ts, mtime_ts, atime_ts;
3862 struct timespec write_time_ts;
3863 files_struct *fsp = NULL;
3864 struct file_id fileid;
3865 struct ea_list *ea_list = NULL;
3866 char *lock_data = NULL;
3867 bool ms_dfs_link = false;
3868 TALLOC_CTX *ctx = talloc_tos();
3871 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3876 ZERO_STRUCT(write_time_ts);
3878 if (tran_call == TRANSACT2_QFILEINFO) {
3879 if (total_params < 4) {
3880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3885 call_trans2qpipeinfo(conn, req, tran_call,
3886 pparams, total_params,
3892 fsp = file_fsp(req, SVAL(params,0));
3893 info_level = SVAL(params,2);
3895 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3897 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3898 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3902 /* Initial check for valid fsp ptr. */
3903 if (!check_fsp_open(conn, req, fsp)) {
3907 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3909 reply_nterror(req, NT_STATUS_NO_MEMORY);
3913 if(fsp->fake_file_handle) {
3915 * This is actually for the QUOTA_FAKE_FILE --metze
3918 /* We know this name is ok, it's already passed the checks. */
3920 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3922 * This is actually a QFILEINFO on a directory
3923 * handle (returned from an NT SMB). NT5.0 seems
3924 * to do this call. JRA.
3927 if (INFO_LEVEL_IS_UNIX(info_level)) {
3928 /* Always do lstat for UNIX calls. */
3929 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3930 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3931 reply_unixerror(req,ERRDOS,ERRbadpath);
3934 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3935 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3936 reply_unixerror(req, ERRDOS, ERRbadpath);
3940 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3941 get_file_infos(fileid, &delete_pending, &write_time_ts);
3944 * Original code - this is an open file.
3946 if (!check_fsp(conn, req, fsp)) {
3950 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3951 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3952 reply_unixerror(req, ERRDOS, ERRbadfid);
3955 pos = fsp->fh->position_information;
3956 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3957 get_file_infos(fileid, &delete_pending, &write_time_ts);
3961 NTSTATUS status = NT_STATUS_OK;
3964 if (total_params < 7) {
3965 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3969 info_level = SVAL(params,0);
3971 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3973 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3974 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3978 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3980 STR_TERMINATE, &status);
3981 if (!NT_STATUS_IS_OK(status)) {
3982 reply_nterror(req, status);
3986 status = resolve_dfspath(ctx,
3988 req->flags2 & FLAGS2_DFS_PATHNAMES,
3991 if (!NT_STATUS_IS_OK(status)) {
3992 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3993 reply_botherror(req,
3994 NT_STATUS_PATH_NOT_COVERED,
3995 ERRSRV, ERRbadpath);
3997 reply_nterror(req, status);
4001 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
4002 if (!NT_STATUS_IS_OK(status)) {
4003 reply_nterror(req, status);
4006 status = check_name(conn, fname);
4007 if (!NT_STATUS_IS_OK(status)) {
4008 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
4009 reply_nterror(req, status);
4013 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4014 && is_ntfs_stream_name(fname)) {
4016 SMB_STRUCT_STAT bsbuf;
4018 status = split_ntfs_stream_name(talloc_tos(), fname,
4020 if (!NT_STATUS_IS_OK(status)) {
4021 DEBUG(10, ("create_file_unixpath: "
4022 "split_ntfs_stream_name failed: %s\n",
4023 nt_errstr(status)));
4024 reply_nterror(req, status);
4028 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4030 if (INFO_LEVEL_IS_UNIX(info_level)) {
4031 /* Always do lstat for UNIX calls. */
4032 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4033 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4034 reply_unixerror(req,ERRDOS,ERRbadpath);
4038 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4039 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4040 reply_unixerror(req,ERRDOS,ERRbadpath);
4045 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4046 get_file_infos(fileid, &delete_pending, NULL);
4047 if (delete_pending) {
4048 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4053 if (INFO_LEVEL_IS_UNIX(info_level)) {
4054 /* Always do lstat for UNIX calls. */
4055 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4056 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4057 reply_unixerror(req, ERRDOS, ERRbadpath);
4061 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4062 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4065 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4066 reply_unixerror(req, ERRDOS, ERRbadpath);
4071 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4072 get_file_infos(fileid, &delete_pending, &write_time_ts);
4073 if (delete_pending) {
4074 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4079 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4080 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4084 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4085 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4087 p = strrchr_m(fname,'/');
4094 mode = dos_mode_msdfs(conn,fname,&sbuf);
4096 mode = dos_mode(conn,fname,&sbuf);
4099 nlink = sbuf.st_ex_nlink;
4101 if (nlink && (mode&aDIR)) {
4105 if ((nlink > 0) && delete_pending) {
4109 fullpathname = fname;
4111 file_size = get_file_size_stat(&sbuf);
4113 /* Pull out any data sent here before we realloc. */
4114 switch (info_level) {
4115 case SMB_INFO_QUERY_EAS_FROM_LIST:
4117 /* Pull any EA list from the data portion. */
4120 if (total_data < 4) {
4122 req, NT_STATUS_INVALID_PARAMETER);
4125 ea_size = IVAL(pdata,0);
4127 if (total_data > 0 && ea_size != total_data) {
4128 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4129 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4131 req, NT_STATUS_INVALID_PARAMETER);
4135 if (!lp_ea_support(SNUM(conn))) {
4136 reply_doserror(req, ERRDOS,
4137 ERReasnotsupported);
4141 /* Pull out the list of names. */
4142 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4145 req, NT_STATUS_INVALID_PARAMETER);
4151 case SMB_QUERY_POSIX_LOCK:
4153 if (fsp == NULL || fsp->fh->fd == -1) {
4154 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4158 if (total_data != POSIX_LOCK_DATA_SIZE) {
4160 req, NT_STATUS_INVALID_PARAMETER);
4164 /* Copy the lock range data. */
4165 lock_data = (char *)TALLOC_MEMDUP(
4166 ctx, pdata, total_data);
4168 reply_nterror(req, NT_STATUS_NO_MEMORY);
4176 *pparams = (char *)SMB_REALLOC(*pparams,2);
4177 if (*pparams == NULL) {
4178 reply_nterror(req, NT_STATUS_NO_MEMORY);
4183 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4184 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4185 if (*ppdata == NULL ) {
4186 reply_nterror(req, NT_STATUS_NO_MEMORY);
4191 dend = dstart + data_size - 1;
4193 create_time_ts = sbuf.st_ex_btime;
4194 mtime_ts = sbuf.st_ex_mtime;
4195 atime_ts = sbuf.st_ex_atime;
4197 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
4200 /* Do we have this path open ? */
4202 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4203 fsp1 = file_find_di_first(fileid);
4204 if (fsp1 && fsp1->initial_allocation_size) {
4205 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, &sbuf);
4209 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4210 mtime_ts = write_time_ts;
4213 if (lp_dos_filetime_resolution(SNUM(conn))) {
4214 dos_filetime_timespec(&create_time_ts);
4215 dos_filetime_timespec(&mtime_ts);
4216 dos_filetime_timespec(&atime_ts);
4219 create_time = convert_timespec_to_time_t(create_time_ts);
4220 mtime = convert_timespec_to_time_t(mtime_ts);
4221 atime = convert_timespec_to_time_t(atime_ts);
4223 /* NT expects the name to be in an exact form of the *full*
4224 filename. See the trans2 torture test */
4225 if (ISDOT(base_name)) {
4226 dos_fname = talloc_strdup(ctx, "\\");
4228 reply_nterror(req, NT_STATUS_NO_MEMORY);
4232 dos_fname = talloc_asprintf(ctx,
4236 reply_nterror(req, NT_STATUS_NO_MEMORY);
4239 string_replace(dos_fname, '/', '\\');
4242 switch (info_level) {
4243 case SMB_INFO_STANDARD:
4244 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4246 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4247 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4248 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4249 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4250 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4251 SSVAL(pdata,l1_attrFile,mode);
4254 case SMB_INFO_QUERY_EA_SIZE:
4256 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4257 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4259 srv_put_dos_date2(pdata,0,create_time);
4260 srv_put_dos_date2(pdata,4,atime);
4261 srv_put_dos_date2(pdata,8,mtime); /* write time */
4262 SIVAL(pdata,12,(uint32)file_size);
4263 SIVAL(pdata,16,(uint32)allocation_size);
4264 SSVAL(pdata,20,mode);
4265 SIVAL(pdata,22,ea_size);
4269 case SMB_INFO_IS_NAME_VALID:
4270 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4271 if (tran_call == TRANSACT2_QFILEINFO) {
4272 /* os/2 needs this ? really ?*/
4273 reply_doserror(req, ERRDOS, ERRbadfunc);
4280 case SMB_INFO_QUERY_EAS_FROM_LIST:
4282 size_t total_ea_len = 0;
4283 struct ea_list *ea_file_list = NULL;
4285 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4287 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4288 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4290 if (!ea_list || (total_ea_len > data_size)) {
4292 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4296 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4300 case SMB_INFO_QUERY_ALL_EAS:
4302 /* We have data_size bytes to put EA's into. */
4303 size_t total_ea_len = 0;
4305 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4307 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4308 if (!ea_list || (total_ea_len > data_size)) {
4310 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4314 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4318 case SMB_FILE_BASIC_INFORMATION:
4319 case SMB_QUERY_FILE_BASIC_INFO:
4321 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4322 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4323 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4325 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4329 put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
4330 put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
4331 put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
4332 put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
4333 SIVAL(pdata,32,mode);
4335 DEBUG(5,("SMB_QFBI - "));
4336 DEBUG(5,("create: %s ", ctime(&create_time)));
4337 DEBUG(5,("access: %s ", ctime(&atime)));
4338 DEBUG(5,("write: %s ", ctime(&mtime)));
4339 DEBUG(5,("change: %s ", ctime(&mtime)));
4340 DEBUG(5,("mode: %x\n", mode));
4343 case SMB_FILE_STANDARD_INFORMATION:
4344 case SMB_QUERY_FILE_STANDARD_INFO:
4346 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4348 SOFF_T(pdata,0,allocation_size);
4349 SOFF_T(pdata,8,file_size);
4350 SIVAL(pdata,16,nlink);
4351 SCVAL(pdata,20,delete_pending?1:0);
4352 SCVAL(pdata,21,(mode&aDIR)?1:0);
4353 SSVAL(pdata,22,0); /* Padding. */
4356 case SMB_FILE_EA_INFORMATION:
4357 case SMB_QUERY_FILE_EA_INFO:
4359 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4360 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4362 SIVAL(pdata,0,ea_size);
4366 /* Get the 8.3 name - used if NT SMB was negotiated. */
4367 case SMB_QUERY_FILE_ALT_NAME_INFO:
4368 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4370 char mangled_name[13];
4371 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4372 if (!name_to_8_3(base_name,mangled_name,
4373 True,conn->params)) {
4376 NT_STATUS_NO_MEMORY);
4378 len = srvstr_push(dstart, req->flags2,
4379 pdata+4, mangled_name,
4380 PTR_DIFF(dend, pdata+4),
4382 data_size = 4 + len;
4387 case SMB_QUERY_FILE_NAME_INFO:
4389 this must be *exactly* right for ACLs on mapped drives to work
4391 len = srvstr_push(dstart, req->flags2,
4393 PTR_DIFF(dend, pdata+4),
4395 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4396 data_size = 4 + len;
4400 case SMB_FILE_ALLOCATION_INFORMATION:
4401 case SMB_QUERY_FILE_ALLOCATION_INFO:
4402 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4404 SOFF_T(pdata,0,allocation_size);
4407 case SMB_FILE_END_OF_FILE_INFORMATION:
4408 case SMB_QUERY_FILE_END_OF_FILEINFO:
4409 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4411 SOFF_T(pdata,0,file_size);
4414 case SMB_QUERY_FILE_ALL_INFO:
4415 case SMB_FILE_ALL_INFORMATION:
4417 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4418 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4419 put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
4420 put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
4421 put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
4422 put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
4423 SIVAL(pdata,32,mode);
4424 SIVAL(pdata,36,0); /* padding. */
4426 SOFF_T(pdata,0,allocation_size);
4427 SOFF_T(pdata,8,file_size);
4428 SIVAL(pdata,16,nlink);
4429 SCVAL(pdata,20,delete_pending);
4430 SCVAL(pdata,21,(mode&aDIR)?1:0);
4433 SIVAL(pdata,0,ea_size);
4434 pdata += 4; /* EA info */
4435 len = srvstr_push(dstart, req->flags2,
4437 PTR_DIFF(dend, pdata+4),
4441 data_size = PTR_DIFF(pdata,(*ppdata));
4444 case SMB_FILE_INTERNAL_INFORMATION:
4445 /* This should be an index number - looks like
4448 I think this causes us to fail the IFSKIT
4449 BasicFileInformationTest. -tpot */
4451 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4452 SIVAL(pdata,0,sbuf.st_ex_ino); /* FileIndexLow */
4453 SIVAL(pdata,4,sbuf.st_ex_dev); /* FileIndexHigh */
4457 case SMB_FILE_ACCESS_INFORMATION:
4458 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4460 SIVAL(pdata,0,fsp->access_mask);
4462 /* GENERIC_EXECUTE mapping from Windows */
4463 SIVAL(pdata,0,0x12019F);
4468 case SMB_FILE_NAME_INFORMATION:
4469 /* Pathname with leading '\'. */
4472 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4473 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4474 SIVAL(pdata,0,byte_len);
4475 data_size = 4 + byte_len;
4479 case SMB_FILE_DISPOSITION_INFORMATION:
4480 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4482 SCVAL(pdata,0,delete_pending);
4485 case SMB_FILE_POSITION_INFORMATION:
4486 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4488 SOFF_T(pdata,0,pos);
4491 case SMB_FILE_MODE_INFORMATION:
4492 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4493 SIVAL(pdata,0,mode);
4497 case SMB_FILE_ALIGNMENT_INFORMATION:
4498 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4499 SIVAL(pdata,0,0); /* No alignment needed. */
4504 * NT4 server just returns "invalid query" to this - if we try
4505 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4508 /* The first statement above is false - verified using Thursby
4509 * client against NT4 -- gcolley.
4511 case SMB_QUERY_FILE_STREAM_INFO:
4512 case SMB_FILE_STREAM_INFORMATION: {
4513 unsigned int num_streams;
4514 struct stream_struct *streams;
4517 DEBUG(10,("call_trans2qfilepathinfo: "
4518 "SMB_FILE_STREAM_INFORMATION\n"));
4520 status = SMB_VFS_STREAMINFO(
4521 conn, fsp, fname, talloc_tos(),
4522 &num_streams, &streams);
4524 if (!NT_STATUS_IS_OK(status)) {
4525 DEBUG(10, ("could not get stream info: %s\n",
4526 nt_errstr(status)));
4527 reply_nterror(req, status);
4531 status = marshall_stream_info(num_streams, streams,
4532 pdata, max_data_bytes,
4535 if (!NT_STATUS_IS_OK(status)) {
4536 DEBUG(10, ("marshall_stream_info failed: %s\n",
4537 nt_errstr(status)));
4538 reply_nterror(req, status);
4542 TALLOC_FREE(streams);
4546 case SMB_QUERY_COMPRESSION_INFO:
4547 case SMB_FILE_COMPRESSION_INFORMATION:
4548 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4549 SOFF_T(pdata,0,file_size);
4550 SIVAL(pdata,8,0); /* ??? */
4551 SIVAL(pdata,12,0); /* ??? */
4555 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4556 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4557 put_long_date_timespec(conn->ts_res, pdata,create_time_ts);
4558 put_long_date_timespec(conn->ts_res, pdata+8,atime_ts);
4559 put_long_date_timespec(conn->ts_res, pdata+16,mtime_ts); /* write time */
4560 put_long_date_timespec(conn->ts_res, pdata+24,mtime_ts); /* change time */
4561 SOFF_T(pdata,32,allocation_size);
4562 SOFF_T(pdata,40,file_size);
4563 SIVAL(pdata,48,mode);
4564 SIVAL(pdata,52,0); /* ??? */
4568 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4569 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4570 SIVAL(pdata,0,mode);
4576 * CIFS UNIX Extensions.
4579 case SMB_QUERY_FILE_UNIX_BASIC:
4581 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4582 data_size = PTR_DIFF(pdata,(*ppdata));
4586 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4588 for (i=0; i<100; i++)
4589 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4595 case SMB_QUERY_FILE_UNIX_INFO2:
4597 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4598 data_size = PTR_DIFF(pdata,(*ppdata));
4602 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4604 for (i=0; i<100; i++)
4605 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4611 case SMB_QUERY_FILE_UNIX_LINK:
4613 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4616 reply_nterror(req, NT_STATUS_NO_MEMORY);
4620 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4622 if(!S_ISLNK(sbuf.st_ex_mode)) {
4623 reply_unixerror(req, ERRSRV,
4628 reply_unixerror(req, ERRDOS, ERRbadlink);
4631 len = SMB_VFS_READLINK(conn,fullpathname,
4634 reply_unixerror(req, ERRDOS,
4639 len = srvstr_push(dstart, req->flags2,
4641 PTR_DIFF(dend, pdata),
4644 data_size = PTR_DIFF(pdata,(*ppdata));
4649 #if defined(HAVE_POSIX_ACLS)
4650 case SMB_QUERY_POSIX_ACL:
4652 SMB_ACL_T file_acl = NULL;
4653 SMB_ACL_T def_acl = NULL;
4654 uint16 num_file_acls = 0;
4655 uint16 num_def_acls = 0;
4657 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4658 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4660 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4663 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4664 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4668 NT_STATUS_NOT_IMPLEMENTED);
4672 if (S_ISDIR(sbuf.st_ex_mode)) {
4673 if (fsp && fsp->is_directory) {
4674 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4676 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4678 def_acl = free_empty_sys_acl(conn, def_acl);
4681 num_file_acls = count_acl_entries(conn, file_acl);
4682 num_def_acls = count_acl_entries(conn, def_acl);
4684 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4685 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4687 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4688 SMB_POSIX_ACL_HEADER_SIZE) ));
4690 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4693 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4697 NT_STATUS_BUFFER_TOO_SMALL);
4701 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4702 SSVAL(pdata,2,num_file_acls);
4703 SSVAL(pdata,4,num_def_acls);
4704 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4706 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4709 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4712 req, NT_STATUS_INTERNAL_ERROR);
4715 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4717 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4720 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4724 NT_STATUS_INTERNAL_ERROR);
4729 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4732 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4734 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4740 case SMB_QUERY_POSIX_LOCK:
4742 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4746 enum brl_type lock_type;
4748 if (total_data != POSIX_LOCK_DATA_SIZE) {
4750 req, NT_STATUS_INVALID_PARAMETER);
4754 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4755 case POSIX_LOCK_TYPE_READ:
4756 lock_type = READ_LOCK;
4758 case POSIX_LOCK_TYPE_WRITE:
4759 lock_type = WRITE_LOCK;
4761 case POSIX_LOCK_TYPE_UNLOCK:
4763 /* There's no point in asking for an unlock... */
4766 NT_STATUS_INVALID_PARAMETER);
4770 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4771 #if defined(HAVE_LONGLONG)
4772 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4773 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4774 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4775 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4776 #else /* HAVE_LONGLONG */
4777 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4778 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4779 #endif /* HAVE_LONGLONG */
4781 status = query_lock(fsp,
4788 if (ERROR_WAS_LOCK_DENIED(status)) {
4789 /* Here we need to report who has it locked... */
4790 data_size = POSIX_LOCK_DATA_SIZE;
4792 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4793 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4794 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4795 #if defined(HAVE_LONGLONG)
4796 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4797 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4798 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4799 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4800 #else /* HAVE_LONGLONG */
4801 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4802 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4803 #endif /* HAVE_LONGLONG */
4805 } else if (NT_STATUS_IS_OK(status)) {
4806 /* For success we just return a copy of what we sent
4807 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4808 data_size = POSIX_LOCK_DATA_SIZE;
4809 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4810 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4812 reply_nterror(req, status);
4819 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4823 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4829 /****************************************************************************
4830 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4832 ****************************************************************************/
4834 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4835 connection_struct *conn,
4836 const char *oldname_in,
4837 const char *newname_in)
4839 SMB_STRUCT_STAT sbuf1, sbuf2;
4840 char *last_component_oldname = NULL;
4841 char *last_component_newname = NULL;
4842 char *oldname = NULL;
4843 char *newname = NULL;
4844 NTSTATUS status = NT_STATUS_OK;
4849 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4850 &last_component_oldname, &sbuf1);
4851 if (!NT_STATUS_IS_OK(status)) {
4855 status = check_name(conn, oldname);
4856 if (!NT_STATUS_IS_OK(status)) {
4860 /* source must already exist. */
4861 if (!VALID_STAT(sbuf1)) {
4862 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4865 status = unix_convert(ctx, conn, newname_in, False, &newname,
4866 &last_component_newname, &sbuf2);
4867 if (!NT_STATUS_IS_OK(status)) {
4871 status = check_name(conn, newname);
4872 if (!NT_STATUS_IS_OK(status)) {
4876 /* Disallow if newname already exists. */
4877 if (VALID_STAT(sbuf2)) {
4878 return NT_STATUS_OBJECT_NAME_COLLISION;
4881 /* No links from a directory. */
4882 if (S_ISDIR(sbuf1.st_ex_mode)) {
4883 return NT_STATUS_FILE_IS_A_DIRECTORY;
4886 /* Ensure this is within the share. */
4887 status = check_reduced_name(conn, oldname);
4888 if (!NT_STATUS_IS_OK(status)) {
4892 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4894 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4895 status = map_nt_error_from_unix(errno);
4896 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4897 nt_errstr(status), newname, oldname));
4903 /****************************************************************************
4904 Deal with setting the time from any of the setfilepathinfo functions.
4905 ****************************************************************************/
4907 NTSTATUS smb_set_file_time(connection_struct *conn,
4910 const SMB_STRUCT_STAT *psbuf,
4911 struct smb_file_time *ft,
4912 bool setting_write_time)
4914 struct smb_file_time ft_stat;
4916 FILE_NOTIFY_CHANGE_LAST_ACCESS
4917 |FILE_NOTIFY_CHANGE_LAST_WRITE
4918 |FILE_NOTIFY_CHANGE_CREATION;
4920 if (!VALID_STAT(*psbuf)) {
4921 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4924 /* get some defaults (no modifications) if any info is zero or -1. */
4925 if (null_timespec(ft->create_time)) {
4926 ft->create_time = psbuf->st_ex_btime;
4927 action &= ~FILE_NOTIFY_CHANGE_CREATION;
4930 if (null_timespec(ft->atime)) {
4931 ft->atime= psbuf->st_ex_atime;
4932 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4935 if (null_timespec(ft->mtime)) {
4936 ft->mtime = psbuf->st_ex_mtime;
4937 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4940 if (!setting_write_time) {
4941 /* ft->mtime comes from change time, not write time. */
4942 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4945 /* Ensure the resolution is the correct for
4946 * what we can store on this filesystem. */
4948 round_timespec(conn->ts_res, &ft->create_time);
4949 round_timespec(conn->ts_res, &ft->atime);
4950 round_timespec(conn->ts_res, &ft->mtime);
4952 DEBUG(5,("smb_set_filetime: actime: %s\n ",
4953 time_to_asc(convert_timespec_to_time_t(ft->atime))));
4954 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
4955 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4956 if (!null_timespec(ft->create_time)) {
4957 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
4958 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
4962 * Try and set the times of this file if
4963 * they are different from the current values.
4967 struct timespec mts = psbuf->st_ex_mtime;
4968 struct timespec ats = psbuf->st_ex_atime;
4969 if ((timespec_compare(&ft->atime, &ats) == 0) &&
4970 (timespec_compare(&ft->mtime, &mts) == 0)) {
4971 return NT_STATUS_OK;
4975 if (setting_write_time) {
4977 * This was a Windows setfileinfo on an open file.
4978 * NT does this a lot. We also need to
4979 * set the time here, as it can be read by
4980 * FindFirst/FindNext and with the patch for bug #2045
4981 * in smbd/fileio.c it ensures that this timestamp is
4982 * kept sticky even after a write. We save the request
4983 * away and will set it on file close and after a write. JRA.
4986 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4987 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
4990 if (fsp->base_fsp) {
4991 set_sticky_write_time_fsp(fsp->base_fsp,
4994 set_sticky_write_time_fsp(fsp, ft->mtime);
4997 set_sticky_write_time_path(conn, fname,
4998 vfs_file_id_from_sbuf(conn, psbuf),
5003 ft_stat.create_time = psbuf->st_ex_btime;
5004 ft_stat.atime = psbuf->st_ex_atime;
5005 ft_stat.mtime = psbuf->st_ex_mtime;
5007 round_timespec(conn->ts_res, &ft_stat.create_time);
5008 round_timespec(conn->ts_res, &ft_stat.atime);
5009 round_timespec(conn->ts_res, &ft_stat.mtime);
5011 if (fsp && fsp->base_fsp) {
5012 fname = fsp->base_fsp->fsp_name;
5015 if (timespec_compare(&ft_stat.create_time, &ft->create_time) ||
5016 timespec_compare(&ft_stat.atime, &ft->atime) ||
5017 timespec_compare(&ft_stat.mtime, &ft->mtime)) {
5018 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5019 if(file_ntimes(conn, fname, ft)!=0) {
5020 return map_nt_error_from_unix(errno);
5023 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
5025 return NT_STATUS_OK;
5028 /****************************************************************************
5029 Deal with setting the dosmode from any of the setfilepathinfo functions.
5030 ****************************************************************************/
5032 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5035 SMB_STRUCT_STAT *psbuf,
5038 if (!VALID_STAT(*psbuf)) {
5039 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5043 if (fsp->base_fsp) {
5044 fname = fsp->base_fsp->fsp_name;
5046 fname = fsp->fsp_name;
5051 if (S_ISDIR(psbuf->st_ex_mode)) {
5058 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5060 /* check the mode isn't different, before changing it */
5061 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5063 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5064 fname, (unsigned int)dosmode ));
5066 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5067 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5068 fname, strerror(errno)));
5069 return map_nt_error_from_unix(errno);
5072 return NT_STATUS_OK;
5075 /****************************************************************************
5076 Deal with setting the size from any of the setfilepathinfo functions.
5077 ****************************************************************************/
5079 static NTSTATUS smb_set_file_size(connection_struct *conn,
5080 struct smb_request *req,
5083 SMB_STRUCT_STAT *psbuf,
5086 NTSTATUS status = NT_STATUS_OK;
5087 files_struct *new_fsp = NULL;
5089 if (!VALID_STAT(*psbuf)) {
5090 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5093 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5095 if (size == get_file_size_stat(psbuf)) {
5096 return NT_STATUS_OK;
5099 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5100 fname, (double)size ));
5102 if (fsp && fsp->fh->fd != -1) {
5103 /* Handle based call. */
5104 if (vfs_set_filelen(fsp, size) == -1) {
5105 return map_nt_error_from_unix(errno);
5107 trigger_write_time_update_immediate(fsp);
5108 return NT_STATUS_OK;
5111 status = SMB_VFS_CREATE_FILE(
5114 0, /* root_dir_fid */
5116 0, /* create_file_flags */
5117 FILE_WRITE_ATTRIBUTES, /* access_mask */
5118 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5120 FILE_OPEN, /* create_disposition*/
5121 0, /* create_options */
5122 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5123 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5124 0, /* allocation_size */
5127 &new_fsp, /* result */
5131 if (!NT_STATUS_IS_OK(status)) {
5132 /* NB. We check for open_was_deferred in the caller. */
5136 if (vfs_set_filelen(new_fsp, size) == -1) {
5137 status = map_nt_error_from_unix(errno);
5138 close_file(req, new_fsp,NORMAL_CLOSE);
5142 trigger_write_time_update_immediate(new_fsp);
5143 close_file(req, new_fsp,NORMAL_CLOSE);
5144 return NT_STATUS_OK;
5147 /****************************************************************************
5148 Deal with SMB_INFO_SET_EA.
5149 ****************************************************************************/
5151 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5157 struct ea_list *ea_list = NULL;
5158 TALLOC_CTX *ctx = NULL;
5159 NTSTATUS status = NT_STATUS_OK;
5161 if (total_data < 10) {
5163 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5164 length. They seem to have no effect. Bug #3212. JRA */
5166 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5167 /* We're done. We only get EA info in this call. */
5168 return NT_STATUS_OK;
5171 return NT_STATUS_INVALID_PARAMETER;
5174 if (IVAL(pdata,0) > total_data) {
5175 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5176 IVAL(pdata,0), (unsigned int)total_data));
5177 return NT_STATUS_INVALID_PARAMETER;
5181 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5183 return NT_STATUS_INVALID_PARAMETER;
5185 status = set_ea(conn, fsp, fname, ea_list);
5190 /****************************************************************************
5191 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5192 ****************************************************************************/
5194 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5199 SMB_STRUCT_STAT *psbuf)
5201 NTSTATUS status = NT_STATUS_OK;
5202 bool delete_on_close;
5205 if (total_data < 1) {
5206 return NT_STATUS_INVALID_PARAMETER;
5210 return NT_STATUS_INVALID_HANDLE;
5213 delete_on_close = (CVAL(pdata,0) ? True : False);
5214 dosmode = dos_mode(conn, fname, psbuf);
5216 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5217 "delete_on_close = %u\n",
5219 (unsigned int)dosmode,
5220 (unsigned int)delete_on_close ));
5222 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5224 if (!NT_STATUS_IS_OK(status)) {
5228 /* The set is across all open files on this dev/inode pair. */
5229 if (!set_delete_on_close(fsp, delete_on_close,
5230 &conn->server_info->utok)) {
5231 return NT_STATUS_ACCESS_DENIED;
5233 return NT_STATUS_OK;
5236 /****************************************************************************
5237 Deal with SMB_FILE_POSITION_INFORMATION.
5238 ****************************************************************************/
5240 static NTSTATUS smb_file_position_information(connection_struct *conn,
5245 uint64_t position_information;
5247 if (total_data < 8) {
5248 return NT_STATUS_INVALID_PARAMETER;
5252 /* Ignore on pathname based set. */
5253 return NT_STATUS_OK;
5256 position_information = (uint64_t)IVAL(pdata,0);
5257 #ifdef LARGE_SMB_OFF_T
5258 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5259 #else /* LARGE_SMB_OFF_T */
5260 if (IVAL(pdata,4) != 0) {
5261 /* more than 32 bits? */
5262 return NT_STATUS_INVALID_PARAMETER;
5264 #endif /* LARGE_SMB_OFF_T */
5266 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5267 fsp->fsp_name, (double)position_information ));
5268 fsp->fh->position_information = position_information;
5269 return NT_STATUS_OK;
5272 /****************************************************************************
5273 Deal with SMB_FILE_MODE_INFORMATION.
5274 ****************************************************************************/
5276 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5282 if (total_data < 4) {
5283 return NT_STATUS_INVALID_PARAMETER;
5285 mode = IVAL(pdata,0);
5286 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5287 return NT_STATUS_INVALID_PARAMETER;
5289 return NT_STATUS_OK;
5292 /****************************************************************************
5293 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5294 ****************************************************************************/
5296 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5297 struct smb_request *req,
5302 char *link_target = NULL;
5303 const char *newname = fname;
5304 TALLOC_CTX *ctx = talloc_tos();
5306 /* Set a symbolic link. */
5307 /* Don't allow this if follow links is false. */
5309 if (total_data == 0) {
5310 return NT_STATUS_INVALID_PARAMETER;
5313 if (!lp_symlinks(SNUM(conn))) {
5314 return NT_STATUS_ACCESS_DENIED;
5317 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5318 total_data, STR_TERMINATE);
5321 return NT_STATUS_INVALID_PARAMETER;
5324 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5325 newname, link_target ));
5327 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5328 return map_nt_error_from_unix(errno);
5331 return NT_STATUS_OK;
5334 /****************************************************************************
5335 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5336 ****************************************************************************/
5338 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5339 struct smb_request *req,
5340 const char *pdata, int total_data,
5343 char *oldname = NULL;
5344 TALLOC_CTX *ctx = talloc_tos();
5345 NTSTATUS status = NT_STATUS_OK;
5347 /* Set a hard link. */
5348 if (total_data == 0) {
5349 return NT_STATUS_INVALID_PARAMETER;
5352 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5353 total_data, STR_TERMINATE, &status);
5354 if (!NT_STATUS_IS_OK(status)) {
5358 status = resolve_dfspath(ctx, conn,
5359 req->flags2 & FLAGS2_DFS_PATHNAMES,
5362 if (!NT_STATUS_IS_OK(status)) {
5366 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5369 return hardlink_internals(ctx, conn, oldname, fname);
5372 /****************************************************************************
5373 Deal with SMB_FILE_RENAME_INFORMATION.
5374 ****************************************************************************/
5376 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5377 struct smb_request *req,
5386 char *newname = NULL;
5387 char *base_name = NULL;
5388 bool dest_has_wcard = False;
5389 SMB_STRUCT_STAT sbuf;
5390 char *newname_last_component = NULL;
5391 NTSTATUS status = NT_STATUS_OK;
5393 TALLOC_CTX *ctx = talloc_tos();
5395 if (total_data < 13) {
5396 return NT_STATUS_INVALID_PARAMETER;
5401 overwrite = (CVAL(pdata,0) ? True : False);
5402 root_fid = IVAL(pdata,4);
5403 len = IVAL(pdata,8);
5405 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5406 return NT_STATUS_INVALID_PARAMETER;
5409 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5412 if (!NT_STATUS_IS_OK(status)) {
5416 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5419 status = resolve_dfspath_wcard(ctx, conn,
5420 req->flags2 & FLAGS2_DFS_PATHNAMES,
5424 if (!NT_STATUS_IS_OK(status)) {
5428 /* Check the new name has no '/' characters. */
5429 if (strchr_m(newname, '/')) {
5430 return NT_STATUS_NOT_SUPPORTED;
5433 if (fsp && fsp->base_fsp) {
5434 /* newname must be a stream name. */
5435 if (newname[0] != ':') {
5436 return NT_STATUS_NOT_SUPPORTED;
5438 base_name = talloc_asprintf(ctx, "%s%s",
5439 fsp->base_fsp->fsp_name,
5442 return NT_STATUS_NO_MEMORY;
5445 /* newname must *not* be a stream name. */
5446 if (is_ntfs_stream_name(newname)) {
5447 return NT_STATUS_NOT_SUPPORTED;
5450 /* Create the base directory. */
5451 base_name = talloc_strdup(ctx, fname);
5453 return NT_STATUS_NO_MEMORY;
5455 p = strrchr_m(base_name, '/');
5459 base_name = talloc_strdup(ctx, "./");
5461 return NT_STATUS_NO_MEMORY;
5464 /* Append the new name. */
5465 base_name = talloc_asprintf_append(base_name,
5469 return NT_STATUS_NO_MEMORY;
5472 status = unix_convert(ctx, conn, newname, False,
5474 &newname_last_component,
5477 /* If an error we expect this to be
5478 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5480 if (!NT_STATUS_IS_OK(status)
5481 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5488 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5489 fsp->fnum, fsp->fsp_name, base_name ));
5490 status = rename_internals_fsp(conn, fsp, base_name,
5491 newname_last_component, 0,
5494 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5495 fname, base_name ));
5496 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5497 overwrite, False, dest_has_wcard,
5498 FILE_WRITE_ATTRIBUTES);
5504 /****************************************************************************
5505 Deal with SMB_SET_POSIX_ACL.
5506 ****************************************************************************/
5508 #if defined(HAVE_POSIX_ACLS)
5509 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5514 SMB_STRUCT_STAT *psbuf)
5516 uint16 posix_acl_version;
5517 uint16 num_file_acls;
5518 uint16 num_def_acls;
5519 bool valid_file_acls = True;
5520 bool valid_def_acls = True;
5522 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5523 return NT_STATUS_INVALID_PARAMETER;
5525 posix_acl_version = SVAL(pdata,0);
5526 num_file_acls = SVAL(pdata,2);
5527 num_def_acls = SVAL(pdata,4);
5529 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5530 valid_file_acls = False;
5534 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5535 valid_def_acls = False;
5539 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5540 return NT_STATUS_INVALID_PARAMETER;
5543 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5544 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5545 return NT_STATUS_INVALID_PARAMETER;
5548 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5549 fname ? fname : fsp->fsp_name,
5550 (unsigned int)num_file_acls,
5551 (unsigned int)num_def_acls));
5553 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5554 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5555 return map_nt_error_from_unix(errno);
5558 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5559 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5560 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5561 return map_nt_error_from_unix(errno);
5563 return NT_STATUS_OK;
5567 /****************************************************************************
5568 Deal with SMB_SET_POSIX_LOCK.
5569 ****************************************************************************/
5571 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5572 struct smb_request *req,
5580 bool blocking_lock = False;
5581 enum brl_type lock_type;
5583 NTSTATUS status = NT_STATUS_OK;
5585 if (fsp == NULL || fsp->fh->fd == -1) {
5586 return NT_STATUS_INVALID_HANDLE;
5589 if (total_data != POSIX_LOCK_DATA_SIZE) {
5590 return NT_STATUS_INVALID_PARAMETER;
5593 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5594 case POSIX_LOCK_TYPE_READ:
5595 lock_type = READ_LOCK;
5597 case POSIX_LOCK_TYPE_WRITE:
5598 /* Return the right POSIX-mappable error code for files opened read-only. */
5599 if (!fsp->can_write) {
5600 return NT_STATUS_INVALID_HANDLE;
5602 lock_type = WRITE_LOCK;
5604 case POSIX_LOCK_TYPE_UNLOCK:
5605 lock_type = UNLOCK_LOCK;
5608 return NT_STATUS_INVALID_PARAMETER;
5611 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5612 blocking_lock = False;
5613 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5614 blocking_lock = True;
5616 return NT_STATUS_INVALID_PARAMETER;
5619 if (!lp_blocking_locks(SNUM(conn))) {
5620 blocking_lock = False;
5623 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5624 #if defined(HAVE_LONGLONG)
5625 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5626 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5627 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5628 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5629 #else /* HAVE_LONGLONG */
5630 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5631 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5632 #endif /* HAVE_LONGLONG */
5634 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5635 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5637 (unsigned int)lock_type,
5638 (unsigned int)lock_pid,
5642 if (lock_type == UNLOCK_LOCK) {
5643 status = do_unlock(smbd_messaging_context(),
5650 uint32 block_smbpid;
5652 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5664 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5666 * A blocking lock was requested. Package up
5667 * this smb into a queued request and push it
5668 * onto the blocking lock queue.
5670 if(push_blocking_lock_request(br_lck,
5673 -1, /* infinite timeout. */
5681 TALLOC_FREE(br_lck);
5685 TALLOC_FREE(br_lck);
5691 /****************************************************************************
5692 Deal with SMB_INFO_STANDARD.
5693 ****************************************************************************/
5695 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5700 const SMB_STRUCT_STAT *psbuf)
5702 struct smb_file_time ft;
5705 if (total_data < 12) {
5706 return NT_STATUS_INVALID_PARAMETER;
5710 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
5713 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
5716 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
5718 DEBUG(10,("smb_set_info_standard: file %s\n",
5719 fname ? fname : fsp->fsp_name ));
5721 return smb_set_file_time(conn,
5729 /****************************************************************************
5730 Deal with SMB_SET_FILE_BASIC_INFO.
5731 ****************************************************************************/
5733 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5738 SMB_STRUCT_STAT *psbuf)
5740 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5741 struct timespec write_time;
5742 struct timespec changed_time;
5743 struct smb_file_time ft;
5745 NTSTATUS status = NT_STATUS_OK;
5746 bool setting_write_time = true;
5750 if (total_data < 36) {
5751 return NT_STATUS_INVALID_PARAMETER;
5754 /* Set the attributes */
5755 dosmode = IVAL(pdata,32);
5756 status = smb_set_file_dosmode(conn, fsp, fname, psbuf, dosmode);
5757 if (!NT_STATUS_IS_OK(status)) {
5762 ft.atime = interpret_long_date(pdata+8);
5764 write_time = interpret_long_date(pdata+16);
5765 changed_time = interpret_long_date(pdata+24);
5768 ft.mtime = timespec_min(&write_time, &changed_time);
5771 ft.create_time = interpret_long_date(pdata);
5773 if ((timespec_compare(&write_time, &ft.mtime) == 1) &&
5774 !null_timespec(write_time)) {
5775 ft.mtime = write_time;
5778 /* Prefer a defined time to an undefined one. */
5779 if (null_timespec(ft.mtime)) {
5780 if (null_timespec(write_time)) {
5781 ft.mtime = changed_time;
5782 setting_write_time = false;
5784 ft.mtime = write_time;
5788 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5789 fname ? fname : fsp->fsp_name ));
5791 return smb_set_file_time(conn,
5796 setting_write_time);
5799 /****************************************************************************
5800 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5801 ****************************************************************************/
5803 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5804 struct smb_request *req,
5809 SMB_STRUCT_STAT *psbuf)
5811 uint64_t allocation_size = 0;
5812 NTSTATUS status = NT_STATUS_OK;
5813 files_struct *new_fsp = NULL;
5815 if (!VALID_STAT(*psbuf)) {
5816 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5819 if (total_data < 8) {
5820 return NT_STATUS_INVALID_PARAMETER;
5823 allocation_size = (uint64_t)IVAL(pdata,0);
5824 #ifdef LARGE_SMB_OFF_T
5825 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5826 #else /* LARGE_SMB_OFF_T */
5827 if (IVAL(pdata,4) != 0) {
5828 /* more than 32 bits? */
5829 return NT_STATUS_INVALID_PARAMETER;
5831 #endif /* LARGE_SMB_OFF_T */
5833 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5834 fname, (double)allocation_size ));
5836 if (allocation_size) {
5837 allocation_size = smb_roundup(conn, allocation_size);
5840 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5841 fname, (double)allocation_size ));
5843 if (fsp && fsp->fh->fd != -1) {
5844 /* Open file handle. */
5845 /* Only change if needed. */
5846 if (allocation_size != get_file_size_stat(psbuf)) {
5847 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5848 return map_nt_error_from_unix(errno);
5851 /* But always update the time. */
5853 * This is equivalent to a write. Ensure it's seen immediately
5854 * if there are no pending writes.
5856 trigger_write_time_update_immediate(fsp);
5857 return NT_STATUS_OK;
5860 /* Pathname or stat or directory file. */
5862 status = SMB_VFS_CREATE_FILE(
5865 0, /* root_dir_fid */
5867 0, /* create_file_flags */
5868 FILE_WRITE_DATA, /* access_mask */
5869 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5871 FILE_OPEN, /* create_disposition*/
5872 0, /* create_options */
5873 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5874 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5875 0, /* allocation_size */
5878 &new_fsp, /* result */
5882 if (!NT_STATUS_IS_OK(status)) {
5883 /* NB. We check for open_was_deferred in the caller. */
5887 /* Only change if needed. */
5888 if (allocation_size != get_file_size_stat(psbuf)) {
5889 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5890 status = map_nt_error_from_unix(errno);
5891 close_file(req, new_fsp, NORMAL_CLOSE);
5896 /* Changing the allocation size should set the last mod time. */
5898 * This is equivalent to a write. Ensure it's seen immediately
5899 * if there are no pending writes.
5901 trigger_write_time_update_immediate(new_fsp);
5903 close_file(req, new_fsp, NORMAL_CLOSE);
5904 return NT_STATUS_OK;
5907 /****************************************************************************
5908 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5909 ****************************************************************************/
5911 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5912 struct smb_request *req,
5917 SMB_STRUCT_STAT *psbuf)
5921 if (total_data < 8) {
5922 return NT_STATUS_INVALID_PARAMETER;
5925 size = IVAL(pdata,0);
5926 #ifdef LARGE_SMB_OFF_T
5927 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5928 #else /* LARGE_SMB_OFF_T */
5929 if (IVAL(pdata,4) != 0) {
5930 /* more than 32 bits? */
5931 return NT_STATUS_INVALID_PARAMETER;
5933 #endif /* LARGE_SMB_OFF_T */
5934 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5935 "file %s to %.0f\n", fname, (double)size ));
5937 return smb_set_file_size(conn, req,
5944 /****************************************************************************
5945 Allow a UNIX info mknod.
5946 ****************************************************************************/
5948 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5952 SMB_STRUCT_STAT *psbuf)
5954 uint32 file_type = IVAL(pdata,56);
5955 #if defined(HAVE_MAKEDEV)
5956 uint32 dev_major = IVAL(pdata,60);
5957 uint32 dev_minor = IVAL(pdata,68);
5959 SMB_DEV_T dev = (SMB_DEV_T)0;
5960 uint32 raw_unixmode = IVAL(pdata,84);
5964 if (total_data < 100) {
5965 return NT_STATUS_INVALID_PARAMETER;
5968 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5969 if (!NT_STATUS_IS_OK(status)) {
5973 #if defined(HAVE_MAKEDEV)
5974 dev = makedev(dev_major, dev_minor);
5977 switch (file_type) {
5978 #if defined(S_IFIFO)
5979 case UNIX_TYPE_FIFO:
5980 unixmode |= S_IFIFO;
5983 #if defined(S_IFSOCK)
5984 case UNIX_TYPE_SOCKET:
5985 unixmode |= S_IFSOCK;
5988 #if defined(S_IFCHR)
5989 case UNIX_TYPE_CHARDEV:
5990 unixmode |= S_IFCHR;
5993 #if defined(S_IFBLK)
5994 case UNIX_TYPE_BLKDEV:
5995 unixmode |= S_IFBLK;
5999 return NT_STATUS_INVALID_PARAMETER;
6002 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
6003 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
6005 /* Ok - do the mknod. */
6006 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
6007 return map_nt_error_from_unix(errno);
6010 /* If any of the other "set" calls fail we
6011 * don't want to end up with a half-constructed mknod.
6014 if (lp_inherit_perms(SNUM(conn))) {
6016 if (!parent_dirname(talloc_tos(), fname, &parent, NULL)) {
6017 return NT_STATUS_NO_MEMORY;
6019 inherit_access_posix_acl(conn, parent, fname, unixmode);
6020 TALLOC_FREE(parent);
6023 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
6024 status = map_nt_error_from_unix(errno);
6025 SMB_VFS_UNLINK(conn,fname);
6028 return NT_STATUS_OK;
6031 /****************************************************************************
6032 Deal with SMB_SET_FILE_UNIX_BASIC.
6033 ****************************************************************************/
6035 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6036 struct smb_request *req,
6041 SMB_STRUCT_STAT *psbuf)
6043 struct smb_file_time ft;
6044 uint32 raw_unixmode;
6047 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6048 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6049 NTSTATUS status = NT_STATUS_OK;
6050 bool delete_on_fail = False;
6051 enum perm_type ptype;
6052 files_struct *all_fsps = NULL;
6053 bool modify_mtime = true;
6058 if (total_data < 100) {
6059 return NT_STATUS_INVALID_PARAMETER;
6062 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6063 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6064 size=IVAL(pdata,0); /* first 8 Bytes are size */
6065 #ifdef LARGE_SMB_OFF_T
6066 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6067 #else /* LARGE_SMB_OFF_T */
6068 if (IVAL(pdata,4) != 0) {
6069 /* more than 32 bits? */
6070 return NT_STATUS_INVALID_PARAMETER;
6072 #endif /* LARGE_SMB_OFF_T */
6075 ft.atime = interpret_long_date(pdata+24); /* access_time */
6076 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6077 set_owner = (uid_t)IVAL(pdata,40);
6078 set_grp = (gid_t)IVAL(pdata,48);
6079 raw_unixmode = IVAL(pdata,84);
6081 if (VALID_STAT(*psbuf)) {
6082 if (S_ISDIR(psbuf->st_ex_mode)) {
6083 ptype = PERM_EXISTING_DIR;
6085 ptype = PERM_EXISTING_FILE;
6088 ptype = PERM_NEW_FILE;
6091 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6092 if (!NT_STATUS_IS_OK(status)) {
6096 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6097 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6098 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6100 if (!VALID_STAT(*psbuf)) {
6102 * The only valid use of this is to create character and block
6103 * devices, and named pipes. This is deprecated (IMHO) and
6104 * a new info level should be used for mknod. JRA.
6107 status = smb_unix_mknod(conn,
6112 if (!NT_STATUS_IS_OK(status)) {
6116 /* Ensure we don't try and change anything else. */
6117 raw_unixmode = SMB_MODE_NO_CHANGE;
6118 size = get_file_size_stat(psbuf);
6119 ft.atime = psbuf->st_ex_atime;
6120 ft.mtime = psbuf->st_ex_mtime;
6122 * We continue here as we might want to change the
6125 delete_on_fail = True;
6129 /* Horrible backwards compatibility hack as an old server bug
6130 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6134 size = get_file_size_stat(psbuf);
6139 * Deal with the UNIX specific mode set.
6142 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6143 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6144 (unsigned int)unixmode, fname ));
6145 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6146 return map_nt_error_from_unix(errno);
6151 * Deal with the UNIX specific uid set.
6154 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_ex_uid != set_owner)) {
6157 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6158 (unsigned int)set_owner, fname ));
6160 if (S_ISLNK(psbuf->st_ex_mode)) {
6161 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6163 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6167 status = map_nt_error_from_unix(errno);
6168 if (delete_on_fail) {
6169 SMB_VFS_UNLINK(conn,fname);
6176 * Deal with the UNIX specific gid set.
6179 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_ex_gid != set_grp)) {
6180 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6181 (unsigned int)set_owner, fname ));
6182 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6183 status = map_nt_error_from_unix(errno);
6184 if (delete_on_fail) {
6185 SMB_VFS_UNLINK(conn,fname);
6191 /* Deal with any size changes. */
6193 status = smb_set_file_size(conn, req,
6198 if (!NT_STATUS_IS_OK(status)) {
6202 /* Deal with any time changes. */
6203 id = vfs_file_id_from_sbuf(conn, psbuf);
6204 for(all_fsps = file_find_di_first(id); all_fsps;
6205 all_fsps = file_find_di_next(all_fsps)) {
6207 * We're setting the time explicitly for UNIX.
6208 * Cancel any pending changes over all handles.
6210 all_fsps->update_write_time_on_close = false;
6211 TALLOC_FREE(all_fsps->update_write_time_event);
6215 * Override the "setting_write_time"
6216 * parameter here as it almost does what
6217 * we need. Just remember if we modified
6218 * mtime and send the notify ourselves.
6220 if (null_timespec(ft.mtime)) {
6221 modify_mtime = false;
6224 status = smb_set_file_time(conn,
6231 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6232 FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
6237 /****************************************************************************
6238 Deal with SMB_SET_FILE_UNIX_INFO2.
6239 ****************************************************************************/
6241 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6242 struct smb_request *req,
6247 SMB_STRUCT_STAT *psbuf)
6253 if (total_data < 116) {
6254 return NT_STATUS_INVALID_PARAMETER;
6257 /* Start by setting all the fields that are common between UNIX_BASIC
6260 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6262 if (!NT_STATUS_IS_OK(status)) {
6266 smb_fflags = IVAL(pdata, 108);
6267 smb_fmask = IVAL(pdata, 112);
6269 /* NB: We should only attempt to alter the file flags if the client
6270 * sends a non-zero mask.
6272 if (smb_fmask != 0) {
6273 int stat_fflags = 0;
6275 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6277 /* Client asked to alter a flag we don't understand. */
6278 return NT_STATUS_INVALID_PARAMETER;
6281 if (fsp && fsp->fh->fd != -1) {
6282 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6283 return NT_STATUS_NOT_SUPPORTED;
6285 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6286 return map_nt_error_from_unix(errno);
6291 /* XXX: need to add support for changing the create_time here. You
6292 * can do this for paths on Darwin with setattrlist(2). The right way
6293 * to hook this up is probably by extending the VFS utimes interface.
6296 return NT_STATUS_OK;
6299 /****************************************************************************
6300 Create a directory with POSIX semantics.
6301 ****************************************************************************/
6303 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6304 struct smb_request *req,
6308 SMB_STRUCT_STAT *psbuf,
6309 int *pdata_return_size)
6311 NTSTATUS status = NT_STATUS_OK;
6312 uint32 raw_unixmode = 0;
6313 uint32 mod_unixmode = 0;
6314 mode_t unixmode = (mode_t)0;
6315 files_struct *fsp = NULL;
6316 uint16 info_level_return = 0;
6318 char *pdata = *ppdata;
6320 if (total_data < 18) {
6321 return NT_STATUS_INVALID_PARAMETER;
6324 raw_unixmode = IVAL(pdata,8);
6325 /* Next 4 bytes are not yet defined. */
6327 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6328 if (!NT_STATUS_IS_OK(status)) {
6332 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6334 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6335 fname, (unsigned int)unixmode ));
6337 status = SMB_VFS_CREATE_FILE(
6340 0, /* root_dir_fid */
6342 0, /* create_file_flags */
6343 FILE_READ_ATTRIBUTES, /* access_mask */
6344 FILE_SHARE_NONE, /* share_access */
6345 FILE_CREATE, /* create_disposition*/
6346 FILE_DIRECTORY_FILE, /* create_options */
6347 mod_unixmode, /* file_attributes */
6348 0, /* oplock_request */
6349 0, /* allocation_size */
6356 if (NT_STATUS_IS_OK(status)) {
6357 close_file(req, fsp, NORMAL_CLOSE);
6360 info_level_return = SVAL(pdata,16);
6362 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6363 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6364 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6365 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6367 *pdata_return_size = 12;
6370 /* Realloc the data size */
6371 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6372 if (*ppdata == NULL) {
6373 *pdata_return_size = 0;
6374 return NT_STATUS_NO_MEMORY;
6378 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6379 SSVAL(pdata,2,0); /* No fnum. */
6380 SIVAL(pdata,4,info); /* Was directory created. */
6382 switch (info_level_return) {
6383 case SMB_QUERY_FILE_UNIX_BASIC:
6384 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6385 SSVAL(pdata,10,0); /* Padding. */
6386 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6388 case SMB_QUERY_FILE_UNIX_INFO2:
6389 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6390 SSVAL(pdata,10,0); /* Padding. */
6391 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6394 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6395 SSVAL(pdata,10,0); /* Padding. */
6402 /****************************************************************************
6403 Open/Create a file with POSIX semantics.
6404 ****************************************************************************/
6406 static NTSTATUS smb_posix_open(connection_struct *conn,
6407 struct smb_request *req,
6411 SMB_STRUCT_STAT *psbuf,
6412 int *pdata_return_size)
6414 bool extended_oplock_granted = False;
6415 char *pdata = *ppdata;
6417 uint32 wire_open_mode = 0;
6418 uint32 raw_unixmode = 0;
6419 uint32 mod_unixmode = 0;
6420 uint32 create_disp = 0;
6421 uint32 access_mask = 0;
6422 uint32 create_options = 0;
6423 NTSTATUS status = NT_STATUS_OK;
6424 mode_t unixmode = (mode_t)0;
6425 files_struct *fsp = NULL;
6426 int oplock_request = 0;
6428 uint16 info_level_return = 0;
6430 if (total_data < 18) {
6431 return NT_STATUS_INVALID_PARAMETER;
6434 flags = IVAL(pdata,0);
6435 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6436 if (oplock_request) {
6437 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6440 wire_open_mode = IVAL(pdata,4);
6442 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6443 return smb_posix_mkdir(conn, req,
6451 switch (wire_open_mode & SMB_ACCMODE) {
6453 access_mask = FILE_READ_DATA;
6456 access_mask = FILE_WRITE_DATA;
6459 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6462 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6463 (unsigned int)wire_open_mode ));
6464 return NT_STATUS_INVALID_PARAMETER;
6467 wire_open_mode &= ~SMB_ACCMODE;
6469 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6470 create_disp = FILE_CREATE;
6471 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6472 create_disp = FILE_OVERWRITE_IF;
6473 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6474 create_disp = FILE_OPEN_IF;
6475 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
6476 create_disp = FILE_OPEN;
6478 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6479 (unsigned int)wire_open_mode ));
6480 return NT_STATUS_INVALID_PARAMETER;
6483 raw_unixmode = IVAL(pdata,8);
6484 /* Next 4 bytes are not yet defined. */
6486 status = unix_perms_from_wire(conn,
6489 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6492 if (!NT_STATUS_IS_OK(status)) {
6496 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6498 if (wire_open_mode & SMB_O_SYNC) {
6499 create_options |= FILE_WRITE_THROUGH;
6501 if (wire_open_mode & SMB_O_APPEND) {
6502 access_mask |= FILE_APPEND_DATA;
6504 if (wire_open_mode & SMB_O_DIRECT) {
6505 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6508 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6510 (unsigned int)wire_open_mode,
6511 (unsigned int)unixmode ));
6513 status = SMB_VFS_CREATE_FILE(
6516 0, /* root_dir_fid */
6518 0, /* create_file_flags */
6519 access_mask, /* access_mask */
6520 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6522 create_disp, /* create_disposition*/
6523 FILE_NON_DIRECTORY_FILE, /* create_options */
6524 mod_unixmode, /* file_attributes */
6525 oplock_request, /* oplock_request */
6526 0, /* allocation_size */
6533 if (!NT_STATUS_IS_OK(status)) {
6537 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6538 extended_oplock_granted = True;
6541 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6542 extended_oplock_granted = True;
6545 info_level_return = SVAL(pdata,16);
6547 /* Allocate the correct return size. */
6549 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6550 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6551 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6552 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6554 *pdata_return_size = 12;
6557 /* Realloc the data size */
6558 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6559 if (*ppdata == NULL) {
6560 close_file(req, fsp, ERROR_CLOSE);
6561 *pdata_return_size = 0;
6562 return NT_STATUS_NO_MEMORY;
6566 if (extended_oplock_granted) {
6567 if (flags & REQUEST_BATCH_OPLOCK) {
6568 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6570 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6572 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6573 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6575 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6578 SSVAL(pdata,2,fsp->fnum);
6579 SIVAL(pdata,4,info); /* Was file created etc. */
6581 switch (info_level_return) {
6582 case SMB_QUERY_FILE_UNIX_BASIC:
6583 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6584 SSVAL(pdata,10,0); /* padding. */
6585 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6587 case SMB_QUERY_FILE_UNIX_INFO2:
6588 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6589 SSVAL(pdata,10,0); /* padding. */
6590 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6593 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6594 SSVAL(pdata,10,0); /* padding. */
6597 return NT_STATUS_OK;
6600 /****************************************************************************
6601 Delete a file with POSIX semantics.
6602 ****************************************************************************/
6604 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6605 struct smb_request *req,
6609 SMB_STRUCT_STAT *psbuf)
6611 NTSTATUS status = NT_STATUS_OK;
6612 files_struct *fsp = NULL;
6616 int create_options = 0;
6618 struct share_mode_lock *lck = NULL;
6620 if (total_data < 2) {
6621 return NT_STATUS_INVALID_PARAMETER;
6624 flags = SVAL(pdata,0);
6626 if (!VALID_STAT(*psbuf)) {
6627 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6630 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6631 !VALID_STAT_OF_DIR(*psbuf)) {
6632 return NT_STATUS_NOT_A_DIRECTORY;
6635 DEBUG(10,("smb_posix_unlink: %s %s\n",
6636 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6639 if (VALID_STAT_OF_DIR(*psbuf)) {
6640 create_options |= FILE_DIRECTORY_FILE;
6643 status = SMB_VFS_CREATE_FILE(
6646 0, /* root_dir_fid */
6648 0, /* create_file_flags */
6649 DELETE_ACCESS, /* access_mask */
6650 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6652 FILE_OPEN, /* create_disposition*/
6653 create_options, /* create_options */
6654 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6655 0, /* oplock_request */
6656 0, /* allocation_size */
6663 if (!NT_STATUS_IS_OK(status)) {
6668 * Don't lie to client. If we can't really delete due to
6669 * non-POSIX opens return SHARING_VIOLATION.
6672 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6675 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6676 "lock for file %s\n", fsp->fsp_name));
6677 close_file(req, fsp, NORMAL_CLOSE);
6678 return NT_STATUS_INVALID_PARAMETER;
6682 * See if others still have the file open. If this is the case, then
6683 * don't delete. If all opens are POSIX delete we can set the delete
6684 * on close disposition.
6686 for (i=0; i<lck->num_share_modes; i++) {
6687 struct share_mode_entry *e = &lck->share_modes[i];
6688 if (is_valid_share_mode_entry(e)) {
6689 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6692 /* Fail with sharing violation. */
6693 close_file(req, fsp, NORMAL_CLOSE);
6695 return NT_STATUS_SHARING_VIOLATION;
6700 * Set the delete on close.
6702 status = smb_set_file_disposition_info(conn,
6709 if (!NT_STATUS_IS_OK(status)) {
6710 close_file(req, fsp, NORMAL_CLOSE);
6715 return close_file(req, fsp, NORMAL_CLOSE);
6718 /****************************************************************************
6719 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6720 ****************************************************************************/
6722 static void call_trans2setfilepathinfo(connection_struct *conn,
6723 struct smb_request *req,
6724 unsigned int tran_call,
6725 char **pparams, int total_params,
6726 char **ppdata, int total_data,
6727 unsigned int max_data_bytes)
6729 char *params = *pparams;
6730 char *pdata = *ppdata;
6732 SMB_STRUCT_STAT sbuf;
6734 files_struct *fsp = NULL;
6735 NTSTATUS status = NT_STATUS_OK;
6736 int data_return_size = 0;
6737 TALLOC_CTX *ctx = talloc_tos();
6740 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6746 if (tran_call == TRANSACT2_SETFILEINFO) {
6747 if (total_params < 4) {
6748 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6752 fsp = file_fsp(req, SVAL(params,0));
6753 /* Basic check for non-null fsp. */
6754 if (!check_fsp_open(conn, req, fsp)) {
6757 info_level = SVAL(params,2);
6759 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6761 reply_nterror(req, NT_STATUS_NO_MEMORY);
6765 if(fsp->is_directory || fsp->fh->fd == -1) {
6767 * This is actually a SETFILEINFO on a directory
6768 * handle (returned from an NT SMB). NT5.0 seems
6769 * to do this call. JRA.
6771 if (INFO_LEVEL_IS_UNIX(info_level)) {
6772 /* Always do lstat for UNIX calls. */
6773 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6774 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6775 reply_unixerror(req,ERRDOS,ERRbadpath);
6779 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6780 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6781 reply_unixerror(req,ERRDOS,ERRbadpath);
6785 } else if (fsp->print_file) {
6787 * Doing a DELETE_ON_CLOSE should cancel a print job.
6789 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6790 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6792 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6795 send_trans2_replies(conn, req, params, 2,
6800 reply_unixerror(req, ERRDOS, ERRbadpath);
6805 * Original code - this is an open file.
6807 if (!check_fsp(conn, req, fsp)) {
6811 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6812 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6813 reply_unixerror(req, ERRDOS, ERRbadfid);
6819 if (total_params < 7) {
6820 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6824 info_level = SVAL(params,0);
6825 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6826 total_params - 6, STR_TERMINATE,
6828 if (!NT_STATUS_IS_OK(status)) {
6829 reply_nterror(req, status);
6833 status = resolve_dfspath(ctx, conn,
6834 req->flags2 & FLAGS2_DFS_PATHNAMES,
6837 if (!NT_STATUS_IS_OK(status)) {
6838 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6839 reply_botherror(req,
6840 NT_STATUS_PATH_NOT_COVERED,
6841 ERRSRV, ERRbadpath);
6844 reply_nterror(req, status);
6848 status = unix_convert(ctx, conn, fname, False,
6849 &fname, NULL, &sbuf);
6850 if (!NT_STATUS_IS_OK(status)) {
6851 reply_nterror(req, status);
6855 status = check_name(conn, fname);
6856 if (!NT_STATUS_IS_OK(status)) {
6857 reply_nterror(req, status);
6861 if (INFO_LEVEL_IS_UNIX(info_level)) {
6863 * For CIFS UNIX extensions the target name may not exist.
6866 /* Always do lstat for UNIX calls. */
6867 SMB_VFS_LSTAT(conn,fname,&sbuf);
6869 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6870 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6871 reply_unixerror(req, ERRDOS, ERRbadpath);
6876 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6877 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6881 if (!CAN_WRITE(conn)) {
6882 /* Allow POSIX opens. The open path will deny
6883 * any non-readonly opens. */
6884 if (info_level != SMB_POSIX_PATH_OPEN) {
6885 reply_doserror(req, ERRSRV, ERRaccess);
6890 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6891 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6893 /* Realloc the parameter size */
6894 *pparams = (char *)SMB_REALLOC(*pparams,2);
6895 if (*pparams == NULL) {
6896 reply_nterror(req, NT_STATUS_NO_MEMORY);
6903 switch (info_level) {
6905 case SMB_INFO_STANDARD:
6907 status = smb_set_info_standard(conn,
6916 case SMB_INFO_SET_EA:
6918 status = smb_info_set_ea(conn,
6926 case SMB_SET_FILE_BASIC_INFO:
6927 case SMB_FILE_BASIC_INFORMATION:
6929 status = smb_set_file_basic_info(conn,
6938 case SMB_FILE_ALLOCATION_INFORMATION:
6939 case SMB_SET_FILE_ALLOCATION_INFO:
6941 status = smb_set_file_allocation_info(conn, req,
6950 case SMB_FILE_END_OF_FILE_INFORMATION:
6951 case SMB_SET_FILE_END_OF_FILE_INFO:
6953 status = smb_set_file_end_of_file_info(conn, req,
6962 case SMB_FILE_DISPOSITION_INFORMATION:
6963 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6966 /* JRA - We used to just ignore this on a path ?
6967 * Shouldn't this be invalid level on a pathname
6970 if (tran_call != TRANSACT2_SETFILEINFO) {
6971 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6974 status = smb_set_file_disposition_info(conn,
6983 case SMB_FILE_POSITION_INFORMATION:
6985 status = smb_file_position_information(conn,
6992 /* From tridge Samba4 :
6993 * MODE_INFORMATION in setfileinfo (I have no
6994 * idea what "mode information" on a file is - it takes a value of 0,
6995 * 2, 4 or 6. What could it be?).
6998 case SMB_FILE_MODE_INFORMATION:
7000 status = smb_file_mode_information(conn,
7007 * CIFS UNIX extensions.
7010 case SMB_SET_FILE_UNIX_BASIC:
7012 status = smb_set_file_unix_basic(conn, req,
7021 case SMB_SET_FILE_UNIX_INFO2:
7023 status = smb_set_file_unix_info2(conn, req,
7032 case SMB_SET_FILE_UNIX_LINK:
7034 if (tran_call != TRANSACT2_SETPATHINFO) {
7035 /* We must have a pathname for this. */
7036 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7039 status = smb_set_file_unix_link(conn, req, pdata,
7044 case SMB_SET_FILE_UNIX_HLINK:
7046 if (tran_call != TRANSACT2_SETPATHINFO) {
7047 /* We must have a pathname for this. */
7048 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7051 status = smb_set_file_unix_hlink(conn, req,
7057 case SMB_FILE_RENAME_INFORMATION:
7059 status = smb_file_rename_information(conn, req,
7065 #if defined(HAVE_POSIX_ACLS)
7066 case SMB_SET_POSIX_ACL:
7068 status = smb_set_posix_acl(conn,
7078 case SMB_SET_POSIX_LOCK:
7080 if (tran_call != TRANSACT2_SETFILEINFO) {
7081 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7084 status = smb_set_posix_lock(conn, req,
7085 pdata, total_data, fsp);
7089 case SMB_POSIX_PATH_OPEN:
7091 if (tran_call != TRANSACT2_SETPATHINFO) {
7092 /* We must have a pathname for this. */
7093 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7097 status = smb_posix_open(conn, req,
7106 case SMB_POSIX_PATH_UNLINK:
7108 if (tran_call != TRANSACT2_SETPATHINFO) {
7109 /* We must have a pathname for this. */
7110 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7114 status = smb_posix_unlink(conn, req,
7123 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7128 if (!NT_STATUS_IS_OK(status)) {
7129 if (open_was_deferred(req->mid)) {
7130 /* We have re-scheduled this call. */
7133 if (blocking_lock_was_deferred(req->mid)) {
7134 /* We have re-scheduled this call. */
7137 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7138 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7139 ERRSRV, ERRbadpath);
7142 if (info_level == SMB_POSIX_PATH_OPEN) {
7143 reply_openerror(req, status);
7147 reply_nterror(req, status);
7152 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7158 /****************************************************************************
7159 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7160 ****************************************************************************/
7162 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7163 char **pparams, int total_params,
7164 char **ppdata, int total_data,
7165 unsigned int max_data_bytes)
7167 char *params = *pparams;
7168 char *pdata = *ppdata;
7169 char *directory = NULL;
7170 SMB_STRUCT_STAT sbuf;
7171 NTSTATUS status = NT_STATUS_OK;
7172 struct ea_list *ea_list = NULL;
7173 TALLOC_CTX *ctx = talloc_tos();
7175 if (!CAN_WRITE(conn)) {
7176 reply_doserror(req, ERRSRV, ERRaccess);
7180 if (total_params < 5) {
7181 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7185 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7186 total_params - 4, STR_TERMINATE,
7188 if (!NT_STATUS_IS_OK(status)) {
7189 reply_nterror(req, status);
7193 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7195 status = resolve_dfspath(ctx,
7197 req->flags2 & FLAGS2_DFS_PATHNAMES,
7200 if (!NT_STATUS_IS_OK(status)) {
7201 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7202 reply_botherror(req,
7203 NT_STATUS_PATH_NOT_COVERED,
7204 ERRSRV, ERRbadpath);
7206 reply_nterror(req, status);
7210 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7211 if (!NT_STATUS_IS_OK(status)) {
7212 reply_nterror(req, status);
7216 status = check_name(conn, directory);
7217 if (!NT_STATUS_IS_OK(status)) {
7218 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7219 reply_nterror(req, status);
7223 /* Any data in this call is an EA list. */
7224 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7225 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7230 * OS/2 workplace shell seems to send SET_EA requests of "null"
7231 * length (4 bytes containing IVAL 4).
7232 * They seem to have no effect. Bug #3212. JRA.
7235 if (total_data != 4) {
7236 if (total_data < 10) {
7237 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7241 if (IVAL(pdata,0) > total_data) {
7242 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7243 IVAL(pdata,0), (unsigned int)total_data));
7244 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7248 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7251 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7255 /* If total_data == 4 Windows doesn't care what values
7256 * are placed in that field, it just ignores them.
7257 * The System i QNTC IBM SMB client puts bad values here,
7258 * so ignore them. */
7260 status = create_directory(conn, req, directory);
7262 if (!NT_STATUS_IS_OK(status)) {
7263 reply_nterror(req, status);
7267 /* Try and set any given EA. */
7269 status = set_ea(conn, NULL, directory, ea_list);
7270 if (!NT_STATUS_IS_OK(status)) {
7271 reply_nterror(req, status);
7276 /* Realloc the parameter and data sizes */
7277 *pparams = (char *)SMB_REALLOC(*pparams,2);
7278 if(*pparams == NULL) {
7279 reply_nterror(req, NT_STATUS_NO_MEMORY);
7286 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7291 /****************************************************************************
7292 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7293 We don't actually do this - we just send a null response.
7294 ****************************************************************************/
7296 static void call_trans2findnotifyfirst(connection_struct *conn,
7297 struct smb_request *req,
7298 char **pparams, int total_params,
7299 char **ppdata, int total_data,
7300 unsigned int max_data_bytes)
7302 char *params = *pparams;
7305 if (total_params < 6) {
7306 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7310 info_level = SVAL(params,4);
7311 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7313 switch (info_level) {
7318 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7322 /* Realloc the parameter and data sizes */
7323 *pparams = (char *)SMB_REALLOC(*pparams,6);
7324 if (*pparams == NULL) {
7325 reply_nterror(req, NT_STATUS_NO_MEMORY);
7330 SSVAL(params,0,fnf_handle);
7331 SSVAL(params,2,0); /* No changes */
7332 SSVAL(params,4,0); /* No EA errors */
7339 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7344 /****************************************************************************
7345 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7346 changes). Currently this does nothing.
7347 ****************************************************************************/
7349 static void call_trans2findnotifynext(connection_struct *conn,
7350 struct smb_request *req,
7351 char **pparams, int total_params,
7352 char **ppdata, int total_data,
7353 unsigned int max_data_bytes)
7355 char *params = *pparams;
7357 DEBUG(3,("call_trans2findnotifynext\n"));
7359 /* Realloc the parameter and data sizes */
7360 *pparams = (char *)SMB_REALLOC(*pparams,4);
7361 if (*pparams == NULL) {
7362 reply_nterror(req, NT_STATUS_NO_MEMORY);
7367 SSVAL(params,0,0); /* No changes */
7368 SSVAL(params,2,0); /* No EA errors */
7370 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7375 /****************************************************************************
7376 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7377 ****************************************************************************/
7379 static void call_trans2getdfsreferral(connection_struct *conn,
7380 struct smb_request *req,
7381 char **pparams, int total_params,
7382 char **ppdata, int total_data,
7383 unsigned int max_data_bytes)
7385 char *params = *pparams;
7386 char *pathname = NULL;
7388 int max_referral_level;
7389 NTSTATUS status = NT_STATUS_OK;
7390 TALLOC_CTX *ctx = talloc_tos();
7392 DEBUG(10,("call_trans2getdfsreferral\n"));
7394 if (total_params < 3) {
7395 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7399 max_referral_level = SVAL(params,0);
7401 if(!lp_host_msdfs()) {
7402 reply_doserror(req, ERRDOS, ERRbadfunc);
7406 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7407 total_params - 2, STR_TERMINATE);
7409 reply_nterror(req, NT_STATUS_NOT_FOUND);
7412 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7413 ppdata,&status)) < 0) {
7414 reply_nterror(req, status);
7418 SSVAL(req->inbuf, smb_flg2,
7419 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7420 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7425 #define LMCAT_SPL 0x53
7426 #define LMFUNC_GETJOBID 0x60
7428 /****************************************************************************
7429 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7430 ****************************************************************************/
7432 static void call_trans2ioctl(connection_struct *conn,
7433 struct smb_request *req,
7434 char **pparams, int total_params,
7435 char **ppdata, int total_data,
7436 unsigned int max_data_bytes)
7438 char *pdata = *ppdata;
7439 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7441 /* check for an invalid fid before proceeding */
7444 reply_doserror(req, ERRDOS, ERRbadfid);
7448 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7449 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7450 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7451 if (*ppdata == NULL) {
7452 reply_nterror(req, NT_STATUS_NO_MEMORY);
7457 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7458 CAN ACCEPT THIS IN UNICODE. JRA. */
7460 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7461 srvstr_push(pdata, req->flags2, pdata + 2,
7462 global_myname(), 15,
7463 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7464 srvstr_push(pdata, req->flags2, pdata+18,
7465 lp_servicename(SNUM(conn)), 13,
7466 STR_ASCII|STR_TERMINATE); /* Service name */
7467 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7472 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7473 reply_doserror(req, ERRSRV, ERRerror);
7476 /****************************************************************************
7477 Reply to a SMBfindclose (stop trans2 directory search).
7478 ****************************************************************************/
7480 void reply_findclose(struct smb_request *req)
7484 START_PROFILE(SMBfindclose);
7487 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7488 END_PROFILE(SMBfindclose);
7492 dptr_num = SVALS(req->vwv+0, 0);
7494 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7496 dptr_close(&dptr_num);
7498 reply_outbuf(req, 0, 0);
7500 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7502 END_PROFILE(SMBfindclose);
7506 /****************************************************************************
7507 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7508 ****************************************************************************/
7510 void reply_findnclose(struct smb_request *req)
7514 START_PROFILE(SMBfindnclose);
7517 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7518 END_PROFILE(SMBfindnclose);
7522 dptr_num = SVAL(req->vwv+0, 0);
7524 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7526 /* We never give out valid handles for a
7527 findnotifyfirst - so any dptr_num is ok here.
7530 reply_outbuf(req, 0, 0);
7532 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7534 END_PROFILE(SMBfindnclose);
7538 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7539 struct trans_state *state)
7541 if (Protocol >= PROTOCOL_NT1) {
7542 req->flags2 |= 0x40; /* IS_LONG_NAME */
7543 SSVAL(req->inbuf,smb_flg2,req->flags2);
7546 if (conn->encrypt_level == Required && !req->encrypted) {
7547 if (state->call != TRANSACT2_QFSINFO &&
7548 state->call != TRANSACT2_SETFSINFO) {
7549 DEBUG(0,("handle_trans2: encryption required "
7551 (unsigned int)state->call));
7552 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7557 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
7559 /* Now we must call the relevant TRANS2 function */
7560 switch(state->call) {
7561 case TRANSACT2_OPEN:
7563 START_PROFILE(Trans2_open);
7564 call_trans2open(conn, req,
7565 &state->param, state->total_param,
7566 &state->data, state->total_data,
7567 state->max_data_return);
7568 END_PROFILE(Trans2_open);
7572 case TRANSACT2_FINDFIRST:
7574 START_PROFILE(Trans2_findfirst);
7575 call_trans2findfirst(conn, req,
7576 &state->param, state->total_param,
7577 &state->data, state->total_data,
7578 state->max_data_return);
7579 END_PROFILE(Trans2_findfirst);
7583 case TRANSACT2_FINDNEXT:
7585 START_PROFILE(Trans2_findnext);
7586 call_trans2findnext(conn, req,
7587 &state->param, state->total_param,
7588 &state->data, state->total_data,
7589 state->max_data_return);
7590 END_PROFILE(Trans2_findnext);
7594 case TRANSACT2_QFSINFO:
7596 START_PROFILE(Trans2_qfsinfo);
7597 call_trans2qfsinfo(conn, req,
7598 &state->param, state->total_param,
7599 &state->data, state->total_data,
7600 state->max_data_return);
7601 END_PROFILE(Trans2_qfsinfo);
7605 case TRANSACT2_SETFSINFO:
7607 START_PROFILE(Trans2_setfsinfo);
7608 call_trans2setfsinfo(conn, req,
7609 &state->param, state->total_param,
7610 &state->data, state->total_data,
7611 state->max_data_return);
7612 END_PROFILE(Trans2_setfsinfo);
7616 case TRANSACT2_QPATHINFO:
7617 case TRANSACT2_QFILEINFO:
7619 START_PROFILE(Trans2_qpathinfo);
7620 call_trans2qfilepathinfo(conn, req, state->call,
7621 &state->param, state->total_param,
7622 &state->data, state->total_data,
7623 state->max_data_return);
7624 END_PROFILE(Trans2_qpathinfo);
7628 case TRANSACT2_SETPATHINFO:
7629 case TRANSACT2_SETFILEINFO:
7631 START_PROFILE(Trans2_setpathinfo);
7632 call_trans2setfilepathinfo(conn, req, state->call,
7633 &state->param, state->total_param,
7634 &state->data, state->total_data,
7635 state->max_data_return);
7636 END_PROFILE(Trans2_setpathinfo);
7640 case TRANSACT2_FINDNOTIFYFIRST:
7642 START_PROFILE(Trans2_findnotifyfirst);
7643 call_trans2findnotifyfirst(conn, req,
7644 &state->param, state->total_param,
7645 &state->data, state->total_data,
7646 state->max_data_return);
7647 END_PROFILE(Trans2_findnotifyfirst);
7651 case TRANSACT2_FINDNOTIFYNEXT:
7653 START_PROFILE(Trans2_findnotifynext);
7654 call_trans2findnotifynext(conn, req,
7655 &state->param, state->total_param,
7656 &state->data, state->total_data,
7657 state->max_data_return);
7658 END_PROFILE(Trans2_findnotifynext);
7662 case TRANSACT2_MKDIR:
7664 START_PROFILE(Trans2_mkdir);
7665 call_trans2mkdir(conn, req,
7666 &state->param, state->total_param,
7667 &state->data, state->total_data,
7668 state->max_data_return);
7669 END_PROFILE(Trans2_mkdir);
7673 case TRANSACT2_GET_DFS_REFERRAL:
7675 START_PROFILE(Trans2_get_dfs_referral);
7676 call_trans2getdfsreferral(conn, req,
7677 &state->param, state->total_param,
7678 &state->data, state->total_data,
7679 state->max_data_return);
7680 END_PROFILE(Trans2_get_dfs_referral);
7684 case TRANSACT2_IOCTL:
7686 START_PROFILE(Trans2_ioctl);
7687 call_trans2ioctl(conn, req,
7688 &state->param, state->total_param,
7689 &state->data, state->total_data,
7690 state->max_data_return);
7691 END_PROFILE(Trans2_ioctl);
7696 /* Error in request */
7697 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7698 reply_doserror(req, ERRSRV,ERRerror);
7702 /****************************************************************************
7703 Reply to a SMBtrans2.
7704 ****************************************************************************/
7706 void reply_trans2(struct smb_request *req)
7708 connection_struct *conn = req->conn;
7713 unsigned int tran_call;
7714 struct trans_state *state;
7717 START_PROFILE(SMBtrans2);
7719 if (req->wct < 14) {
7720 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7721 END_PROFILE(SMBtrans2);
7725 dsoff = SVAL(req->vwv+12, 0);
7726 dscnt = SVAL(req->vwv+11, 0);
7727 psoff = SVAL(req->vwv+10, 0);
7728 pscnt = SVAL(req->vwv+9, 0);
7729 tran_call = SVAL(req->vwv+14, 0);
7731 result = allow_new_trans(conn->pending_trans, req->mid);
7732 if (!NT_STATUS_IS_OK(result)) {
7733 DEBUG(2, ("Got invalid trans2 request: %s\n",
7734 nt_errstr(result)));
7735 reply_nterror(req, result);
7736 END_PROFILE(SMBtrans2);
7741 switch (tran_call) {
7742 /* List the allowed trans2 calls on IPC$ */
7743 case TRANSACT2_OPEN:
7744 case TRANSACT2_GET_DFS_REFERRAL:
7745 case TRANSACT2_QFILEINFO:
7746 case TRANSACT2_QFSINFO:
7747 case TRANSACT2_SETFSINFO:
7750 reply_doserror(req, ERRSRV, ERRaccess);
7751 END_PROFILE(SMBtrans2);
7756 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7757 DEBUG(0, ("talloc failed\n"));
7758 reply_nterror(req, NT_STATUS_NO_MEMORY);
7759 END_PROFILE(SMBtrans2);
7763 state->cmd = SMBtrans2;
7765 state->mid = req->mid;
7766 state->vuid = req->vuid;
7767 state->setup_count = SVAL(req->vwv+13, 0);
7768 state->setup = NULL;
7769 state->total_param = SVAL(req->vwv+0, 0);
7770 state->param = NULL;
7771 state->total_data = SVAL(req->vwv+1, 0);
7773 state->max_param_return = SVAL(req->vwv+2, 0);
7774 state->max_data_return = SVAL(req->vwv+3, 0);
7775 state->max_setup_return = SVAL(req->vwv+4, 0);
7776 state->close_on_completion = BITSETW(req->vwv+5, 0);
7777 state->one_way = BITSETW(req->vwv+5, 1);
7779 state->call = tran_call;
7781 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7782 is so as a sanity check */
7783 if (state->setup_count != 1) {
7785 * Need to have rc=0 for ioctl to get job id for OS/2.
7786 * Network printing will fail if function is not successful.
7787 * Similar function in reply.c will be used if protocol
7788 * is LANMAN1.0 instead of LM1.2X002.
7789 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7790 * outbuf doesn't have to be set(only job id is used).
7792 if ( (state->setup_count == 4)
7793 && (tran_call == TRANSACT2_IOCTL)
7794 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7795 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7796 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7798 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7799 DEBUG(2,("Transaction is %d\n",tran_call));
7801 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7802 END_PROFILE(SMBtrans2);
7807 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7810 if (state->total_data) {
7812 if (trans_oob(state->total_data, 0, dscnt)
7813 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7817 /* Can't use talloc here, the core routines do realloc on the
7818 * params and data. */
7819 state->data = (char *)SMB_MALLOC(state->total_data);
7820 if (state->data == NULL) {
7821 DEBUG(0,("reply_trans2: data malloc fail for %u "
7822 "bytes !\n", (unsigned int)state->total_data));
7824 reply_nterror(req, NT_STATUS_NO_MEMORY);
7825 END_PROFILE(SMBtrans2);
7829 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7832 if (state->total_param) {
7834 if (trans_oob(state->total_param, 0, pscnt)
7835 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7839 /* Can't use talloc here, the core routines do realloc on the
7840 * params and data. */
7841 state->param = (char *)SMB_MALLOC(state->total_param);
7842 if (state->param == NULL) {
7843 DEBUG(0,("reply_trans: param malloc fail for %u "
7844 "bytes !\n", (unsigned int)state->total_param));
7845 SAFE_FREE(state->data);
7847 reply_nterror(req, NT_STATUS_NO_MEMORY);
7848 END_PROFILE(SMBtrans2);
7852 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7855 state->received_data = dscnt;
7856 state->received_param = pscnt;
7858 if ((state->received_param == state->total_param) &&
7859 (state->received_data == state->total_data)) {
7861 handle_trans2(conn, req, state);
7863 SAFE_FREE(state->data);
7864 SAFE_FREE(state->param);
7866 END_PROFILE(SMBtrans2);
7870 DLIST_ADD(conn->pending_trans, state);
7872 /* We need to send an interim response then receive the rest
7873 of the parameter/data bytes */
7874 reply_outbuf(req, 0, 0);
7875 show_msg((char *)req->outbuf);
7876 END_PROFILE(SMBtrans2);
7881 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7882 SAFE_FREE(state->data);
7883 SAFE_FREE(state->param);
7885 END_PROFILE(SMBtrans2);
7886 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7890 /****************************************************************************
7891 Reply to a SMBtranss2
7892 ****************************************************************************/
7894 void reply_transs2(struct smb_request *req)
7896 connection_struct *conn = req->conn;
7897 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7898 struct trans_state *state;
7900 START_PROFILE(SMBtranss2);
7902 show_msg((char *)req->inbuf);
7905 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7906 END_PROFILE(SMBtranss2);
7910 for (state = conn->pending_trans; state != NULL;
7911 state = state->next) {
7912 if (state->mid == req->mid) {
7917 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7918 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7919 END_PROFILE(SMBtranss2);
7923 /* Revise state->total_param and state->total_data in case they have
7924 changed downwards */
7926 if (SVAL(req->vwv+0, 0) < state->total_param)
7927 state->total_param = SVAL(req->vwv+0, 0);
7928 if (SVAL(req->vwv+1, 0) < state->total_data)
7929 state->total_data = SVAL(req->vwv+1, 0);
7931 pcnt = SVAL(req->vwv+2, 0);
7932 poff = SVAL(req->vwv+3, 0);
7933 pdisp = SVAL(req->vwv+4, 0);
7935 dcnt = SVAL(req->vwv+5, 0);
7936 doff = SVAL(req->vwv+6, 0);
7937 ddisp = SVAL(req->vwv+7, 0);
7939 state->received_param += pcnt;
7940 state->received_data += dcnt;
7942 if ((state->received_data > state->total_data) ||
7943 (state->received_param > state->total_param))
7947 if (trans_oob(state->total_param, pdisp, pcnt)
7948 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7951 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7955 if (trans_oob(state->total_data, ddisp, dcnt)
7956 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7959 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7962 if ((state->received_param < state->total_param) ||
7963 (state->received_data < state->total_data)) {
7964 END_PROFILE(SMBtranss2);
7968 handle_trans2(conn, req, state);
7970 DLIST_REMOVE(conn->pending_trans, state);
7971 SAFE_FREE(state->data);
7972 SAFE_FREE(state->param);
7975 END_PROFILE(SMBtranss2);
7980 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7981 DLIST_REMOVE(conn->pending_trans, state);
7982 SAFE_FREE(state->data);
7983 SAFE_FREE(state->param);
7985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7986 END_PROFILE(SMBtranss2);