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/>.
29 extern enum protocol_types Protocol;
30 extern uint32 global_client_caps;
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 SMB_BIG_UINT smb_roundup(connection_struct *conn, SMB_BIG_UINT val)
52 SMB_BIG_UINT rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
62 /********************************************************************
63 Given a stat buffer return the allocated size on disk, taking into
65 ********************************************************************/
67 SMB_BIG_UINT get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
71 if(S_ISDIR(sbuf->st_mode)) {
75 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
76 ret = (SMB_BIG_UINT)STAT_ST_BLOCKSIZE * (SMB_BIG_UINT)sbuf->st_blocks;
78 ret = (SMB_BIG_UINT)get_file_size(*sbuf);
81 if (fsp && fsp->initial_allocation_size)
82 ret = MAX(ret,fsp->initial_allocation_size);
84 return smb_roundup(conn, ret);
87 /****************************************************************************
88 Utility functions for dealing with extended attributes.
89 ****************************************************************************/
91 /****************************************************************************
92 Refuse to allow clients to overwrite our private xattrs.
93 ****************************************************************************/
95 static bool samba_private_attr_name(const char *unix_ea_name)
97 static const char *prohibited_ea_names[] = {
98 SAMBA_POSIX_INHERITANCE_EA_NAME,
99 SAMBA_XATTR_DOS_ATTRIB,
105 for (i = 0; prohibited_ea_names[i]; i++) {
106 if (strequal( prohibited_ea_names[i], unix_ea_name))
109 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
110 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
116 /****************************************************************************
117 Get one EA value. Fill in a struct ea_struct.
118 ****************************************************************************/
120 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
121 files_struct *fsp, const char *fname,
122 const char *ea_name, struct ea_struct *pea)
124 /* Get the value of this xattr. Max size is 64k. */
125 size_t attr_size = 256;
131 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
133 return NT_STATUS_NO_MEMORY;
136 if (fsp && fsp->fh->fd != -1) {
137 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
139 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
142 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
148 return map_nt_error_from_unix(errno);
151 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
152 dump_data(10, (uint8 *)val, sizeret);
155 if (strnequal(ea_name, "user.", 5)) {
156 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
158 pea->name = talloc_strdup(mem_ctx, ea_name);
160 if (pea->name == NULL) {
162 return NT_STATUS_NO_MEMORY;
164 pea->value.data = (unsigned char *)val;
165 pea->value.length = (size_t)sizeret;
169 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
170 files_struct *fsp, const char *fname,
171 char ***pnames, size_t *pnum_names)
173 /* Get a list of all xattrs. Max namesize is 64k. */
174 size_t ea_namelist_size = 1024;
175 char *ea_namelist = NULL;
180 ssize_t sizeret = -1;
182 if (!lp_ea_support(SNUM(conn))) {
189 * TALLOC the result early to get the talloc hierarchy right.
192 names = TALLOC_ARRAY(mem_ctx, char *, 1);
194 DEBUG(0, ("talloc failed\n"));
195 return NT_STATUS_NO_MEMORY;
198 while (ea_namelist_size <= 65536) {
200 ea_namelist = TALLOC_REALLOC_ARRAY(
201 names, ea_namelist, char, ea_namelist_size);
202 if (ea_namelist == NULL) {
203 DEBUG(0, ("talloc failed\n"));
205 return NT_STATUS_NO_MEMORY;
208 if (fsp && fsp->fh->fd != -1) {
209 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
212 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
216 if ((sizeret == -1) && (errno == ERANGE)) {
217 ea_namelist_size *= 2;
226 return map_nt_error_from_unix(errno);
229 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
230 (unsigned int)sizeret));
240 * Ensure the result is 0-terminated
243 if (ea_namelist[sizeret-1] != '\0') {
245 return NT_STATUS_INTERNAL_ERROR;
253 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
257 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
259 DEBUG(0, ("talloc failed\n"));
261 return NT_STATUS_NO_MEMORY;
267 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
268 names[num_names++] = p;
272 *pnum_names = num_names;
276 /****************************************************************************
277 Return a linked list of the total EA's. Plus the total size
278 ****************************************************************************/
280 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
281 const char *fname, size_t *pea_total_len)
283 /* Get a list of all xattrs. Max namesize is 64k. */
286 struct ea_list *ea_list_head = NULL;
291 if (!lp_ea_support(SNUM(conn))) {
295 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
298 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
302 for (i=0; i<num_names; i++) {
303 struct ea_list *listp;
306 if (strnequal(names[i], "system.", 7)
307 || samba_private_attr_name(names[i]))
310 listp = TALLOC_P(mem_ctx, struct ea_list);
315 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
321 push_ascii_fstring(dos_ea_name, listp->ea.name);
324 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
326 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
327 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
328 (unsigned int)listp->ea.value.length));
330 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
334 /* Add on 4 for total length. */
335 if (*pea_total_len) {
339 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
340 (unsigned int)*pea_total_len));
345 /****************************************************************************
346 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
348 ****************************************************************************/
350 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
351 connection_struct *conn, struct ea_list *ea_list)
353 unsigned int ret_data_size = 4;
356 SMB_ASSERT(total_data_size >= 4);
358 if (!lp_ea_support(SNUM(conn))) {
363 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
366 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
367 dos_namelen = strlen(dos_ea_name);
368 if (dos_namelen > 255 || dos_namelen == 0) {
371 if (ea_list->ea.value.length > 65535) {
374 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
378 /* We know we have room. */
379 SCVAL(p,0,ea_list->ea.flags);
380 SCVAL(p,1,dos_namelen);
381 SSVAL(p,2,ea_list->ea.value.length);
382 fstrcpy(p+4, dos_ea_name);
383 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
385 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
386 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
389 ret_data_size = PTR_DIFF(p, pdata);
390 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
391 SIVAL(pdata,0,ret_data_size);
392 return ret_data_size;
395 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
397 size_t total_ea_len = 0;
398 TALLOC_CTX *mem_ctx = NULL;
400 if (!lp_ea_support(SNUM(conn))) {
403 mem_ctx = talloc_tos();
404 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
408 /****************************************************************************
409 Ensure the EA name is case insensitive by matching any existing EA name.
410 ****************************************************************************/
412 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
415 TALLOC_CTX *mem_ctx = talloc_tos();
416 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
418 for (; ea_list; ea_list = ea_list->next) {
419 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
420 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
421 &unix_ea_name[5], ea_list->ea.name));
422 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
428 /****************************************************************************
429 Set or delete an extended attribute.
430 ****************************************************************************/
432 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
434 if (!lp_ea_support(SNUM(conn))) {
435 return NT_STATUS_EAS_NOT_SUPPORTED;
438 for (;ea_list; ea_list = ea_list->next) {
440 fstring unix_ea_name;
442 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
443 fstrcat(unix_ea_name, ea_list->ea.name);
445 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
447 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
449 if (samba_private_attr_name(unix_ea_name)) {
450 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
451 return NT_STATUS_ACCESS_DENIED;
454 if (ea_list->ea.value.length == 0) {
455 /* Remove the attribute. */
456 if (fsp && (fsp->fh->fd != -1)) {
457 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
458 unix_ea_name, fsp->fsp_name));
459 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
461 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
462 unix_ea_name, fname));
463 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
466 /* Removing a non existent attribute always succeeds. */
467 if (ret == -1 && errno == ENOATTR) {
468 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
474 if (fsp && (fsp->fh->fd != -1)) {
475 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
476 unix_ea_name, fsp->fsp_name));
477 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
478 ea_list->ea.value.data, ea_list->ea.value.length, 0);
480 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
481 unix_ea_name, fname));
482 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
483 ea_list->ea.value.data, ea_list->ea.value.length, 0);
489 if (errno == ENOTSUP) {
490 return NT_STATUS_EAS_NOT_SUPPORTED;
493 return map_nt_error_from_unix(errno);
499 /****************************************************************************
500 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
501 ****************************************************************************/
503 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
505 struct ea_list *ea_list_head = NULL;
506 size_t converted_size, offset = 0;
508 while (offset + 2 < data_size) {
509 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
510 unsigned int namelen = CVAL(pdata,offset);
512 offset++; /* Go past the namelen byte. */
514 /* integer wrap paranioa. */
515 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
516 (offset > data_size) || (namelen > data_size) ||
517 (offset + namelen >= data_size)) {
520 /* Ensure the name is null terminated. */
521 if (pdata[offset + namelen] != '\0') {
524 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
526 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
527 "failed: %s", strerror(errno)));
533 offset += (namelen + 1); /* Go past the name + terminating zero. */
534 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
535 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
541 /****************************************************************************
542 Read one EA list entry from the buffer.
543 ****************************************************************************/
545 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
547 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
549 unsigned int namelen;
550 size_t converted_size;
560 eal->ea.flags = CVAL(pdata,0);
561 namelen = CVAL(pdata,1);
562 val_len = SVAL(pdata,2);
564 if (4 + namelen + 1 + val_len > data_size) {
568 /* Ensure the name is null terminated. */
569 if (pdata[namelen + 4] != '\0') {
572 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
573 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
580 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
581 if (!eal->ea.value.data) {
585 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
587 /* Ensure we're null terminated just in case we print the value. */
588 eal->ea.value.data[val_len] = '\0';
589 /* But don't count the null. */
590 eal->ea.value.length--;
593 *pbytes_used = 4 + namelen + 1 + val_len;
596 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
597 dump_data(10, eal->ea.value.data, eal->ea.value.length);
602 /****************************************************************************
603 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
604 ****************************************************************************/
606 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
608 struct ea_list *ea_list_head = NULL;
610 size_t bytes_used = 0;
612 while (offset < data_size) {
613 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
619 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
620 offset += bytes_used;
626 /****************************************************************************
627 Count the total EA size needed.
628 ****************************************************************************/
630 static size_t ea_list_size(struct ea_list *ealist)
633 struct ea_list *listp;
636 for (listp = ealist; listp; listp = listp->next) {
637 push_ascii_fstring(dos_ea_name, listp->ea.name);
638 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
640 /* Add on 4 for total length. */
648 /****************************************************************************
649 Return a union of EA's from a file list and a list of names.
650 The TALLOC context for the two lists *MUST* be identical as we steal
651 memory from one list to add to another. JRA.
652 ****************************************************************************/
654 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
656 struct ea_list *nlistp, *flistp;
658 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
659 for (flistp = file_list; flistp; flistp = flistp->next) {
660 if (strequal(nlistp->ea.name, flistp->ea.name)) {
666 /* Copy the data from this entry. */
667 nlistp->ea.flags = flistp->ea.flags;
668 nlistp->ea.value = flistp->ea.value;
671 nlistp->ea.flags = 0;
672 ZERO_STRUCT(nlistp->ea.value);
676 *total_ea_len = ea_list_size(name_list);
680 /****************************************************************************
681 Send the required number of replies back.
682 We assume all fields other than the data fields are
683 set correctly for the type of call.
684 HACK ! Always assumes smb_setup field is zero.
685 ****************************************************************************/
687 void send_trans2_replies(connection_struct *conn,
688 struct smb_request *req,
695 /* As we are using a protocol > LANMAN1 then the max_send
696 variable must have been set in the sessetupX call.
697 This takes precedence over the max_xmit field in the
698 global struct. These different max_xmit variables should
699 be merged as this is now too confusing */
701 int data_to_send = datasize;
702 int params_to_send = paramsize;
704 const char *pp = params;
705 const char *pd = pdata;
706 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
707 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
708 int data_alignment_offset = 0;
709 bool overflow = False;
711 /* Modify the data_to_send and datasize and set the error if
712 we're trying to send more than max_data_bytes. We still send
713 the part of the packet(s) that fit. Strange, but needed
716 if (max_data_bytes > 0 && datasize > max_data_bytes) {
717 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
718 max_data_bytes, datasize ));
719 datasize = data_to_send = max_data_bytes;
723 /* If there genuinely are no parameters or data to send just send the empty packet */
725 if(params_to_send == 0 && data_to_send == 0) {
726 reply_outbuf(req, 10, 0);
727 show_msg((char *)req->outbuf);
731 /* When sending params and data ensure that both are nicely aligned */
732 /* Only do this alignment when there is also data to send - else
733 can cause NT redirector problems. */
735 if (((params_to_send % 4) != 0) && (data_to_send != 0))
736 data_alignment_offset = 4 - (params_to_send % 4);
738 /* Space is bufsize minus Netbios over TCP header minus SMB header */
739 /* The alignment_offset is to align the param bytes on an even byte
740 boundary. NT 4.0 Beta needs this to work correctly. */
742 useable_space = max_send - (smb_size
745 + data_alignment_offset);
747 if (useable_space < 0) {
748 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
749 "= %d!!!", useable_space));
750 exit_server_cleanly("send_trans2_replies: Not enough space");
753 while (params_to_send || data_to_send) {
754 /* Calculate whether we will totally or partially fill this packet */
756 total_sent_thistime = params_to_send + data_to_send;
758 /* We can never send more than useable_space */
760 * Note that 'useable_space' does not include the alignment offsets,
761 * but we must include the alignment offsets in the calculation of
762 * the length of the data we send over the wire, as the alignment offsets
763 * are sent here. Fix from Marc_Jacobsen@hp.com.
766 total_sent_thistime = MIN(total_sent_thistime, useable_space);
768 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
769 + data_alignment_offset);
771 /* Set total params and data to be sent */
772 SSVAL(req->outbuf,smb_tprcnt,paramsize);
773 SSVAL(req->outbuf,smb_tdrcnt,datasize);
775 /* Calculate how many parameters and data we can fit into
776 * this packet. Parameters get precedence
779 params_sent_thistime = MIN(params_to_send,useable_space);
780 data_sent_thistime = useable_space - params_sent_thistime;
781 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
783 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
785 /* smb_proff is the offset from the start of the SMB header to the
786 parameter bytes, however the first 4 bytes of outbuf are
787 the Netbios over TCP header. Thus use smb_base() to subtract
788 them from the calculation */
790 SSVAL(req->outbuf,smb_proff,
791 ((smb_buf(req->outbuf)+alignment_offset)
792 - smb_base(req->outbuf)));
794 if(params_sent_thistime == 0)
795 SSVAL(req->outbuf,smb_prdisp,0);
797 /* Absolute displacement of param bytes sent in this packet */
798 SSVAL(req->outbuf,smb_prdisp,pp - params);
800 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
801 if(data_sent_thistime == 0) {
802 SSVAL(req->outbuf,smb_droff,0);
803 SSVAL(req->outbuf,smb_drdisp, 0);
805 /* The offset of the data bytes is the offset of the
806 parameter bytes plus the number of parameters being sent this time */
807 SSVAL(req->outbuf, smb_droff,
808 ((smb_buf(req->outbuf)+alignment_offset)
809 - smb_base(req->outbuf))
810 + params_sent_thistime + data_alignment_offset);
811 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
814 /* Initialize the padding for alignment */
816 if (alignment_offset != 0) {
817 memset(smb_buf(req->outbuf), 0, alignment_offset);
820 /* Copy the param bytes into the packet */
822 if(params_sent_thistime) {
823 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
824 params_sent_thistime);
827 /* Copy in the data bytes */
828 if(data_sent_thistime) {
829 if (data_alignment_offset != 0) {
830 memset((smb_buf(req->outbuf)+alignment_offset+
831 params_sent_thistime), 0,
832 data_alignment_offset);
834 memcpy(smb_buf(req->outbuf)+alignment_offset
835 +params_sent_thistime+data_alignment_offset,
836 pd,data_sent_thistime);
839 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
840 params_sent_thistime, data_sent_thistime, useable_space));
841 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
842 params_to_send, data_to_send, paramsize, datasize));
845 error_packet_set((char *)req->outbuf,
846 ERRDOS,ERRbufferoverflow,
847 STATUS_BUFFER_OVERFLOW,
851 /* Send the packet */
852 show_msg((char *)req->outbuf);
853 if (!srv_send_smb(smbd_server_fd(),
855 IS_CONN_ENCRYPTED(conn)))
856 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
858 TALLOC_FREE(req->outbuf);
860 pp += params_sent_thistime;
861 pd += data_sent_thistime;
863 params_to_send -= params_sent_thistime;
864 data_to_send -= data_sent_thistime;
867 if(params_to_send < 0 || data_to_send < 0) {
868 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
869 params_to_send, data_to_send));
877 /****************************************************************************
878 Reply to a TRANSACT2_OPEN.
879 ****************************************************************************/
881 static void call_trans2open(connection_struct *conn,
882 struct smb_request *req,
883 char **pparams, int total_params,
884 char **ppdata, int total_data,
885 unsigned int max_data_bytes)
887 char *params = *pparams;
888 char *pdata = *ppdata;
893 bool return_additional_info;
904 SMB_STRUCT_STAT sbuf;
907 struct ea_list *ea_list = NULL;
912 uint32 create_disposition;
913 uint32 create_options = 0;
914 TALLOC_CTX *ctx = talloc_tos();
917 * Ensure we have enough parameters to perform the operation.
920 if (total_params < 29) {
921 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
925 flags = SVAL(params, 0);
926 deny_mode = SVAL(params, 2);
927 open_attr = SVAL(params,6);
928 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
929 if (oplock_request) {
930 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
934 return_additional_info = BITSETW(params,0);
935 open_sattr = SVAL(params, 4);
936 open_time = make_unix_date3(params+8);
938 open_ofun = SVAL(params,12);
939 open_size = IVAL(params,14);
943 reply_doserror(req, ERRSRV, ERRaccess);
947 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
948 total_params - 28, STR_TERMINATE,
950 if (!NT_STATUS_IS_OK(status)) {
951 reply_nterror(req, status);
955 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
956 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
957 (unsigned int)open_ofun, open_size));
959 if (open_ofun == 0) {
960 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
964 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
969 reply_doserror(req, ERRDOS, ERRbadaccess);
973 /* Any data in this call is an EA list. */
974 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
975 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
979 if (total_data != 4) {
980 if (total_data < 10) {
981 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
985 if (IVAL(pdata,0) > total_data) {
986 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
987 IVAL(pdata,0), (unsigned int)total_data));
988 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
992 ea_list = read_ea_list(talloc_tos(), pdata + 4,
995 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
998 } else if (IVAL(pdata,0) != 4) {
999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1003 status = create_file(conn, /* conn */
1005 0, /* root_dir_fid */
1007 access_mask, /* access_mask */
1008 share_mode, /* share_access */
1009 create_disposition, /* create_disposition*/
1010 create_options, /* create_options */
1011 open_attr, /* file_attributes */
1012 oplock_request, /* oplock_request */
1013 open_size, /* allocation_size */
1015 ea_list, /* ea_list */
1017 &smb_action, /* pinfo */
1020 if (!NT_STATUS_IS_OK(status)) {
1021 if (open_was_deferred(req->mid)) {
1022 /* We have re-scheduled this call. */
1025 reply_openerror(req, status);
1029 size = get_file_size(sbuf);
1030 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1031 mtime = sbuf.st_mtime;
1032 inode = sbuf.st_ino;
1034 close_file(fsp,ERROR_CLOSE);
1035 reply_doserror(req, ERRDOS,ERRnoaccess);
1039 /* Realloc the size of parameters and data we will return */
1040 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1041 if(*pparams == NULL ) {
1042 reply_nterror(req, NT_STATUS_NO_MEMORY);
1047 SSVAL(params,0,fsp->fnum);
1048 SSVAL(params,2,fattr);
1049 srv_put_dos_date2(params,4, mtime);
1050 SIVAL(params,8, (uint32)size);
1051 SSVAL(params,12,deny_mode);
1052 SSVAL(params,14,0); /* open_type - file or directory. */
1053 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1055 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1056 smb_action |= EXTENDED_OPLOCK_GRANTED;
1059 SSVAL(params,18,smb_action);
1062 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1064 SIVAL(params,20,inode);
1065 SSVAL(params,24,0); /* Padding. */
1067 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1068 SIVAL(params, 26, ea_size);
1070 SIVAL(params, 26, 0);
1073 /* Send the required number of replies */
1074 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1077 /*********************************************************
1078 Routine to check if a given string matches exactly.
1079 as a special case a mask of "." does NOT match. That
1080 is required for correct wildcard semantics
1081 Case can be significant or not.
1082 **********************************************************/
1084 static bool exact_match(connection_struct *conn,
1088 if (mask[0] == '.' && mask[1] == 0)
1090 if (conn->case_sensitive)
1091 return strcmp(str,mask)==0;
1092 if (StrCaseCmp(str,mask) != 0) {
1095 if (dptr_has_wild(conn->dirptr)) {
1101 /****************************************************************************
1102 Return the filetype for UNIX extensions.
1103 ****************************************************************************/
1105 static uint32 unix_filetype(mode_t mode)
1108 return UNIX_TYPE_FILE;
1109 else if(S_ISDIR(mode))
1110 return UNIX_TYPE_DIR;
1112 else if(S_ISLNK(mode))
1113 return UNIX_TYPE_SYMLINK;
1116 else if(S_ISCHR(mode))
1117 return UNIX_TYPE_CHARDEV;
1120 else if(S_ISBLK(mode))
1121 return UNIX_TYPE_BLKDEV;
1124 else if(S_ISFIFO(mode))
1125 return UNIX_TYPE_FIFO;
1128 else if(S_ISSOCK(mode))
1129 return UNIX_TYPE_SOCKET;
1132 DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
1133 return UNIX_TYPE_UNKNOWN;
1136 /****************************************************************************
1137 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1138 ****************************************************************************/
1140 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1142 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1143 SMB_STRUCT_STAT *psbuf,
1145 enum perm_type ptype,
1150 if (perms == SMB_MODE_NO_CHANGE) {
1151 if (!VALID_STAT(*psbuf)) {
1152 return NT_STATUS_INVALID_PARAMETER;
1154 *ret_perms = psbuf->st_mode;
1155 return NT_STATUS_OK;
1159 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1160 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1161 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1162 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1163 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1164 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1165 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1166 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1167 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1169 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1172 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1175 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1180 /* Apply mode mask */
1181 ret &= lp_create_mask(SNUM(conn));
1182 /* Add in force bits */
1183 ret |= lp_force_create_mode(SNUM(conn));
1186 ret &= lp_dir_mask(SNUM(conn));
1187 /* Add in force bits */
1188 ret |= lp_force_dir_mode(SNUM(conn));
1190 case PERM_EXISTING_FILE:
1191 /* Apply mode mask */
1192 ret &= lp_security_mask(SNUM(conn));
1193 /* Add in force bits */
1194 ret |= lp_force_security_mode(SNUM(conn));
1196 case PERM_EXISTING_DIR:
1197 /* Apply mode mask */
1198 ret &= lp_dir_security_mask(SNUM(conn));
1199 /* Add in force bits */
1200 ret |= lp_force_dir_security_mode(SNUM(conn));
1205 return NT_STATUS_OK;
1208 /****************************************************************************
1209 Needed to show the msdfs symlinks as directories. Modifies psbuf
1210 to be a directory if it's a msdfs link.
1211 ****************************************************************************/
1213 static bool check_msdfs_link(connection_struct *conn,
1214 const char *pathname,
1215 SMB_STRUCT_STAT *psbuf)
1217 int saved_errno = errno;
1218 if(lp_host_msdfs() &&
1219 lp_msdfs_root(SNUM(conn)) &&
1220 is_msdfs_link(conn, pathname, psbuf)) {
1222 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1225 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1226 errno = saved_errno;
1229 errno = saved_errno;
1234 /****************************************************************************
1235 Get a level dependent lanman2 dir entry.
1236 ****************************************************************************/
1238 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1239 connection_struct *conn,
1241 const char *path_mask,
1244 int requires_resume_key,
1250 int space_remaining,
1252 bool *got_exact_match,
1253 int *last_entry_off,
1254 struct ea_list *name_list)
1258 SMB_STRUCT_STAT sbuf;
1259 const char *mask = NULL;
1260 char *pathreal = NULL;
1261 const char *fname = NULL;
1262 char *p, *q, *pdata = *ppdata;
1266 SMB_OFF_T file_size = 0;
1267 SMB_BIG_UINT allocation_size = 0;
1269 struct timespec mdate_ts, adate_ts, create_date_ts;
1270 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1272 char *last_entry_ptr;
1274 uint32 nt_extmode; /* Used for NT connections instead of mode */
1275 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1276 bool check_mangled_names = lp_manglednames(conn->params);
1277 char mangled_name[13]; /* mangled 8.3 name. */
1279 *out_of_space = False;
1280 *got_exact_match = False;
1282 ZERO_STRUCT(mdate_ts);
1283 ZERO_STRUCT(adate_ts);
1284 ZERO_STRUCT(create_date_ts);
1286 if (!conn->dirptr) {
1290 p = strrchr_m(path_mask,'/');
1293 mask = talloc_strdup(ctx,"*.*");
1303 bool ms_dfs_link = False;
1305 /* Needed if we run out of space */
1306 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1307 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1310 * Due to bugs in NT client redirectors we are not using
1311 * resume keys any more - set them to zero.
1312 * Check out the related comments in findfirst/findnext.
1318 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1319 (long)conn->dirptr,curr_dirpos));
1326 * fname may get mangled, dname is never mangled.
1327 * Whenever we're accessing the filesystem we use
1328 * pathreal which is composed from dname.
1334 /* Mangle fname if it's an illegal name. */
1335 if (mangle_must_mangle(dname,conn->params)) {
1336 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1337 continue; /* Error - couldn't mangle. */
1339 fname = mangled_name;
1342 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1343 got_match = mask_match(fname, mask, conn->case_sensitive);
1346 if(!got_match && check_mangled_names &&
1347 !mangle_is_8_3(fname, False, conn->params)) {
1349 * It turns out that NT matches wildcards against
1350 * both long *and* short names. This may explain some
1351 * of the wildcard wierdness from old DOS clients
1352 * that some people have been seeing.... JRA.
1354 /* Force the mangling into 8.3. */
1355 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1356 continue; /* Error - couldn't mangle. */
1359 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1360 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1365 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1367 if (dont_descend && !isdots) {
1373 pathreal = talloc_asprintf(ctx,
1378 pathreal = talloc_asprintf(ctx,
1388 if (INFO_LEVEL_IS_UNIX(info_level)) {
1389 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1390 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1391 pathreal,strerror(errno)));
1392 TALLOC_FREE(pathreal);
1395 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1396 /* Needed to show the msdfs symlinks as
1399 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1401 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1402 pathreal,strerror(errno)));
1403 TALLOC_FREE(pathreal);
1409 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1411 mode = dos_mode(conn,pathreal,&sbuf);
1414 if (!dir_check_ftype(conn,mode,dirtype)) {
1415 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1416 TALLOC_FREE(pathreal);
1420 if (!(mode & aDIR)) {
1421 file_size = get_file_size(sbuf);
1423 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1425 mdate_ts = get_mtimespec(&sbuf);
1426 adate_ts = get_atimespec(&sbuf);
1427 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1429 if (ask_sharemode) {
1430 struct timespec write_time_ts;
1431 struct file_id fileid;
1433 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1434 get_file_infos(fileid, NULL, &write_time_ts);
1435 if (!null_timespec(write_time_ts)) {
1436 mdate_ts = write_time_ts;
1440 if (lp_dos_filetime_resolution(SNUM(conn))) {
1441 dos_filetime_timespec(&create_date_ts);
1442 dos_filetime_timespec(&mdate_ts);
1443 dos_filetime_timespec(&adate_ts);
1446 create_date = convert_timespec_to_time_t(create_date_ts);
1447 mdate = convert_timespec_to_time_t(mdate_ts);
1448 adate = convert_timespec_to_time_t(adate_ts);
1450 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1454 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1461 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1463 switch (info_level) {
1464 case SMB_FIND_INFO_STANDARD:
1465 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1466 if(requires_resume_key) {
1470 srv_put_dos_date2(p,0,create_date);
1471 srv_put_dos_date2(p,4,adate);
1472 srv_put_dos_date2(p,8,mdate);
1473 SIVAL(p,12,(uint32)file_size);
1474 SIVAL(p,16,(uint32)allocation_size);
1478 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1479 p += ucs2_align(base_data, p, 0);
1481 len = srvstr_push(base_data, flags2, p,
1482 fname, PTR_DIFF(end_data, p),
1484 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1486 SCVAL(nameptr, -1, len - 2);
1488 SCVAL(nameptr, -1, 0);
1492 SCVAL(nameptr, -1, len - 1);
1494 SCVAL(nameptr, -1, 0);
1500 case SMB_FIND_EA_SIZE:
1501 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1502 if(requires_resume_key) {
1506 srv_put_dos_date2(p,0,create_date);
1507 srv_put_dos_date2(p,4,adate);
1508 srv_put_dos_date2(p,8,mdate);
1509 SIVAL(p,12,(uint32)file_size);
1510 SIVAL(p,16,(uint32)allocation_size);
1513 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1514 SIVAL(p,22,ea_size); /* Extended attributes */
1518 len = srvstr_push(base_data, flags2,
1519 p, fname, PTR_DIFF(end_data, p),
1520 STR_TERMINATE | STR_NOALIGN);
1521 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1534 SCVAL(nameptr,0,len);
1536 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1539 case SMB_FIND_EA_LIST:
1541 struct ea_list *file_list = NULL;
1544 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1548 if(requires_resume_key) {
1552 srv_put_dos_date2(p,0,create_date);
1553 srv_put_dos_date2(p,4,adate);
1554 srv_put_dos_date2(p,8,mdate);
1555 SIVAL(p,12,(uint32)file_size);
1556 SIVAL(p,16,(uint32)allocation_size);
1558 p += 22; /* p now points to the EA area. */
1560 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1561 name_list = ea_list_union(name_list, file_list, &ea_len);
1563 /* We need to determine if this entry will fit in the space available. */
1564 /* Max string size is 255 bytes. */
1565 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1566 /* Move the dirptr back to prev_dirpos */
1567 dptr_SeekDir(conn->dirptr, prev_dirpos);
1568 *out_of_space = True;
1569 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1570 return False; /* Not finished - just out of space */
1573 /* Push the ea_data followed by the name. */
1574 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1576 len = srvstr_push(base_data, flags2,
1577 p + 1, fname, PTR_DIFF(end_data, p+1),
1578 STR_TERMINATE | STR_NOALIGN);
1579 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1592 SCVAL(nameptr,0,len);
1594 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1598 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1599 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1600 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1602 SIVAL(p,0,reskey); p += 4;
1603 put_long_date_timespec(p,create_date_ts); p += 8;
1604 put_long_date_timespec(p,adate_ts); p += 8;
1605 put_long_date_timespec(p,mdate_ts); p += 8;
1606 put_long_date_timespec(p,mdate_ts); p += 8;
1607 SOFF_T(p,0,file_size); p += 8;
1608 SOFF_T(p,0,allocation_size); p += 8;
1609 SIVAL(p,0,nt_extmode); p += 4;
1610 q = p; p += 4; /* q is placeholder for name length. */
1612 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1613 SIVAL(p,0,ea_size); /* Extended attributes */
1616 /* Clear the short name buffer. This is
1617 * IMPORTANT as not doing so will trigger
1618 * a Win2k client bug. JRA.
1620 if (!was_8_3 && check_mangled_names) {
1621 if (!name_to_8_3(fname,mangled_name,True,
1623 /* Error - mangle failed ! */
1624 memset(mangled_name,'\0',12);
1626 mangled_name[12] = 0;
1627 len = srvstr_push(base_data, flags2,
1628 p+2, mangled_name, 24,
1629 STR_UPPER|STR_UNICODE);
1631 memset(p + 2 + len,'\0',24 - len);
1638 len = srvstr_push(base_data, flags2, p,
1639 fname, PTR_DIFF(end_data, p),
1640 STR_TERMINATE_ASCII);
1643 SIVAL(p,0,0); /* Ensure any padding is null. */
1644 len = PTR_DIFF(p, pdata);
1645 len = (len + 3) & ~3;
1650 case SMB_FIND_FILE_DIRECTORY_INFO:
1651 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1653 SIVAL(p,0,reskey); p += 4;
1654 put_long_date_timespec(p,create_date_ts); p += 8;
1655 put_long_date_timespec(p,adate_ts); p += 8;
1656 put_long_date_timespec(p,mdate_ts); p += 8;
1657 put_long_date_timespec(p,mdate_ts); p += 8;
1658 SOFF_T(p,0,file_size); p += 8;
1659 SOFF_T(p,0,allocation_size); p += 8;
1660 SIVAL(p,0,nt_extmode); p += 4;
1661 len = srvstr_push(base_data, flags2,
1662 p + 4, fname, PTR_DIFF(end_data, p+4),
1663 STR_TERMINATE_ASCII);
1666 SIVAL(p,0,0); /* Ensure any padding is null. */
1667 len = PTR_DIFF(p, pdata);
1668 len = (len + 3) & ~3;
1673 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1674 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1676 SIVAL(p,0,reskey); p += 4;
1677 put_long_date_timespec(p,create_date_ts); p += 8;
1678 put_long_date_timespec(p,adate_ts); p += 8;
1679 put_long_date_timespec(p,mdate_ts); p += 8;
1680 put_long_date_timespec(p,mdate_ts); p += 8;
1681 SOFF_T(p,0,file_size); p += 8;
1682 SOFF_T(p,0,allocation_size); p += 8;
1683 SIVAL(p,0,nt_extmode); p += 4;
1684 q = p; p += 4; /* q is placeholder for name length. */
1686 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1687 SIVAL(p,0,ea_size); /* Extended attributes */
1690 len = srvstr_push(base_data, flags2, p,
1691 fname, PTR_DIFF(end_data, p),
1692 STR_TERMINATE_ASCII);
1696 SIVAL(p,0,0); /* Ensure any padding is null. */
1697 len = PTR_DIFF(p, pdata);
1698 len = (len + 3) & ~3;
1703 case SMB_FIND_FILE_NAMES_INFO:
1704 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1706 SIVAL(p,0,reskey); p += 4;
1708 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1709 acl on a dir (tridge) */
1710 len = srvstr_push(base_data, flags2, p,
1711 fname, PTR_DIFF(end_data, p),
1712 STR_TERMINATE_ASCII);
1715 SIVAL(p,0,0); /* Ensure any padding is null. */
1716 len = PTR_DIFF(p, pdata);
1717 len = (len + 3) & ~3;
1722 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1723 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1725 SIVAL(p,0,reskey); p += 4;
1726 put_long_date_timespec(p,create_date_ts); p += 8;
1727 put_long_date_timespec(p,adate_ts); p += 8;
1728 put_long_date_timespec(p,mdate_ts); p += 8;
1729 put_long_date_timespec(p,mdate_ts); p += 8;
1730 SOFF_T(p,0,file_size); p += 8;
1731 SOFF_T(p,0,allocation_size); p += 8;
1732 SIVAL(p,0,nt_extmode); p += 4;
1733 q = p; p += 4; /* q is placeholder for name length. */
1735 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1736 SIVAL(p,0,ea_size); /* Extended attributes */
1739 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1740 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1741 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1742 len = srvstr_push(base_data, flags2, p,
1743 fname, PTR_DIFF(end_data, p),
1744 STR_TERMINATE_ASCII);
1747 SIVAL(p,0,0); /* Ensure any padding is null. */
1748 len = PTR_DIFF(p, pdata);
1749 len = (len + 3) & ~3;
1754 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1755 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1756 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1758 SIVAL(p,0,reskey); p += 4;
1759 put_long_date_timespec(p,create_date_ts); p += 8;
1760 put_long_date_timespec(p,adate_ts); p += 8;
1761 put_long_date_timespec(p,mdate_ts); p += 8;
1762 put_long_date_timespec(p,mdate_ts); p += 8;
1763 SOFF_T(p,0,file_size); p += 8;
1764 SOFF_T(p,0,allocation_size); p += 8;
1765 SIVAL(p,0,nt_extmode); p += 4;
1766 q = p; p += 4; /* q is placeholder for name length */
1768 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1769 SIVAL(p,0,ea_size); /* Extended attributes */
1772 /* Clear the short name buffer. This is
1773 * IMPORTANT as not doing so will trigger
1774 * a Win2k client bug. JRA.
1776 if (!was_8_3 && check_mangled_names) {
1777 if (!name_to_8_3(fname,mangled_name,True,
1779 /* Error - mangle failed ! */
1780 memset(mangled_name,'\0',12);
1782 mangled_name[12] = 0;
1783 len = srvstr_push(base_data, flags2,
1784 p+2, mangled_name, 24,
1785 STR_UPPER|STR_UNICODE);
1788 memset(p + 2 + len,'\0',24 - len);
1795 SSVAL(p,0,0); p += 2; /* Reserved ? */
1796 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1797 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1798 len = srvstr_push(base_data, flags2, p,
1799 fname, PTR_DIFF(end_data, p),
1800 STR_TERMINATE_ASCII);
1803 SIVAL(p,0,0); /* Ensure any padding is null. */
1804 len = PTR_DIFF(p, pdata);
1805 len = (len + 3) & ~3;
1810 /* CIFS UNIX Extension. */
1812 case SMB_FIND_FILE_UNIX:
1813 case SMB_FIND_FILE_UNIX_INFO2:
1815 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1817 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1819 if (info_level == SMB_FIND_FILE_UNIX) {
1820 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1821 p = store_file_unix_basic(conn, p,
1823 len = srvstr_push(base_data, flags2, p,
1824 fname, PTR_DIFF(end_data, p),
1827 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1828 p = store_file_unix_basic_info2(conn, p,
1832 len = srvstr_push(base_data, flags2, p, fname,
1833 PTR_DIFF(end_data, p), 0);
1834 SIVAL(nameptr, 0, len);
1838 SIVAL(p,0,0); /* Ensure any padding is null. */
1840 len = PTR_DIFF(p, pdata);
1841 len = (len + 3) & ~3;
1842 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1844 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1853 if (PTR_DIFF(p,pdata) > space_remaining) {
1854 /* Move the dirptr back to prev_dirpos */
1855 dptr_SeekDir(conn->dirptr, prev_dirpos);
1856 *out_of_space = True;
1857 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1858 return False; /* Not finished - just out of space */
1861 /* Setup the last entry pointer, as an offset from base_data */
1862 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1863 /* Advance the data pointer to the next slot */
1869 /****************************************************************************
1870 Reply to a TRANS2_FINDFIRST.
1871 ****************************************************************************/
1873 static void call_trans2findfirst(connection_struct *conn,
1874 struct smb_request *req,
1875 char **pparams, int total_params,
1876 char **ppdata, int total_data,
1877 unsigned int max_data_bytes)
1879 /* We must be careful here that we don't return more than the
1880 allowed number of data bytes. If this means returning fewer than
1881 maxentries then so be it. We assume that the redirector has
1882 enough room for the fixed number of parameter bytes it has
1884 char *params = *pparams;
1885 char *pdata = *ppdata;
1889 uint16 findfirst_flags;
1890 bool close_after_first;
1892 bool requires_resume_key;
1894 char *directory = NULL;
1895 const char *mask = NULL;
1897 int last_entry_off=0;
1901 bool finished = False;
1902 bool dont_descend = False;
1903 bool out_of_space = False;
1904 int space_remaining;
1905 bool mask_contains_wcard = False;
1906 SMB_STRUCT_STAT sbuf;
1907 struct ea_list *ea_list = NULL;
1908 NTSTATUS ntstatus = NT_STATUS_OK;
1909 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1910 TALLOC_CTX *ctx = talloc_tos();
1912 if (total_params < 13) {
1913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1917 dirtype = SVAL(params,0);
1918 maxentries = SVAL(params,2);
1919 findfirst_flags = SVAL(params,4);
1920 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1921 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1922 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1923 info_level = SVAL(params,6);
1925 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1926 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1927 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1928 info_level, max_data_bytes));
1931 /* W2K3 seems to treat zero as 1. */
1935 switch (info_level) {
1936 case SMB_FIND_INFO_STANDARD:
1937 case SMB_FIND_EA_SIZE:
1938 case SMB_FIND_EA_LIST:
1939 case SMB_FIND_FILE_DIRECTORY_INFO:
1940 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1941 case SMB_FIND_FILE_NAMES_INFO:
1942 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1943 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1944 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1946 case SMB_FIND_FILE_UNIX:
1947 case SMB_FIND_FILE_UNIX_INFO2:
1948 /* Always use filesystem for UNIX mtime query. */
1949 ask_sharemode = false;
1950 if (!lp_unix_extensions()) {
1951 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1956 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1960 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1961 params+12, total_params - 12,
1962 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1963 if (!NT_STATUS_IS_OK(ntstatus)) {
1964 reply_nterror(req, ntstatus);
1968 ntstatus = resolve_dfspath_wcard(ctx, conn,
1969 req->flags2 & FLAGS2_DFS_PATHNAMES,
1972 &mask_contains_wcard);
1973 if (!NT_STATUS_IS_OK(ntstatus)) {
1974 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1975 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1976 ERRSRV, ERRbadpath);
1979 reply_nterror(req, ntstatus);
1983 ntstatus = unix_convert(ctx, conn, directory, True, &directory, NULL, &sbuf);
1984 if (!NT_STATUS_IS_OK(ntstatus)) {
1985 reply_nterror(req, ntstatus);
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')) {
2000 mask_contains_wcard = True;
2004 directory = talloc_strdup(talloc_tos(), "./");
2006 reply_nterror(req, NT_STATUS_NO_MEMORY);
2014 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2016 if (info_level == SMB_FIND_EA_LIST) {
2019 if (total_data < 4) {
2020 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2024 ea_size = IVAL(pdata,0);
2025 if (ea_size != total_data) {
2026 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2027 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2032 if (!lp_ea_support(SNUM(conn))) {
2033 reply_doserror(req, ERRDOS, ERReasnotsupported);
2037 /* Pull out the list of names. */
2038 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2040 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2045 *ppdata = (char *)SMB_REALLOC(
2046 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2047 if(*ppdata == NULL ) {
2048 reply_nterror(req, NT_STATUS_NO_MEMORY);
2052 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2054 /* Realloc the params space */
2055 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2056 if (*pparams == NULL) {
2057 reply_nterror(req, NT_STATUS_NO_MEMORY);
2062 /* Save the wildcard match and attribs we are using on this directory -
2063 needed as lanman2 assumes these are being saved between calls */
2065 ntstatus = dptr_create(conn,
2071 mask_contains_wcard,
2075 if (!NT_STATUS_IS_OK(ntstatus)) {
2076 reply_nterror(req, ntstatus);
2080 dptr_num = dptr_dnum(conn->dirptr);
2081 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2083 /* We don't need to check for VOL here as this is returned by
2084 a different TRANS2 call. */
2086 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2087 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2088 dont_descend = True;
2091 space_remaining = max_data_bytes;
2092 out_of_space = False;
2094 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2095 bool got_exact_match = False;
2097 /* this is a heuristic to avoid seeking the dirptr except when
2098 absolutely necessary. It allows for a filename of about 40 chars */
2099 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2100 out_of_space = True;
2103 finished = !get_lanman2_dir_entry(ctx,
2106 mask,dirtype,info_level,
2107 requires_resume_key,dont_descend,
2110 space_remaining, &out_of_space,
2112 &last_entry_off, ea_list);
2115 if (finished && out_of_space)
2118 if (!finished && !out_of_space)
2122 * As an optimisation if we know we aren't looking
2123 * for a wildcard name (ie. the name matches the wildcard exactly)
2124 * then we can finish on any (first) match.
2125 * This speeds up large directory searches. JRA.
2131 /* Ensure space_remaining never goes -ve. */
2132 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2133 space_remaining = 0;
2134 out_of_space = true;
2136 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2140 /* Check if we can close the dirptr */
2141 if(close_after_first || (finished && close_if_end)) {
2142 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2143 dptr_close(&dptr_num);
2147 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2148 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2149 * the protocol level is less than NT1. Tested with smbclient. JRA.
2150 * This should fix the OS/2 client bug #2335.
2153 if(numentries == 0) {
2154 dptr_close(&dptr_num);
2155 if (Protocol < PROTOCOL_NT1) {
2156 reply_doserror(req, ERRDOS, ERRnofiles);
2159 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2160 ERRDOS, ERRbadfile);
2165 /* At this point pdata points to numentries directory entries. */
2167 /* Set up the return parameter block */
2168 SSVAL(params,0,dptr_num);
2169 SSVAL(params,2,numentries);
2170 SSVAL(params,4,finished);
2171 SSVAL(params,6,0); /* Never an EA error */
2172 SSVAL(params,8,last_entry_off);
2174 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2177 if ((! *directory) && dptr_path(dptr_num)) {
2178 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2180 reply_nterror(req, NT_STATUS_NO_MEMORY);
2184 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2185 smb_fn_name(CVAL(req->inbuf,smb_com)),
2186 mask, directory, dirtype, numentries ) );
2189 * Force a name mangle here to ensure that the
2190 * mask as an 8.3 name is top of the mangled cache.
2191 * The reasons for this are subtle. Don't remove
2192 * this code unless you know what you are doing
2193 * (see PR#13758). JRA.
2196 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2197 char mangled_name[13];
2198 name_to_8_3(mask, mangled_name, True, conn->params);
2204 /****************************************************************************
2205 Reply to a TRANS2_FINDNEXT.
2206 ****************************************************************************/
2208 static void call_trans2findnext(connection_struct *conn,
2209 struct smb_request *req,
2210 char **pparams, int total_params,
2211 char **ppdata, int total_data,
2212 unsigned int max_data_bytes)
2214 /* We must be careful here that we don't return more than the
2215 allowed number of data bytes. If this means returning fewer than
2216 maxentries then so be it. We assume that the redirector has
2217 enough room for the fixed number of parameter bytes it has
2219 char *params = *pparams;
2220 char *pdata = *ppdata;
2226 uint16 findnext_flags;
2227 bool close_after_request;
2229 bool requires_resume_key;
2231 bool mask_contains_wcard = False;
2232 char *resume_name = NULL;
2233 const char *mask = NULL;
2234 const char *directory = NULL;
2238 int i, last_entry_off=0;
2239 bool finished = False;
2240 bool dont_descend = False;
2241 bool out_of_space = False;
2242 int space_remaining;
2243 struct ea_list *ea_list = NULL;
2244 NTSTATUS ntstatus = NT_STATUS_OK;
2245 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2246 TALLOC_CTX *ctx = talloc_tos();
2248 if (total_params < 13) {
2249 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2253 dptr_num = SVAL(params,0);
2254 maxentries = SVAL(params,2);
2255 info_level = SVAL(params,4);
2256 resume_key = IVAL(params,6);
2257 findnext_flags = SVAL(params,10);
2258 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2259 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2260 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2261 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2263 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2265 total_params - 12, STR_TERMINATE, &ntstatus,
2266 &mask_contains_wcard);
2267 if (!NT_STATUS_IS_OK(ntstatus)) {
2268 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2269 complain (it thinks we're asking for the directory above the shared
2270 path or an invalid name). Catch this as the resume name is only compared, never used in
2271 a file access. JRA. */
2272 srvstr_pull_talloc(ctx, params, req->flags2,
2273 &resume_name, params+12,
2277 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2278 reply_nterror(req, ntstatus);
2283 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2284 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2285 resume_key = %d resume name = %s continue=%d level = %d\n",
2286 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2287 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2290 /* W2K3 seems to treat zero as 1. */
2294 switch (info_level) {
2295 case SMB_FIND_INFO_STANDARD:
2296 case SMB_FIND_EA_SIZE:
2297 case SMB_FIND_EA_LIST:
2298 case SMB_FIND_FILE_DIRECTORY_INFO:
2299 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2300 case SMB_FIND_FILE_NAMES_INFO:
2301 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2302 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2303 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2305 case SMB_FIND_FILE_UNIX:
2306 case SMB_FIND_FILE_UNIX_INFO2:
2307 /* Always use filesystem for UNIX mtime query. */
2308 ask_sharemode = false;
2309 if (!lp_unix_extensions()) {
2310 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2315 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2319 if (info_level == SMB_FIND_EA_LIST) {
2322 if (total_data < 4) {
2323 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2327 ea_size = IVAL(pdata,0);
2328 if (ea_size != total_data) {
2329 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2330 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2331 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2335 if (!lp_ea_support(SNUM(conn))) {
2336 reply_doserror(req, ERRDOS, ERReasnotsupported);
2340 /* Pull out the list of names. */
2341 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2348 *ppdata = (char *)SMB_REALLOC(
2349 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2350 if(*ppdata == NULL) {
2351 reply_nterror(req, NT_STATUS_NO_MEMORY);
2356 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2358 /* Realloc the params space */
2359 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2360 if(*pparams == NULL ) {
2361 reply_nterror(req, NT_STATUS_NO_MEMORY);
2367 /* Check that the dptr is valid */
2368 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2369 reply_doserror(req, ERRDOS, ERRnofiles);
2373 string_set(&conn->dirpath,dptr_path(dptr_num));
2375 /* Get the wildcard mask from the dptr */
2376 if((p = dptr_wcard(dptr_num))== NULL) {
2377 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2378 reply_doserror(req, ERRDOS, ERRnofiles);
2383 directory = conn->dirpath;
2385 /* Get the attr mask from the dptr */
2386 dirtype = dptr_attr(dptr_num);
2388 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2389 dptr_num, mask, dirtype,
2391 dptr_TellDir(conn->dirptr)));
2393 /* We don't need to check for VOL here as this is returned by
2394 a different TRANS2 call. */
2396 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2397 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2398 dont_descend = True;
2401 space_remaining = max_data_bytes;
2402 out_of_space = False;
2405 * Seek to the correct position. We no longer use the resume key but
2406 * depend on the last file name instead.
2409 if(*resume_name && !continue_bit) {
2412 long current_pos = 0;
2414 * Remember, name_to_8_3 is called by
2415 * get_lanman2_dir_entry(), so the resume name
2416 * could be mangled. Ensure we check the unmangled name.
2419 if (mangle_is_mangled(resume_name, conn->params)) {
2420 char *new_resume_name = NULL;
2421 mangle_lookup_name_from_8_3(ctx,
2425 if (new_resume_name) {
2426 resume_name = new_resume_name;
2431 * Fix for NT redirector problem triggered by resume key indexes
2432 * changing between directory scans. We now return a resume key of 0
2433 * and instead look for the filename to continue from (also given
2434 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2435 * findfirst/findnext (as is usual) then the directory pointer
2436 * should already be at the correct place.
2439 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2440 } /* end if resume_name && !continue_bit */
2442 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2443 bool got_exact_match = False;
2445 /* this is a heuristic to avoid seeking the dirptr except when
2446 absolutely necessary. It allows for a filename of about 40 chars */
2447 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2448 out_of_space = True;
2451 finished = !get_lanman2_dir_entry(ctx,
2454 mask,dirtype,info_level,
2455 requires_resume_key,dont_descend,
2458 space_remaining, &out_of_space,
2460 &last_entry_off, ea_list);
2463 if (finished && out_of_space)
2466 if (!finished && !out_of_space)
2470 * As an optimisation if we know we aren't looking
2471 * for a wildcard name (ie. the name matches the wildcard exactly)
2472 * then we can finish on any (first) match.
2473 * This speeds up large directory searches. JRA.
2479 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2482 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2483 smb_fn_name(CVAL(req->inbuf,smb_com)),
2484 mask, directory, dirtype, numentries ) );
2486 /* Check if we can close the dirptr */
2487 if(close_after_request || (finished && close_if_end)) {
2488 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2489 dptr_close(&dptr_num); /* This frees up the saved mask */
2492 /* Set up the return parameter block */
2493 SSVAL(params,0,numentries);
2494 SSVAL(params,2,finished);
2495 SSVAL(params,4,0); /* Never an EA error */
2496 SSVAL(params,6,last_entry_off);
2498 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2504 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2506 E_md4hash(lp_servicename(SNUM(conn)),objid);
2510 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2512 SMB_ASSERT(extended_info != NULL);
2514 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2515 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2516 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2517 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2518 #ifdef SAMBA_VERSION_REVISION
2519 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2521 extended_info->samba_subversion = 0;
2522 #ifdef SAMBA_VERSION_RC_RELEASE
2523 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2525 #ifdef SAMBA_VERSION_PRE_RELEASE
2526 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2529 #ifdef SAMBA_VERSION_VENDOR_PATCH
2530 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2532 extended_info->samba_gitcommitdate = 0;
2533 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2534 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2537 memset(extended_info->samba_version_string, 0,
2538 sizeof(extended_info->samba_version_string));
2540 snprintf (extended_info->samba_version_string,
2541 sizeof(extended_info->samba_version_string),
2542 "%s", samba_version_string());
2545 /****************************************************************************
2546 Reply to a TRANS2_QFSINFO (query filesystem info).
2547 ****************************************************************************/
2549 static void call_trans2qfsinfo(connection_struct *conn,
2550 struct smb_request *req,
2551 char **pparams, int total_params,
2552 char **ppdata, int total_data,
2553 unsigned int max_data_bytes)
2555 char *pdata, *end_data;
2556 char *params = *pparams;
2560 const char *vname = volume_label(SNUM(conn));
2561 int snum = SNUM(conn);
2562 char *fstype = lp_fstype(SNUM(conn));
2563 uint32 additional_flags = 0;
2565 if (total_params < 2) {
2566 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2570 info_level = SVAL(params,0);
2573 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2574 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2575 "info level (0x%x) on IPC$.\n",
2576 (unsigned int)info_level));
2577 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2582 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2583 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2584 DEBUG(0,("call_trans2qfsinfo: encryption required "
2585 "and info level 0x%x sent.\n",
2586 (unsigned int)info_level));
2587 exit_server_cleanly("encryption required "
2593 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2595 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2596 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2597 reply_doserror(req, ERRSRV, ERRinvdevice);
2601 *ppdata = (char *)SMB_REALLOC(
2602 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2603 if (*ppdata == NULL ) {
2604 reply_nterror(req, NT_STATUS_NO_MEMORY);
2609 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2610 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2612 switch (info_level) {
2613 case SMB_INFO_ALLOCATION:
2615 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2617 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2618 reply_unixerror(req, ERRHRD, ERRgeneral);
2622 block_size = lp_block_size(snum);
2623 if (bsize < block_size) {
2624 SMB_BIG_UINT factor = block_size/bsize;
2629 if (bsize > block_size) {
2630 SMB_BIG_UINT factor = bsize/block_size;
2635 bytes_per_sector = 512;
2636 sectors_per_unit = bsize/bytes_per_sector;
2638 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2639 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2640 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2642 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2643 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2644 SIVAL(pdata,l1_cUnit,dsize);
2645 SIVAL(pdata,l1_cUnitAvail,dfree);
2646 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2650 case SMB_INFO_VOLUME:
2651 /* Return volume name */
2653 * Add volume serial number - hash of a combination of
2654 * the called hostname and the service name.
2656 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2658 * Win2k3 and previous mess this up by sending a name length
2659 * one byte short. I believe only older clients (OS/2 Win9x) use
2660 * this call so try fixing this by adding a terminating null to
2661 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2665 pdata+l2_vol_szVolLabel, vname,
2666 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2667 STR_NOALIGN|STR_TERMINATE);
2668 SCVAL(pdata,l2_vol_cch,len);
2669 data_len = l2_vol_szVolLabel + len;
2670 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2671 (unsigned)st.st_ctime, len, vname));
2674 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2675 case SMB_FS_ATTRIBUTE_INFORMATION:
2677 additional_flags = 0;
2678 #if defined(HAVE_SYS_QUOTAS)
2679 additional_flags |= FILE_VOLUME_QUOTAS;
2682 if(lp_nt_acl_support(SNUM(conn))) {
2683 additional_flags |= FILE_PERSISTENT_ACLS;
2686 /* Capabilities are filled in at connection time through STATVFS call */
2687 additional_flags |= conn->fs_capabilities;
2689 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2690 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2691 additional_flags); /* FS ATTRIBUTES */
2693 SIVAL(pdata,4,255); /* Max filename component length */
2694 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2695 and will think we can't do long filenames */
2696 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2697 PTR_DIFF(end_data, pdata+12),
2700 data_len = 12 + len;
2703 case SMB_QUERY_FS_LABEL_INFO:
2704 case SMB_FS_LABEL_INFORMATION:
2705 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2706 PTR_DIFF(end_data, pdata+4), 0);
2711 case SMB_QUERY_FS_VOLUME_INFO:
2712 case SMB_FS_VOLUME_INFORMATION:
2715 * Add volume serial number - hash of a combination of
2716 * the called hostname and the service name.
2718 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2719 (str_checksum(get_local_machine_name())<<16));
2721 /* Max label len is 32 characters. */
2722 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2723 PTR_DIFF(end_data, pdata+18),
2725 SIVAL(pdata,12,len);
2728 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2729 (int)strlen(vname),vname, lp_servicename(snum)));
2732 case SMB_QUERY_FS_SIZE_INFO:
2733 case SMB_FS_SIZE_INFORMATION:
2735 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2737 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2738 reply_unixerror(req, ERRHRD, ERRgeneral);
2741 block_size = lp_block_size(snum);
2742 if (bsize < block_size) {
2743 SMB_BIG_UINT factor = block_size/bsize;
2748 if (bsize > block_size) {
2749 SMB_BIG_UINT factor = bsize/block_size;
2754 bytes_per_sector = 512;
2755 sectors_per_unit = bsize/bytes_per_sector;
2756 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2757 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2758 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2759 SBIG_UINT(pdata,0,dsize);
2760 SBIG_UINT(pdata,8,dfree);
2761 SIVAL(pdata,16,sectors_per_unit);
2762 SIVAL(pdata,20,bytes_per_sector);
2766 case SMB_FS_FULL_SIZE_INFORMATION:
2768 SMB_BIG_UINT dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2770 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (SMB_BIG_UINT)-1) {
2771 reply_unixerror(req, ERRHRD, ERRgeneral);
2774 block_size = lp_block_size(snum);
2775 if (bsize < block_size) {
2776 SMB_BIG_UINT factor = block_size/bsize;
2781 if (bsize > block_size) {
2782 SMB_BIG_UINT factor = bsize/block_size;
2787 bytes_per_sector = 512;
2788 sectors_per_unit = bsize/bytes_per_sector;
2789 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2790 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2791 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2792 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2793 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2794 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2795 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2796 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2800 case SMB_QUERY_FS_DEVICE_INFO:
2801 case SMB_FS_DEVICE_INFORMATION:
2803 SIVAL(pdata,0,0); /* dev type */
2804 SIVAL(pdata,4,0); /* characteristics */
2807 #ifdef HAVE_SYS_QUOTAS
2808 case SMB_FS_QUOTA_INFORMATION:
2810 * what we have to send --metze:
2812 * Unknown1: 24 NULL bytes
2813 * Soft Quota Treshold: 8 bytes seems like SMB_BIG_UINT or so
2814 * Hard Quota Limit: 8 bytes seems like SMB_BIG_UINT or so
2815 * Quota Flags: 2 byte :
2816 * Unknown3: 6 NULL bytes
2820 * details for Quota Flags:
2822 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2823 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2824 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2825 * 0x0001 Enable Quotas: enable quota for this fs
2829 /* we need to fake up a fsp here,
2830 * because its not send in this call
2833 SMB_NTQUOTA_STRUCT quotas;
2836 ZERO_STRUCT(quotas);
2842 if (conn->server_info->utok.uid != 0) {
2843 DEBUG(0,("set_user_quota: access_denied "
2844 "service [%s] user [%s]\n",
2845 lp_servicename(SNUM(conn)),
2846 conn->server_info->unix_name));
2847 reply_doserror(req, ERRDOS, ERRnoaccess);
2851 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2852 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2853 reply_doserror(req, ERRSRV, ERRerror);
2859 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2861 /* Unknown1 24 NULL bytes*/
2862 SBIG_UINT(pdata,0,(SMB_BIG_UINT)0);
2863 SBIG_UINT(pdata,8,(SMB_BIG_UINT)0);
2864 SBIG_UINT(pdata,16,(SMB_BIG_UINT)0);
2866 /* Default Soft Quota 8 bytes */
2867 SBIG_UINT(pdata,24,quotas.softlim);
2869 /* Default Hard Quota 8 bytes */
2870 SBIG_UINT(pdata,32,quotas.hardlim);
2872 /* Quota flag 2 bytes */
2873 SSVAL(pdata,40,quotas.qflags);
2875 /* Unknown3 6 NULL bytes */
2881 #endif /* HAVE_SYS_QUOTAS */
2882 case SMB_FS_OBJECTID_INFORMATION:
2884 unsigned char objid[16];
2885 struct smb_extended_info extended_info;
2886 memcpy(pdata,create_volume_objectid(conn, objid),16);
2887 samba_extended_info_version (&extended_info);
2888 SIVAL(pdata,16,extended_info.samba_magic);
2889 SIVAL(pdata,20,extended_info.samba_version);
2890 SIVAL(pdata,24,extended_info.samba_subversion);
2891 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2892 memcpy(pdata+36,extended_info.samba_version_string,28);
2898 * Query the version and capabilities of the CIFS UNIX extensions
2902 case SMB_QUERY_CIFS_UNIX_INFO:
2904 bool large_write = lp_min_receive_file_size() &&
2905 !srv_is_signing_active();
2906 bool large_read = !srv_is_signing_active();
2907 int encrypt_caps = 0;
2909 if (!lp_unix_extensions()) {
2910 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2914 switch (conn->encrypt_level) {
2920 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2923 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2924 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2925 large_write = false;
2931 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2932 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2934 /* We have POSIX ACLs, pathname, encryption,
2935 * large read/write, and locking capability. */
2937 SBIG_UINT(pdata,4,((SMB_BIG_UINT)(
2938 CIFS_UNIX_POSIX_ACLS_CAP|
2939 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2940 CIFS_UNIX_FCNTL_LOCKS_CAP|
2941 CIFS_UNIX_EXTATTR_CAP|
2942 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2944 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2946 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2950 case SMB_QUERY_POSIX_FS_INFO:
2953 vfs_statvfs_struct svfs;
2955 if (!lp_unix_extensions()) {
2956 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2960 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2964 SIVAL(pdata,0,svfs.OptimalTransferSize);
2965 SIVAL(pdata,4,svfs.BlockSize);
2966 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2967 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2968 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2969 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2970 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2971 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2972 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2974 } else if (rc == EOPNOTSUPP) {
2975 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2977 #endif /* EOPNOTSUPP */
2979 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2980 reply_doserror(req, ERRSRV, ERRerror);
2986 case SMB_QUERY_POSIX_WHOAMI:
2992 if (!lp_unix_extensions()) {
2993 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2997 if (max_data_bytes < 40) {
2998 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3002 /* We ARE guest if global_sid_Builtin_Guests is
3003 * in our list of SIDs.
3005 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3006 conn->server_info->ptok)) {
3007 flags |= SMB_WHOAMI_GUEST;
3010 /* We are NOT guest if global_sid_Authenticated_Users
3011 * is in our list of SIDs.
3013 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3014 conn->server_info->ptok)) {
3015 flags &= ~SMB_WHOAMI_GUEST;
3018 /* NOTE: 8 bytes for UID/GID, irrespective of native
3019 * platform size. This matches
3020 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3022 data_len = 4 /* flags */
3029 + 4 /* pad/reserved */
3030 + (conn->server_info->utok.ngroups * 8)
3032 + (conn->server_info->ptok->num_sids *
3036 SIVAL(pdata, 0, flags);
3037 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3039 (SMB_BIG_UINT)conn->server_info->utok.uid);
3040 SBIG_UINT(pdata, 16,
3041 (SMB_BIG_UINT)conn->server_info->utok.gid);
3044 if (data_len >= max_data_bytes) {
3045 /* Potential overflow, skip the GIDs and SIDs. */
3047 SIVAL(pdata, 24, 0); /* num_groups */
3048 SIVAL(pdata, 28, 0); /* num_sids */
3049 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3050 SIVAL(pdata, 36, 0); /* reserved */
3056 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3057 SIVAL(pdata, 28, conn->server_info->num_sids);
3059 /* We walk the SID list twice, but this call is fairly
3060 * infrequent, and I don't expect that it's performance
3061 * sensitive -- jpeach
3063 for (i = 0, sid_bytes = 0;
3064 i < conn->server_info->ptok->num_sids; ++i) {
3065 sid_bytes += ndr_size_dom_sid(
3066 &conn->server_info->ptok->user_sids[i],
3070 /* SID list byte count */
3071 SIVAL(pdata, 32, sid_bytes);
3073 /* 4 bytes pad/reserved - must be zero */
3074 SIVAL(pdata, 36, 0);
3078 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3079 SBIG_UINT(pdata, data_len,
3080 (SMB_BIG_UINT)conn->server_info->utok.groups[i]);
3086 i < conn->server_info->ptok->num_sids; ++i) {
3087 int sid_len = ndr_size_dom_sid(
3088 &conn->server_info->ptok->user_sids[i],
3091 sid_linearize(pdata + data_len, sid_len,
3092 &conn->server_info->ptok->user_sids[i]);
3093 data_len += sid_len;
3099 case SMB_MAC_QUERY_FS_INFO:
3101 * Thursby MAC extension... ONLY on NTFS filesystems
3102 * once we do streams then we don't need this
3104 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3106 SIVAL(pdata,84,0x100); /* Don't support mac... */
3111 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3116 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3119 DEBUG( 4, ( "%s info_level = %d\n",
3120 smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) );
3125 /****************************************************************************
3126 Reply to a TRANS2_SETFSINFO (set filesystem info).
3127 ****************************************************************************/
3129 static void call_trans2setfsinfo(connection_struct *conn,
3130 struct smb_request *req,
3131 char **pparams, int total_params,
3132 char **ppdata, int total_data,
3133 unsigned int max_data_bytes)
3135 char *pdata = *ppdata;
3136 char *params = *pparams;
3139 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3142 if (total_params < 4) {
3143 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3145 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3149 info_level = SVAL(params,2);
3152 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3153 info_level != SMB_SET_CIFS_UNIX_INFO) {
3154 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3155 "info level (0x%x) on IPC$.\n",
3156 (unsigned int)info_level));
3157 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3162 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3163 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3164 DEBUG(0,("call_trans2setfsinfo: encryption required "
3165 "and info level 0x%x sent.\n",
3166 (unsigned int)info_level));
3167 exit_server_cleanly("encryption required "
3173 switch(info_level) {
3174 case SMB_SET_CIFS_UNIX_INFO:
3176 uint16 client_unix_major;
3177 uint16 client_unix_minor;
3178 uint32 client_unix_cap_low;
3179 uint32 client_unix_cap_high;
3181 if (!lp_unix_extensions()) {
3183 NT_STATUS_INVALID_LEVEL);
3187 /* There should be 12 bytes of capabilities set. */
3188 if (total_data < 8) {
3191 NT_STATUS_INVALID_PARAMETER);
3194 client_unix_major = SVAL(pdata,0);
3195 client_unix_minor = SVAL(pdata,2);
3196 client_unix_cap_low = IVAL(pdata,4);
3197 client_unix_cap_high = IVAL(pdata,8);
3198 /* Just print these values for now. */
3199 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3200 cap_low = 0x%x, cap_high = 0x%x\n",
3201 (unsigned int)client_unix_major,
3202 (unsigned int)client_unix_minor,
3203 (unsigned int)client_unix_cap_low,
3204 (unsigned int)client_unix_cap_high ));
3206 /* Here is where we must switch to posix pathname processing... */
3207 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3208 lp_set_posix_pathnames();
3209 mangle_change_to_posix();
3212 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3213 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3214 /* Client that knows how to do posix locks,
3215 * but not posix open/mkdir operations. Set a
3216 * default type for read/write checks. */
3218 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3224 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3227 size_t param_len = 0;
3228 size_t data_len = total_data;
3230 if (!lp_unix_extensions()) {
3233 NT_STATUS_INVALID_LEVEL);
3237 if (lp_smb_encrypt(SNUM(conn)) == false) {
3240 NT_STATUS_NOT_SUPPORTED);
3244 DEBUG( 4,("call_trans2setfsinfo: "
3245 "request transport encryption.\n"));
3247 status = srv_request_encryption_setup(conn,
3248 (unsigned char **)ppdata,
3250 (unsigned char **)pparams,
3253 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3254 !NT_STATUS_IS_OK(status)) {
3255 reply_nterror(req, status);
3259 send_trans2_replies(conn, req,
3266 if (NT_STATUS_IS_OK(status)) {
3267 /* Server-side transport
3268 * encryption is now *on*. */
3269 status = srv_encryption_start(conn);
3270 if (!NT_STATUS_IS_OK(status)) {
3271 exit_server_cleanly(
3272 "Failure in setting "
3273 "up encrypted transport");
3279 case SMB_FS_QUOTA_INFORMATION:
3281 files_struct *fsp = NULL;
3282 SMB_NTQUOTA_STRUCT quotas;
3284 ZERO_STRUCT(quotas);
3287 if ((conn->server_info->utok.uid != 0)
3288 ||!CAN_WRITE(conn)) {
3289 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3290 lp_servicename(SNUM(conn)),
3291 conn->server_info->unix_name));
3292 reply_doserror(req, ERRSRV, ERRaccess);
3296 /* note: normaly there're 48 bytes,
3297 * but we didn't use the last 6 bytes for now
3300 fsp = file_fsp(SVAL(params,0));
3302 if (!check_fsp_ntquota_handle(conn, req,
3304 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3306 req, NT_STATUS_INVALID_HANDLE);
3310 if (total_data < 42) {
3311 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3315 NT_STATUS_INVALID_PARAMETER);
3319 /* unknown_1 24 NULL bytes in pdata*/
3321 /* the soft quotas 8 bytes (SMB_BIG_UINT)*/
3322 quotas.softlim = (SMB_BIG_UINT)IVAL(pdata,24);
3323 #ifdef LARGE_SMB_OFF_T
3324 quotas.softlim |= (((SMB_BIG_UINT)IVAL(pdata,28)) << 32);
3325 #else /* LARGE_SMB_OFF_T */
3326 if ((IVAL(pdata,28) != 0)&&
3327 ((quotas.softlim != 0xFFFFFFFF)||
3328 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3329 /* more than 32 bits? */
3332 NT_STATUS_INVALID_PARAMETER);
3335 #endif /* LARGE_SMB_OFF_T */
3337 /* the hard quotas 8 bytes (SMB_BIG_UINT)*/
3338 quotas.hardlim = (SMB_BIG_UINT)IVAL(pdata,32);
3339 #ifdef LARGE_SMB_OFF_T
3340 quotas.hardlim |= (((SMB_BIG_UINT)IVAL(pdata,36)) << 32);
3341 #else /* LARGE_SMB_OFF_T */
3342 if ((IVAL(pdata,36) != 0)&&
3343 ((quotas.hardlim != 0xFFFFFFFF)||
3344 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3345 /* more than 32 bits? */
3348 NT_STATUS_INVALID_PARAMETER);
3351 #endif /* LARGE_SMB_OFF_T */
3353 /* quota_flags 2 bytes **/
3354 quotas.qflags = SVAL(pdata,40);
3356 /* unknown_2 6 NULL bytes follow*/
3358 /* now set the quotas */
3359 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3360 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3361 reply_doserror(req, ERRSRV, ERRerror);
3368 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3370 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3376 * sending this reply works fine,
3377 * but I'm not sure it's the same
3378 * like windows do...
3381 reply_outbuf(req, 10, 0);
3384 #if defined(HAVE_POSIX_ACLS)
3385 /****************************************************************************
3386 Utility function to count the number of entries in a POSIX acl.
3387 ****************************************************************************/
3389 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3391 unsigned int ace_count = 0;
3392 int entry_id = SMB_ACL_FIRST_ENTRY;
3393 SMB_ACL_ENTRY_T entry;
3395 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3397 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3398 entry_id = SMB_ACL_NEXT_ENTRY;
3405 /****************************************************************************
3406 Utility function to marshall a POSIX acl into wire format.
3407 ****************************************************************************/
3409 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3411 int entry_id = SMB_ACL_FIRST_ENTRY;
3412 SMB_ACL_ENTRY_T entry;
3414 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3415 SMB_ACL_TAG_T tagtype;
3416 SMB_ACL_PERMSET_T permset;
3417 unsigned char perms = 0;
3418 unsigned int own_grp;
3421 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3422 entry_id = SMB_ACL_NEXT_ENTRY;
3425 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3426 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3430 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3431 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3435 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3436 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3437 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3439 SCVAL(pdata,1,perms);
3442 case SMB_ACL_USER_OBJ:
3443 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3444 own_grp = (unsigned int)pst->st_uid;
3445 SIVAL(pdata,2,own_grp);
3450 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3452 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3455 own_grp = (unsigned int)*puid;
3456 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3457 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3458 SIVAL(pdata,2,own_grp);
3462 case SMB_ACL_GROUP_OBJ:
3463 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3464 own_grp = (unsigned int)pst->st_gid;
3465 SIVAL(pdata,2,own_grp);
3470 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3472 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3475 own_grp = (unsigned int)*pgid;
3476 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3477 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3478 SIVAL(pdata,2,own_grp);
3483 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3484 SIVAL(pdata,2,0xFFFFFFFF);
3485 SIVAL(pdata,6,0xFFFFFFFF);
3488 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3489 SIVAL(pdata,2,0xFFFFFFFF);
3490 SIVAL(pdata,6,0xFFFFFFFF);
3493 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3496 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3503 /****************************************************************************
3504 Store the FILE_UNIX_BASIC info.
3505 ****************************************************************************/
3507 static char *store_file_unix_basic(connection_struct *conn,
3510 const SMB_STRUCT_STAT *psbuf)
3512 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3513 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3515 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3518 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3521 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3522 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3523 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3526 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3530 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3534 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3537 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3541 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3545 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3548 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3552 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3559 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3560 * the chflags(2) (or equivalent) flags.
3562 * XXX: this really should be behind the VFS interface. To do this, we would
3563 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3564 * Each VFS module could then implement its own mapping as appropriate for the
3565 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3567 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3571 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3575 { UF_IMMUTABLE, EXT_IMMUTABLE },
3579 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3583 { UF_HIDDEN, EXT_HIDDEN },
3586 /* Do not remove. We need to guarantee that this array has at least one
3587 * entry to build on HP-UX.
3593 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3594 uint32 *smb_fflags, uint32 *smb_fmask)
3596 #ifdef HAVE_STAT_ST_FLAGS
3599 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3600 *smb_fmask |= info2_flags_map[i].smb_fflag;
3601 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3602 *smb_fflags |= info2_flags_map[i].smb_fflag;
3605 #endif /* HAVE_STAT_ST_FLAGS */
3608 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3609 const uint32 smb_fflags,
3610 const uint32 smb_fmask,
3613 #ifdef HAVE_STAT_ST_FLAGS
3614 uint32 max_fmask = 0;
3617 *stat_fflags = psbuf->st_flags;
3619 /* For each flags requested in smb_fmask, check the state of the
3620 * corresponding flag in smb_fflags and set or clear the matching
3624 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3625 max_fmask |= info2_flags_map[i].smb_fflag;
3626 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3627 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3628 *stat_fflags |= info2_flags_map[i].stat_fflag;
3630 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3635 /* If smb_fmask is asking to set any bits that are not supported by
3636 * our flag mappings, we should fail.
3638 if ((smb_fmask & max_fmask) != smb_fmask) {
3645 #endif /* HAVE_STAT_ST_FLAGS */
3649 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3650 * of file flags and birth (create) time.
3652 static char *store_file_unix_basic_info2(connection_struct *conn,
3655 const SMB_STRUCT_STAT *psbuf)
3657 uint32 file_flags = 0;
3658 uint32 flags_mask = 0;
3660 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3662 /* Create (birth) time 64 bit */
3663 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3666 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3667 SIVAL(pdata, 0, file_flags); /* flags */
3668 SIVAL(pdata, 4, flags_mask); /* mask */
3674 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3675 const struct stream_struct *streams,
3677 unsigned int max_data_bytes,
3678 unsigned int *data_size)
3681 unsigned int ofs = 0;
3683 for (i=0; i<num_streams; i++) {
3684 unsigned int next_offset;
3686 smb_ucs2_t *namebuf;
3688 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3689 streams[i].name, &namelen) ||
3692 return NT_STATUS_INVALID_PARAMETER;
3696 * name_buf is now null-terminated, we need to marshall as not
3702 if (ofs + 24 + namelen > max_data_bytes) {
3703 TALLOC_FREE(namebuf);
3704 return NT_STATUS_BUFFER_TOO_SMALL;
3707 SIVAL(data, ofs+4, namelen);
3708 SOFF_T(data, ofs+8, streams[i].size);
3709 SOFF_T(data, ofs+16, streams[i].alloc_size);
3710 memcpy(data+ofs+24, namebuf, namelen);
3711 TALLOC_FREE(namebuf);
3713 next_offset = ofs + 24 + namelen;
3715 if (i == num_streams-1) {
3716 SIVAL(data, ofs, 0);
3719 unsigned int align = ndr_align_size(next_offset, 8);
3721 if (next_offset + align > max_data_bytes) {
3722 return NT_STATUS_BUFFER_TOO_SMALL;
3725 memset(data+next_offset, 0, align);
3726 next_offset += align;
3728 SIVAL(data, ofs, next_offset - ofs);
3737 return NT_STATUS_OK;
3740 /****************************************************************************
3741 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3742 ****************************************************************************/
3744 static void call_trans2qpipeinfo(connection_struct *conn,
3745 struct smb_request *req,
3746 unsigned int tran_call,
3747 char **pparams, int total_params,
3748 char **ppdata, int total_data,
3749 unsigned int max_data_bytes)
3751 char *params = *pparams;
3752 char *pdata = *ppdata;
3753 unsigned int data_size = 0;
3754 unsigned int param_size = 2;
3756 smb_np_struct *p_pipe = NULL;
3759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3763 if (total_params < 4) {
3764 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3768 p_pipe = get_rpc_pipe_p(SVAL(params,0));
3769 if (p_pipe == NULL) {
3770 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3774 info_level = SVAL(params,2);
3776 *pparams = (char *)SMB_REALLOC(*pparams,2);
3777 if (*pparams == NULL) {
3778 reply_nterror(req, NT_STATUS_NO_MEMORY);
3783 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3784 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3785 if (*ppdata == NULL ) {
3786 reply_nterror(req, NT_STATUS_NO_MEMORY);
3791 switch (info_level) {
3792 case SMB_FILE_STANDARD_INFORMATION:
3794 SOFF_T(pdata,0,4096LL);
3801 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3805 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3811 /****************************************************************************
3812 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3813 file name or file id).
3814 ****************************************************************************/
3816 static void call_trans2qfilepathinfo(connection_struct *conn,
3817 struct smb_request *req,
3818 unsigned int tran_call,
3819 char **pparams, int total_params,
3820 char **ppdata, int total_data,
3821 unsigned int max_data_bytes)
3823 char *params = *pparams;
3824 char *pdata = *ppdata;
3825 char *dstart, *dend;
3829 SMB_OFF_T file_size=0;
3830 SMB_BIG_UINT allocation_size=0;
3831 unsigned int data_size = 0;
3832 unsigned int param_size = 2;
3833 SMB_STRUCT_STAT sbuf;
3834 char *dos_fname = NULL;
3840 bool delete_pending = False;
3842 time_t create_time, mtime, atime;
3843 struct timespec create_time_ts, mtime_ts, atime_ts;
3844 struct timespec write_time_ts;
3845 files_struct *fsp = NULL;
3846 struct file_id fileid;
3847 struct ea_list *ea_list = NULL;
3848 uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */
3849 char *lock_data = NULL;
3850 bool ms_dfs_link = false;
3851 TALLOC_CTX *ctx = talloc_tos();
3854 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3859 ZERO_STRUCT(write_time_ts);
3861 if (tran_call == TRANSACT2_QFILEINFO) {
3862 if (total_params < 4) {
3863 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3868 call_trans2qpipeinfo(conn, req, tran_call,
3869 pparams, total_params,
3875 fsp = file_fsp(SVAL(params,0));
3876 info_level = SVAL(params,2);
3878 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3880 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3881 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3885 /* Initial check for valid fsp ptr. */
3886 if (!check_fsp_open(conn, req, fsp)) {
3890 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3892 reply_nterror(req, NT_STATUS_NO_MEMORY);
3896 if(fsp->fake_file_handle) {
3898 * This is actually for the QUOTA_FAKE_FILE --metze
3901 /* We know this name is ok, it's already passed the checks. */
3903 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3905 * This is actually a QFILEINFO on a directory
3906 * handle (returned from an NT SMB). NT5.0 seems
3907 * to do this call. JRA.
3910 if (INFO_LEVEL_IS_UNIX(info_level)) {
3911 /* Always do lstat for UNIX calls. */
3912 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3913 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3914 reply_unixerror(req,ERRDOS,ERRbadpath);
3917 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3918 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3919 reply_unixerror(req, ERRDOS, ERRbadpath);
3923 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3924 get_file_infos(fileid, &delete_pending, &write_time_ts);
3927 * Original code - this is an open file.
3929 if (!check_fsp(conn, req, fsp)) {
3933 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3934 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3935 reply_unixerror(req, ERRDOS, ERRbadfid);
3938 pos = fsp->fh->position_information;
3939 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3940 get_file_infos(fileid, &delete_pending, &write_time_ts);
3941 access_mask = fsp->access_mask;
3945 NTSTATUS status = NT_STATUS_OK;
3948 if (total_params < 7) {
3949 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3953 info_level = SVAL(params,0);
3955 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3957 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3958 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3962 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3964 STR_TERMINATE, &status);
3965 if (!NT_STATUS_IS_OK(status)) {
3966 reply_nterror(req, status);
3970 status = resolve_dfspath(ctx,
3972 req->flags2 & FLAGS2_DFS_PATHNAMES,
3975 if (!NT_STATUS_IS_OK(status)) {
3976 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3977 reply_botherror(req,
3978 NT_STATUS_PATH_NOT_COVERED,
3979 ERRSRV, ERRbadpath);
3981 reply_nterror(req, status);
3985 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3986 if (!NT_STATUS_IS_OK(status)) {
3987 reply_nterror(req, status);
3990 status = check_name(conn, fname);
3991 if (!NT_STATUS_IS_OK(status)) {
3992 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3993 reply_nterror(req, status);
3997 if (INFO_LEVEL_IS_UNIX(info_level)) {
3998 /* Always do lstat for UNIX calls. */
3999 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4000 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4001 reply_unixerror(req, ERRDOS, ERRbadpath);
4005 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4006 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4009 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4010 reply_unixerror(req, ERRDOS, ERRbadpath);
4015 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4016 get_file_infos(fileid, &delete_pending, &write_time_ts);
4017 if (delete_pending) {
4018 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4023 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4024 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4028 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4029 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4031 p = strrchr_m(fname,'/');
4038 mode = dos_mode_msdfs(conn,fname,&sbuf);
4040 mode = dos_mode(conn,fname,&sbuf);
4043 mode = FILE_ATTRIBUTE_NORMAL;
4045 nlink = sbuf.st_nlink;
4047 if (nlink && (mode&aDIR)) {
4051 if ((nlink > 0) && delete_pending) {
4055 fullpathname = fname;
4057 file_size = get_file_size(sbuf);
4059 /* Pull out any data sent here before we realloc. */
4060 switch (info_level) {
4061 case SMB_INFO_QUERY_EAS_FROM_LIST:
4063 /* Pull any EA list from the data portion. */
4066 if (total_data < 4) {
4068 req, NT_STATUS_INVALID_PARAMETER);
4071 ea_size = IVAL(pdata,0);
4073 if (total_data > 0 && ea_size != total_data) {
4074 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4075 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4077 req, NT_STATUS_INVALID_PARAMETER);
4081 if (!lp_ea_support(SNUM(conn))) {
4082 reply_doserror(req, ERRDOS,
4083 ERReasnotsupported);
4087 /* Pull out the list of names. */
4088 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4091 req, NT_STATUS_INVALID_PARAMETER);
4097 case SMB_QUERY_POSIX_LOCK:
4099 if (fsp == NULL || fsp->fh->fd == -1) {
4100 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4104 if (total_data != POSIX_LOCK_DATA_SIZE) {
4106 req, NT_STATUS_INVALID_PARAMETER);
4110 /* Copy the lock range data. */
4111 lock_data = (char *)TALLOC_MEMDUP(
4112 ctx, pdata, total_data);
4114 reply_nterror(req, NT_STATUS_NO_MEMORY);
4122 *pparams = (char *)SMB_REALLOC(*pparams,2);
4123 if (*pparams == NULL) {
4124 reply_nterror(req, NT_STATUS_NO_MEMORY);
4129 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4130 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4131 if (*ppdata == NULL ) {
4132 reply_nterror(req, NT_STATUS_NO_MEMORY);
4137 dend = dstart + data_size - 1;
4139 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4140 mtime_ts = get_mtimespec(&sbuf);
4141 atime_ts = get_atimespec(&sbuf);
4143 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4146 /* Do we have this path open ? */
4148 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4149 fsp1 = file_find_di_first(fileid);
4150 if (fsp1 && fsp1->initial_allocation_size) {
4151 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4155 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4156 mtime_ts = write_time_ts;
4159 if (lp_dos_filetime_resolution(SNUM(conn))) {
4160 dos_filetime_timespec(&create_time_ts);
4161 dos_filetime_timespec(&mtime_ts);
4162 dos_filetime_timespec(&atime_ts);
4165 create_time = convert_timespec_to_time_t(create_time_ts);
4166 mtime = convert_timespec_to_time_t(mtime_ts);
4167 atime = convert_timespec_to_time_t(atime_ts);
4169 /* NT expects the name to be in an exact form of the *full*
4170 filename. See the trans2 torture test */
4171 if (ISDOT(base_name)) {
4172 dos_fname = talloc_strdup(ctx, "\\");
4174 reply_nterror(req, NT_STATUS_NO_MEMORY);
4178 dos_fname = talloc_asprintf(ctx,
4182 reply_nterror(req, NT_STATUS_NO_MEMORY);
4185 string_replace(dos_fname, '/', '\\');
4188 switch (info_level) {
4189 case SMB_INFO_STANDARD:
4190 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4192 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4193 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4194 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4195 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4196 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4197 SSVAL(pdata,l1_attrFile,mode);
4200 case SMB_INFO_QUERY_EA_SIZE:
4202 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4203 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4205 srv_put_dos_date2(pdata,0,create_time);
4206 srv_put_dos_date2(pdata,4,atime);
4207 srv_put_dos_date2(pdata,8,mtime); /* write time */
4208 SIVAL(pdata,12,(uint32)file_size);
4209 SIVAL(pdata,16,(uint32)allocation_size);
4210 SSVAL(pdata,20,mode);
4211 SIVAL(pdata,22,ea_size);
4215 case SMB_INFO_IS_NAME_VALID:
4216 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4217 if (tran_call == TRANSACT2_QFILEINFO) {
4218 /* os/2 needs this ? really ?*/
4219 reply_doserror(req, ERRDOS, ERRbadfunc);
4226 case SMB_INFO_QUERY_EAS_FROM_LIST:
4228 size_t total_ea_len = 0;
4229 struct ea_list *ea_file_list = NULL;
4231 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4233 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4234 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4236 if (!ea_list || (total_ea_len > data_size)) {
4238 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4242 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4246 case SMB_INFO_QUERY_ALL_EAS:
4248 /* We have data_size bytes to put EA's into. */
4249 size_t total_ea_len = 0;
4251 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4253 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4254 if (!ea_list || (total_ea_len > data_size)) {
4256 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4260 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4264 case SMB_FILE_BASIC_INFORMATION:
4265 case SMB_QUERY_FILE_BASIC_INFO:
4267 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4268 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4269 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4271 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4275 put_long_date_timespec(pdata,create_time_ts);
4276 put_long_date_timespec(pdata+8,atime_ts);
4277 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4278 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4279 SIVAL(pdata,32,mode);
4281 DEBUG(5,("SMB_QFBI - "));
4282 DEBUG(5,("create: %s ", ctime(&create_time)));
4283 DEBUG(5,("access: %s ", ctime(&atime)));
4284 DEBUG(5,("write: %s ", ctime(&mtime)));
4285 DEBUG(5,("change: %s ", ctime(&mtime)));
4286 DEBUG(5,("mode: %x\n", mode));
4289 case SMB_FILE_STANDARD_INFORMATION:
4290 case SMB_QUERY_FILE_STANDARD_INFO:
4292 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4294 SOFF_T(pdata,0,allocation_size);
4295 SOFF_T(pdata,8,file_size);
4296 SIVAL(pdata,16,nlink);
4297 SCVAL(pdata,20,delete_pending?1:0);
4298 SCVAL(pdata,21,(mode&aDIR)?1:0);
4299 SSVAL(pdata,22,0); /* Padding. */
4302 case SMB_FILE_EA_INFORMATION:
4303 case SMB_QUERY_FILE_EA_INFO:
4305 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4306 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4308 SIVAL(pdata,0,ea_size);
4312 /* Get the 8.3 name - used if NT SMB was negotiated. */
4313 case SMB_QUERY_FILE_ALT_NAME_INFO:
4314 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4316 char mangled_name[13];
4317 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4318 if (!name_to_8_3(base_name,mangled_name,
4319 True,conn->params)) {
4322 NT_STATUS_NO_MEMORY);
4324 len = srvstr_push(dstart, req->flags2,
4325 pdata+4, mangled_name,
4326 PTR_DIFF(dend, pdata+4),
4328 data_size = 4 + len;
4333 case SMB_QUERY_FILE_NAME_INFO:
4335 this must be *exactly* right for ACLs on mapped drives to work
4337 len = srvstr_push(dstart, req->flags2,
4339 PTR_DIFF(dend, pdata+4),
4341 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4342 data_size = 4 + len;
4346 case SMB_FILE_ALLOCATION_INFORMATION:
4347 case SMB_QUERY_FILE_ALLOCATION_INFO:
4348 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4350 SOFF_T(pdata,0,allocation_size);
4353 case SMB_FILE_END_OF_FILE_INFORMATION:
4354 case SMB_QUERY_FILE_END_OF_FILEINFO:
4355 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4357 SOFF_T(pdata,0,file_size);
4360 case SMB_QUERY_FILE_ALL_INFO:
4361 case SMB_FILE_ALL_INFORMATION:
4363 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4364 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4365 put_long_date_timespec(pdata,create_time_ts);
4366 put_long_date_timespec(pdata+8,atime_ts);
4367 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4368 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4369 SIVAL(pdata,32,mode);
4370 SIVAL(pdata,36,0); /* padding. */
4372 SOFF_T(pdata,0,allocation_size);
4373 SOFF_T(pdata,8,file_size);
4374 SIVAL(pdata,16,nlink);
4375 SCVAL(pdata,20,delete_pending);
4376 SCVAL(pdata,21,(mode&aDIR)?1:0);
4379 SIVAL(pdata,0,ea_size);
4380 pdata += 4; /* EA info */
4381 len = srvstr_push(dstart, req->flags2,
4383 PTR_DIFF(dend, pdata+4),
4387 data_size = PTR_DIFF(pdata,(*ppdata));
4390 case SMB_FILE_INTERNAL_INFORMATION:
4391 /* This should be an index number - looks like
4394 I think this causes us to fail the IFSKIT
4395 BasicFileInformationTest. -tpot */
4397 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4398 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4399 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4403 case SMB_FILE_ACCESS_INFORMATION:
4404 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4405 SIVAL(pdata,0,access_mask);
4409 case SMB_FILE_NAME_INFORMATION:
4410 /* Pathname with leading '\'. */
4413 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4414 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4415 SIVAL(pdata,0,byte_len);
4416 data_size = 4 + byte_len;
4420 case SMB_FILE_DISPOSITION_INFORMATION:
4421 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4423 SCVAL(pdata,0,delete_pending);
4426 case SMB_FILE_POSITION_INFORMATION:
4427 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4429 SOFF_T(pdata,0,pos);
4432 case SMB_FILE_MODE_INFORMATION:
4433 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4434 SIVAL(pdata,0,mode);
4438 case SMB_FILE_ALIGNMENT_INFORMATION:
4439 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4440 SIVAL(pdata,0,0); /* No alignment needed. */
4445 * NT4 server just returns "invalid query" to this - if we try
4446 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4449 /* The first statement above is false - verified using Thursby
4450 * client against NT4 -- gcolley.
4452 case SMB_QUERY_FILE_STREAM_INFO:
4453 case SMB_FILE_STREAM_INFORMATION: {
4454 unsigned int num_streams;
4455 struct stream_struct *streams;
4458 DEBUG(10,("call_trans2qfilepathinfo: "
4459 "SMB_FILE_STREAM_INFORMATION\n"));
4461 status = SMB_VFS_STREAMINFO(
4462 conn, fsp, fname, talloc_tos(),
4463 &num_streams, &streams);
4465 if (!NT_STATUS_IS_OK(status)) {
4466 DEBUG(10, ("could not get stream info: %s\n",
4467 nt_errstr(status)));
4468 reply_nterror(req, status);
4472 status = marshall_stream_info(num_streams, streams,
4473 pdata, max_data_bytes,
4476 if (!NT_STATUS_IS_OK(status)) {
4477 DEBUG(10, ("marshall_stream_info failed: %s\n",
4478 nt_errstr(status)));
4479 reply_nterror(req, status);
4483 TALLOC_FREE(streams);
4487 case SMB_QUERY_COMPRESSION_INFO:
4488 case SMB_FILE_COMPRESSION_INFORMATION:
4489 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4490 SOFF_T(pdata,0,file_size);
4491 SIVAL(pdata,8,0); /* ??? */
4492 SIVAL(pdata,12,0); /* ??? */
4496 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4497 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4498 put_long_date_timespec(pdata,create_time_ts);
4499 put_long_date_timespec(pdata+8,atime_ts);
4500 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4501 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4502 SOFF_T(pdata,32,allocation_size);
4503 SOFF_T(pdata,40,file_size);
4504 SIVAL(pdata,48,mode);
4505 SIVAL(pdata,52,0); /* ??? */
4509 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4510 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4511 SIVAL(pdata,0,mode);
4517 * CIFS UNIX Extensions.
4520 case SMB_QUERY_FILE_UNIX_BASIC:
4522 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4523 data_size = PTR_DIFF(pdata,(*ppdata));
4527 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4529 for (i=0; i<100; i++)
4530 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4536 case SMB_QUERY_FILE_UNIX_INFO2:
4538 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4539 data_size = PTR_DIFF(pdata,(*ppdata));
4543 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4545 for (i=0; i<100; i++)
4546 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4552 case SMB_QUERY_FILE_UNIX_LINK:
4554 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4557 reply_nterror(req, NT_STATUS_NO_MEMORY);
4561 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4563 if(!S_ISLNK(sbuf.st_mode)) {
4564 reply_unixerror(req, ERRSRV,
4569 reply_unixerror(req, ERRDOS, ERRbadlink);
4572 len = SMB_VFS_READLINK(conn,fullpathname,
4575 reply_unixerror(req, ERRDOS,
4580 len = srvstr_push(dstart, req->flags2,
4582 PTR_DIFF(dend, pdata),
4585 data_size = PTR_DIFF(pdata,(*ppdata));
4590 #if defined(HAVE_POSIX_ACLS)
4591 case SMB_QUERY_POSIX_ACL:
4593 SMB_ACL_T file_acl = NULL;
4594 SMB_ACL_T def_acl = NULL;
4595 uint16 num_file_acls = 0;
4596 uint16 num_def_acls = 0;
4598 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4599 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4601 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4604 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4605 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4609 NT_STATUS_NOT_IMPLEMENTED);
4613 if (S_ISDIR(sbuf.st_mode)) {
4614 if (fsp && fsp->is_directory) {
4615 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4617 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4619 def_acl = free_empty_sys_acl(conn, def_acl);
4622 num_file_acls = count_acl_entries(conn, file_acl);
4623 num_def_acls = count_acl_entries(conn, def_acl);
4625 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4626 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4628 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4629 SMB_POSIX_ACL_HEADER_SIZE) ));
4631 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4634 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4638 NT_STATUS_BUFFER_TOO_SMALL);
4642 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4643 SSVAL(pdata,2,num_file_acls);
4644 SSVAL(pdata,4,num_def_acls);
4645 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4647 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4650 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4653 req, NT_STATUS_INTERNAL_ERROR);
4656 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4658 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4661 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4665 NT_STATUS_INTERNAL_ERROR);
4670 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4673 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4675 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4681 case SMB_QUERY_POSIX_LOCK:
4683 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4685 SMB_BIG_UINT offset;
4687 enum brl_type lock_type;
4689 if (total_data != POSIX_LOCK_DATA_SIZE) {
4691 req, NT_STATUS_INVALID_PARAMETER);
4695 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4696 case POSIX_LOCK_TYPE_READ:
4697 lock_type = READ_LOCK;
4699 case POSIX_LOCK_TYPE_WRITE:
4700 lock_type = WRITE_LOCK;
4702 case POSIX_LOCK_TYPE_UNLOCK:
4704 /* There's no point in asking for an unlock... */
4707 NT_STATUS_INVALID_PARAMETER);
4711 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4712 #if defined(HAVE_LONGLONG)
4713 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4714 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4715 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4716 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4717 #else /* HAVE_LONGLONG */
4718 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4719 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4720 #endif /* HAVE_LONGLONG */
4722 status = query_lock(fsp,
4729 if (ERROR_WAS_LOCK_DENIED(status)) {
4730 /* Here we need to report who has it locked... */
4731 data_size = POSIX_LOCK_DATA_SIZE;
4733 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4734 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4735 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4736 #if defined(HAVE_LONGLONG)
4737 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4738 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4739 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4740 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4741 #else /* HAVE_LONGLONG */
4742 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4743 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4744 #endif /* HAVE_LONGLONG */
4746 } else if (NT_STATUS_IS_OK(status)) {
4747 /* For success we just return a copy of what we sent
4748 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4749 data_size = POSIX_LOCK_DATA_SIZE;
4750 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4751 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4753 reply_nterror(req, status);
4760 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4764 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4770 /****************************************************************************
4771 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4773 ****************************************************************************/
4775 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4776 connection_struct *conn,
4777 const char *oldname_in,
4778 const char *newname_in)
4780 SMB_STRUCT_STAT sbuf1, sbuf2;
4781 char *last_component_oldname = NULL;
4782 char *last_component_newname = NULL;
4783 char *oldname = NULL;
4784 char *newname = NULL;
4785 NTSTATUS status = NT_STATUS_OK;
4790 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4791 &last_component_oldname, &sbuf1);
4792 if (!NT_STATUS_IS_OK(status)) {
4796 status = check_name(conn, oldname);
4797 if (!NT_STATUS_IS_OK(status)) {
4801 /* source must already exist. */
4802 if (!VALID_STAT(sbuf1)) {
4803 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4806 status = unix_convert(ctx, conn, newname_in, False, &newname,
4807 &last_component_newname, &sbuf2);
4808 if (!NT_STATUS_IS_OK(status)) {
4812 status = check_name(conn, newname);
4813 if (!NT_STATUS_IS_OK(status)) {
4817 /* Disallow if newname already exists. */
4818 if (VALID_STAT(sbuf2)) {
4819 return NT_STATUS_OBJECT_NAME_COLLISION;
4822 /* No links from a directory. */
4823 if (S_ISDIR(sbuf1.st_mode)) {
4824 return NT_STATUS_FILE_IS_A_DIRECTORY;
4827 /* Ensure this is within the share. */
4828 status = check_reduced_name(conn, oldname);
4829 if (!NT_STATUS_IS_OK(status)) {
4833 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4835 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4836 status = map_nt_error_from_unix(errno);
4837 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4838 nt_errstr(status), newname, oldname));
4844 /****************************************************************************
4845 Deal with setting the time from any of the setfilepathinfo functions.
4846 ****************************************************************************/
4848 NTSTATUS smb_set_file_time(connection_struct *conn,
4851 const SMB_STRUCT_STAT *psbuf,
4852 struct timespec ts[2],
4853 bool setting_write_time)
4856 FILE_NOTIFY_CHANGE_LAST_ACCESS
4857 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4859 if (!VALID_STAT(*psbuf)) {
4860 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4863 /* get some defaults (no modifications) if any info is zero or -1. */
4864 if (null_timespec(ts[0])) {
4865 ts[0] = get_atimespec(psbuf);
4866 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4869 if (null_timespec(ts[1])) {
4870 ts[1] = get_mtimespec(psbuf);
4871 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4874 if (!setting_write_time) {
4875 /* ts[1] comes from change time, not write time. */
4876 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4879 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4880 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4883 * Try and set the times of this file if
4884 * they are different from the current values.
4888 struct timespec mts = get_mtimespec(psbuf);
4889 struct timespec ats = get_atimespec(psbuf);
4890 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4891 return NT_STATUS_OK;
4895 if (setting_write_time) {
4897 * This was a setfileinfo on an open file.
4898 * NT does this a lot. We also need to
4899 * set the time here, as it can be read by
4900 * FindFirst/FindNext and with the patch for bug #2045
4901 * in smbd/fileio.c it ensures that this timestamp is
4902 * kept sticky even after a write. We save the request
4903 * away and will set it on file close and after a write. JRA.
4906 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4907 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4910 set_sticky_write_time_fsp(fsp, ts[1]);
4912 set_sticky_write_time_path(conn, fname,
4913 vfs_file_id_from_sbuf(conn, psbuf),
4918 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4920 if(file_ntimes(conn, fname, ts)!=0) {
4921 return map_nt_error_from_unix(errno);
4923 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4925 return NT_STATUS_OK;
4928 /****************************************************************************
4929 Deal with setting the dosmode from any of the setfilepathinfo functions.
4930 ****************************************************************************/
4932 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4934 SMB_STRUCT_STAT *psbuf,
4937 if (!VALID_STAT(*psbuf)) {
4938 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4942 if (S_ISDIR(psbuf->st_mode)) {
4949 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4951 /* check the mode isn't different, before changing it */
4952 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4954 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4955 fname, (unsigned int)dosmode ));
4957 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4958 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4959 fname, strerror(errno)));
4960 return map_nt_error_from_unix(errno);
4963 return NT_STATUS_OK;
4966 /****************************************************************************
4967 Deal with setting the size from any of the setfilepathinfo functions.
4968 ****************************************************************************/
4970 static NTSTATUS smb_set_file_size(connection_struct *conn,
4971 struct smb_request *req,
4974 SMB_STRUCT_STAT *psbuf,
4977 NTSTATUS status = NT_STATUS_OK;
4978 files_struct *new_fsp = NULL;
4980 if (!VALID_STAT(*psbuf)) {
4981 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4984 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4986 if (size == get_file_size(*psbuf)) {
4987 return NT_STATUS_OK;
4990 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4991 fname, (double)size ));
4993 if (fsp && fsp->fh->fd != -1) {
4994 /* Handle based call. */
4995 if (vfs_set_filelen(fsp, size) == -1) {
4996 return map_nt_error_from_unix(errno);
4998 trigger_write_time_update_immediate(fsp);
4999 return NT_STATUS_OK;
5002 status = open_file_ntcreate(conn, req, fname, psbuf,
5003 FILE_WRITE_ATTRIBUTES,
5004 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5007 FILE_ATTRIBUTE_NORMAL,
5008 FORCE_OPLOCK_BREAK_TO_NONE,
5011 if (!NT_STATUS_IS_OK(status)) {
5012 /* NB. We check for open_was_deferred in the caller. */
5016 if (vfs_set_filelen(new_fsp, size) == -1) {
5017 status = map_nt_error_from_unix(errno);
5018 close_file(new_fsp,NORMAL_CLOSE);
5022 trigger_write_time_update_immediate(new_fsp);
5023 close_file(new_fsp,NORMAL_CLOSE);
5024 return NT_STATUS_OK;
5027 /****************************************************************************
5028 Deal with SMB_INFO_SET_EA.
5029 ****************************************************************************/
5031 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5037 struct ea_list *ea_list = NULL;
5038 TALLOC_CTX *ctx = NULL;
5039 NTSTATUS status = NT_STATUS_OK;
5041 if (total_data < 10) {
5043 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5044 length. They seem to have no effect. Bug #3212. JRA */
5046 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5047 /* We're done. We only get EA info in this call. */
5048 return NT_STATUS_OK;
5051 return NT_STATUS_INVALID_PARAMETER;
5054 if (IVAL(pdata,0) > total_data) {
5055 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5056 IVAL(pdata,0), (unsigned int)total_data));
5057 return NT_STATUS_INVALID_PARAMETER;
5061 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5063 return NT_STATUS_INVALID_PARAMETER;
5065 status = set_ea(conn, fsp, fname, ea_list);
5070 /****************************************************************************
5071 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5072 ****************************************************************************/
5074 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5079 SMB_STRUCT_STAT *psbuf)
5081 NTSTATUS status = NT_STATUS_OK;
5082 bool delete_on_close;
5085 if (total_data < 1) {
5086 return NT_STATUS_INVALID_PARAMETER;
5090 return NT_STATUS_INVALID_HANDLE;
5093 delete_on_close = (CVAL(pdata,0) ? True : False);
5094 dosmode = dos_mode(conn, fname, psbuf);
5096 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5097 "delete_on_close = %u\n",
5099 (unsigned int)dosmode,
5100 (unsigned int)delete_on_close ));
5102 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5104 if (!NT_STATUS_IS_OK(status)) {
5108 /* The set is across all open files on this dev/inode pair. */
5109 if (!set_delete_on_close(fsp, delete_on_close,
5110 &conn->server_info->utok)) {
5111 return NT_STATUS_ACCESS_DENIED;
5113 return NT_STATUS_OK;
5116 /****************************************************************************
5117 Deal with SMB_FILE_POSITION_INFORMATION.
5118 ****************************************************************************/
5120 static NTSTATUS smb_file_position_information(connection_struct *conn,
5125 SMB_BIG_UINT position_information;
5127 if (total_data < 8) {
5128 return NT_STATUS_INVALID_PARAMETER;
5132 /* Ignore on pathname based set. */
5133 return NT_STATUS_OK;
5136 position_information = (SMB_BIG_UINT)IVAL(pdata,0);
5137 #ifdef LARGE_SMB_OFF_T
5138 position_information |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5139 #else /* LARGE_SMB_OFF_T */
5140 if (IVAL(pdata,4) != 0) {
5141 /* more than 32 bits? */
5142 return NT_STATUS_INVALID_PARAMETER;
5144 #endif /* LARGE_SMB_OFF_T */
5146 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5147 fsp->fsp_name, (double)position_information ));
5148 fsp->fh->position_information = position_information;
5149 return NT_STATUS_OK;
5152 /****************************************************************************
5153 Deal with SMB_FILE_MODE_INFORMATION.
5154 ****************************************************************************/
5156 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5162 if (total_data < 4) {
5163 return NT_STATUS_INVALID_PARAMETER;
5165 mode = IVAL(pdata,0);
5166 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5167 return NT_STATUS_INVALID_PARAMETER;
5169 return NT_STATUS_OK;
5172 /****************************************************************************
5173 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5174 ****************************************************************************/
5176 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5177 struct smb_request *req,
5182 char *link_target = NULL;
5183 const char *newname = fname;
5184 NTSTATUS status = NT_STATUS_OK;
5185 TALLOC_CTX *ctx = talloc_tos();
5187 /* Set a symbolic link. */
5188 /* Don't allow this if follow links is false. */
5190 if (total_data == 0) {
5191 return NT_STATUS_INVALID_PARAMETER;
5194 if (!lp_symlinks(SNUM(conn))) {
5195 return NT_STATUS_ACCESS_DENIED;
5198 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5199 total_data, STR_TERMINATE);
5202 return NT_STATUS_INVALID_PARAMETER;
5205 /* !widelinks forces the target path to be within the share. */
5206 /* This means we can interpret the target as a pathname. */
5207 if (!lp_widelinks(SNUM(conn))) {
5208 char *rel_name = NULL;
5209 char *last_dirp = NULL;
5211 if (*link_target == '/') {
5212 /* No absolute paths allowed. */
5213 return NT_STATUS_ACCESS_DENIED;
5215 rel_name = talloc_strdup(ctx,newname);
5217 return NT_STATUS_NO_MEMORY;
5219 last_dirp = strrchr_m(rel_name, '/');
5221 last_dirp[1] = '\0';
5223 rel_name = talloc_strdup(ctx,"./");
5225 return NT_STATUS_NO_MEMORY;
5228 rel_name = talloc_asprintf_append(rel_name,
5232 return NT_STATUS_NO_MEMORY;
5235 status = check_name(conn, rel_name);
5236 if (!NT_STATUS_IS_OK(status)) {
5241 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5242 newname, link_target ));
5244 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5245 return map_nt_error_from_unix(errno);
5248 return NT_STATUS_OK;
5251 /****************************************************************************
5252 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5253 ****************************************************************************/
5255 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5256 struct smb_request *req,
5257 const char *pdata, int total_data,
5260 char *oldname = NULL;
5261 TALLOC_CTX *ctx = talloc_tos();
5262 NTSTATUS status = NT_STATUS_OK;
5264 /* Set a hard link. */
5265 if (total_data == 0) {
5266 return NT_STATUS_INVALID_PARAMETER;
5269 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5270 total_data, STR_TERMINATE, &status);
5271 if (!NT_STATUS_IS_OK(status)) {
5275 status = resolve_dfspath(ctx, conn,
5276 req->flags2 & FLAGS2_DFS_PATHNAMES,
5279 if (!NT_STATUS_IS_OK(status)) {
5283 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5286 return hardlink_internals(ctx, conn, oldname, fname);
5289 /****************************************************************************
5290 Deal with SMB_FILE_RENAME_INFORMATION.
5291 ****************************************************************************/
5293 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5294 struct smb_request *req,
5303 char *newname = NULL;
5304 char *base_name = NULL;
5305 bool dest_has_wcard = False;
5306 NTSTATUS status = NT_STATUS_OK;
5308 TALLOC_CTX *ctx = talloc_tos();
5310 if (total_data < 13) {
5311 return NT_STATUS_INVALID_PARAMETER;
5314 overwrite = (CVAL(pdata,0) ? True : False);
5315 root_fid = IVAL(pdata,4);
5316 len = IVAL(pdata,8);
5318 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5319 return NT_STATUS_INVALID_PARAMETER;
5322 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5325 if (!NT_STATUS_IS_OK(status)) {
5329 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5332 status = resolve_dfspath_wcard(ctx, conn,
5333 req->flags2 & FLAGS2_DFS_PATHNAMES,
5337 if (!NT_STATUS_IS_OK(status)) {
5341 /* Check the new name has no '/' characters. */
5342 if (strchr_m(newname, '/')) {
5343 return NT_STATUS_NOT_SUPPORTED;
5346 /* Create the base directory. */
5347 base_name = talloc_strdup(ctx, fname);
5349 return NT_STATUS_NO_MEMORY;
5351 p = strrchr_m(base_name, '/');
5355 base_name = talloc_strdup(ctx, "./");
5357 return NT_STATUS_NO_MEMORY;
5360 /* Append the new name. */
5361 base_name = talloc_asprintf_append(base_name,
5365 return NT_STATUS_NO_MEMORY;
5369 SMB_STRUCT_STAT sbuf;
5370 char *newname_last_component = NULL;
5374 status = unix_convert(ctx, conn, newname, False,
5376 &newname_last_component,
5379 /* If an error we expect this to be
5380 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5382 if (!NT_STATUS_IS_OK(status)
5383 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5388 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5389 fsp->fnum, fsp->fsp_name, base_name ));
5390 status = rename_internals_fsp(conn, fsp, base_name,
5391 newname_last_component, 0,
5394 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5395 fname, base_name ));
5396 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5397 overwrite, False, dest_has_wcard,
5398 FILE_WRITE_ATTRIBUTES);
5404 /****************************************************************************
5405 Deal with SMB_SET_POSIX_ACL.
5406 ****************************************************************************/
5408 #if defined(HAVE_POSIX_ACLS)
5409 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5414 SMB_STRUCT_STAT *psbuf)
5416 uint16 posix_acl_version;
5417 uint16 num_file_acls;
5418 uint16 num_def_acls;
5419 bool valid_file_acls = True;
5420 bool valid_def_acls = True;
5422 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5423 return NT_STATUS_INVALID_PARAMETER;
5425 posix_acl_version = SVAL(pdata,0);
5426 num_file_acls = SVAL(pdata,2);
5427 num_def_acls = SVAL(pdata,4);
5429 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5430 valid_file_acls = False;
5434 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5435 valid_def_acls = False;
5439 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5440 return NT_STATUS_INVALID_PARAMETER;
5443 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5444 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5445 return NT_STATUS_INVALID_PARAMETER;
5448 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5449 fname ? fname : fsp->fsp_name,
5450 (unsigned int)num_file_acls,
5451 (unsigned int)num_def_acls));
5453 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5454 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5455 return map_nt_error_from_unix(errno);
5458 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5459 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5460 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5461 return map_nt_error_from_unix(errno);
5463 return NT_STATUS_OK;
5467 /****************************************************************************
5468 Deal with SMB_SET_POSIX_LOCK.
5469 ****************************************************************************/
5471 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5472 const struct smb_request *req,
5478 SMB_BIG_UINT offset;
5480 bool blocking_lock = False;
5481 enum brl_type lock_type;
5483 NTSTATUS status = NT_STATUS_OK;
5485 if (fsp == NULL || fsp->fh->fd == -1) {
5486 return NT_STATUS_INVALID_HANDLE;
5489 if (total_data != POSIX_LOCK_DATA_SIZE) {
5490 return NT_STATUS_INVALID_PARAMETER;
5493 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5494 case POSIX_LOCK_TYPE_READ:
5495 lock_type = READ_LOCK;
5497 case POSIX_LOCK_TYPE_WRITE:
5498 /* Return the right POSIX-mappable error code for files opened read-only. */
5499 if (!fsp->can_write) {
5500 return NT_STATUS_INVALID_HANDLE;
5502 lock_type = WRITE_LOCK;
5504 case POSIX_LOCK_TYPE_UNLOCK:
5505 lock_type = UNLOCK_LOCK;
5508 return NT_STATUS_INVALID_PARAMETER;
5511 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5512 blocking_lock = False;
5513 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5514 blocking_lock = True;
5516 return NT_STATUS_INVALID_PARAMETER;
5519 if (!lp_blocking_locks(SNUM(conn))) {
5520 blocking_lock = False;
5523 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5524 #if defined(HAVE_LONGLONG)
5525 offset = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5526 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5527 count = (((SMB_BIG_UINT) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5528 ((SMB_BIG_UINT) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5529 #else /* HAVE_LONGLONG */
5530 offset = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5531 count = (SMB_BIG_UINT)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5532 #endif /* HAVE_LONGLONG */
5534 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5535 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5537 (unsigned int)lock_type,
5538 (unsigned int)lock_pid,
5542 if (lock_type == UNLOCK_LOCK) {
5543 status = do_unlock(smbd_messaging_context(),
5550 uint32 block_smbpid;
5552 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5563 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5565 * A blocking lock was requested. Package up
5566 * this smb into a queued request and push it
5567 * onto the blocking lock queue.
5569 if(push_blocking_lock_request(br_lck,
5572 -1, /* infinite timeout. */
5580 TALLOC_FREE(br_lck);
5584 TALLOC_FREE(br_lck);
5590 /****************************************************************************
5591 Deal with SMB_INFO_STANDARD.
5592 ****************************************************************************/
5594 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5599 const SMB_STRUCT_STAT *psbuf)
5601 struct timespec ts[2];
5603 if (total_data < 12) {
5604 return NT_STATUS_INVALID_PARAMETER;
5608 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5610 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5612 DEBUG(10,("smb_set_info_standard: file %s\n",
5613 fname ? fname : fsp->fsp_name ));
5615 return smb_set_file_time(conn,
5623 /****************************************************************************
5624 Deal with SMB_SET_FILE_BASIC_INFO.
5625 ****************************************************************************/
5627 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5632 SMB_STRUCT_STAT *psbuf)
5634 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5635 struct timespec write_time;
5636 struct timespec changed_time;
5638 struct timespec ts[2];
5639 NTSTATUS status = NT_STATUS_OK;
5640 bool setting_write_time = true;
5642 if (total_data < 36) {
5643 return NT_STATUS_INVALID_PARAMETER;
5646 /* Set the attributes */
5647 dosmode = IVAL(pdata,32);
5648 status = smb_set_file_dosmode(conn,
5652 if (!NT_STATUS_IS_OK(status)) {
5656 /* Ignore create time at offset pdata. */
5659 ts[0] = interpret_long_date(pdata+8);
5661 write_time = interpret_long_date(pdata+16);
5662 changed_time = interpret_long_date(pdata+24);
5665 ts[1] = timespec_min(&write_time, &changed_time);
5667 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5671 /* Prefer a defined time to an undefined one. */
5672 if (null_timespec(ts[1])) {
5673 if (null_timespec(write_time)) {
5674 ts[1] = changed_time;
5675 setting_write_time = false;
5681 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5682 fname ? fname : fsp->fsp_name ));
5684 return smb_set_file_time(conn,
5689 setting_write_time);
5692 /****************************************************************************
5693 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5694 ****************************************************************************/
5696 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5697 struct smb_request *req,
5702 SMB_STRUCT_STAT *psbuf)
5704 SMB_BIG_UINT allocation_size = 0;
5705 NTSTATUS status = NT_STATUS_OK;
5706 files_struct *new_fsp = NULL;
5708 if (!VALID_STAT(*psbuf)) {
5709 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5712 if (total_data < 8) {
5713 return NT_STATUS_INVALID_PARAMETER;
5716 allocation_size = (SMB_BIG_UINT)IVAL(pdata,0);
5717 #ifdef LARGE_SMB_OFF_T
5718 allocation_size |= (((SMB_BIG_UINT)IVAL(pdata,4)) << 32);
5719 #else /* LARGE_SMB_OFF_T */
5720 if (IVAL(pdata,4) != 0) {
5721 /* more than 32 bits? */
5722 return NT_STATUS_INVALID_PARAMETER;
5724 #endif /* LARGE_SMB_OFF_T */
5726 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5727 fname, (double)allocation_size ));
5729 if (allocation_size) {
5730 allocation_size = smb_roundup(conn, allocation_size);
5733 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5734 fname, (double)allocation_size ));
5736 if (fsp && fsp->fh->fd != -1) {
5737 /* Open file handle. */
5738 /* Only change if needed. */
5739 if (allocation_size != get_file_size(*psbuf)) {
5740 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5741 return map_nt_error_from_unix(errno);
5744 /* But always update the time. */
5746 * This is equivalent to a write. Ensure it's seen immediately
5747 * if there are no pending writes.
5749 trigger_write_time_update_immediate(fsp);
5750 return NT_STATUS_OK;
5753 /* Pathname or stat or directory file. */
5755 status = open_file_ntcreate(conn, req, fname, psbuf,
5757 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5760 FILE_ATTRIBUTE_NORMAL,
5761 FORCE_OPLOCK_BREAK_TO_NONE,
5764 if (!NT_STATUS_IS_OK(status)) {
5765 /* NB. We check for open_was_deferred in the caller. */
5769 /* Only change if needed. */
5770 if (allocation_size != get_file_size(*psbuf)) {
5771 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5772 status = map_nt_error_from_unix(errno);
5773 close_file(new_fsp,NORMAL_CLOSE);
5778 /* Changing the allocation size should set the last mod time. */
5780 * This is equivalent to a write. Ensure it's seen immediately
5781 * if there are no pending writes.
5783 trigger_write_time_update_immediate(new_fsp);
5785 close_file(new_fsp,NORMAL_CLOSE);
5786 return NT_STATUS_OK;
5789 /****************************************************************************
5790 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5791 ****************************************************************************/
5793 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5794 struct smb_request *req,
5799 SMB_STRUCT_STAT *psbuf)
5803 if (total_data < 8) {
5804 return NT_STATUS_INVALID_PARAMETER;
5807 size = IVAL(pdata,0);
5808 #ifdef LARGE_SMB_OFF_T
5809 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5810 #else /* LARGE_SMB_OFF_T */
5811 if (IVAL(pdata,4) != 0) {
5812 /* more than 32 bits? */
5813 return NT_STATUS_INVALID_PARAMETER;
5815 #endif /* LARGE_SMB_OFF_T */
5816 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5817 "file %s to %.0f\n", fname, (double)size ));
5819 return smb_set_file_size(conn, req,
5826 /****************************************************************************
5827 Allow a UNIX info mknod.
5828 ****************************************************************************/
5830 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5834 SMB_STRUCT_STAT *psbuf)
5836 uint32 file_type = IVAL(pdata,56);
5837 #if defined(HAVE_MAKEDEV)
5838 uint32 dev_major = IVAL(pdata,60);
5839 uint32 dev_minor = IVAL(pdata,68);
5841 SMB_DEV_T dev = (SMB_DEV_T)0;
5842 uint32 raw_unixmode = IVAL(pdata,84);
5846 if (total_data < 100) {
5847 return NT_STATUS_INVALID_PARAMETER;
5850 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5851 if (!NT_STATUS_IS_OK(status)) {
5855 #if defined(HAVE_MAKEDEV)
5856 dev = makedev(dev_major, dev_minor);
5859 switch (file_type) {
5860 #if defined(S_IFIFO)
5861 case UNIX_TYPE_FIFO:
5862 unixmode |= S_IFIFO;
5865 #if defined(S_IFSOCK)
5866 case UNIX_TYPE_SOCKET:
5867 unixmode |= S_IFSOCK;
5870 #if defined(S_IFCHR)
5871 case UNIX_TYPE_CHARDEV:
5872 unixmode |= S_IFCHR;
5875 #if defined(S_IFBLK)
5876 case UNIX_TYPE_BLKDEV:
5877 unixmode |= S_IFBLK;
5881 return NT_STATUS_INVALID_PARAMETER;
5884 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5885 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5887 /* Ok - do the mknod. */
5888 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5889 return map_nt_error_from_unix(errno);
5892 /* If any of the other "set" calls fail we
5893 * don't want to end up with a half-constructed mknod.
5896 if (lp_inherit_perms(SNUM(conn))) {
5897 inherit_access_posix_acl(
5898 conn, parent_dirname(fname),
5902 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5903 status = map_nt_error_from_unix(errno);
5904 SMB_VFS_UNLINK(conn,fname);
5907 return NT_STATUS_OK;
5910 /****************************************************************************
5911 Deal with SMB_SET_FILE_UNIX_BASIC.
5912 ****************************************************************************/
5914 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5915 struct smb_request *req,
5920 SMB_STRUCT_STAT *psbuf)
5922 struct timespec ts[2];
5923 uint32 raw_unixmode;
5926 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5927 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5928 NTSTATUS status = NT_STATUS_OK;
5929 bool delete_on_fail = False;
5930 enum perm_type ptype;
5932 if (total_data < 100) {
5933 return NT_STATUS_INVALID_PARAMETER;
5936 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5937 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5938 size=IVAL(pdata,0); /* first 8 Bytes are size */
5939 #ifdef LARGE_SMB_OFF_T
5940 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5941 #else /* LARGE_SMB_OFF_T */
5942 if (IVAL(pdata,4) != 0) {
5943 /* more than 32 bits? */
5944 return NT_STATUS_INVALID_PARAMETER;
5946 #endif /* LARGE_SMB_OFF_T */
5949 ts[0] = interpret_long_date(pdata+24); /* access_time */
5950 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5951 set_owner = (uid_t)IVAL(pdata,40);
5952 set_grp = (gid_t)IVAL(pdata,48);
5953 raw_unixmode = IVAL(pdata,84);
5955 if (VALID_STAT(*psbuf)) {
5956 if (S_ISDIR(psbuf->st_mode)) {
5957 ptype = PERM_EXISTING_DIR;
5959 ptype = PERM_EXISTING_FILE;
5962 ptype = PERM_NEW_FILE;
5965 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5966 if (!NT_STATUS_IS_OK(status)) {
5970 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5971 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5972 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
5974 if (!VALID_STAT(*psbuf)) {
5976 * The only valid use of this is to create character and block
5977 * devices, and named pipes. This is deprecated (IMHO) and
5978 * a new info level should be used for mknod. JRA.
5981 status = smb_unix_mknod(conn,
5986 if (!NT_STATUS_IS_OK(status)) {
5990 /* Ensure we don't try and change anything else. */
5991 raw_unixmode = SMB_MODE_NO_CHANGE;
5992 size = get_file_size(*psbuf);
5993 ts[0] = get_atimespec(psbuf);
5994 ts[1] = get_mtimespec(psbuf);
5996 * We continue here as we might want to change the
5999 delete_on_fail = True;
6003 /* Horrible backwards compatibility hack as an old server bug
6004 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6008 size = get_file_size(*psbuf);
6013 * Deal with the UNIX specific mode set.
6016 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6017 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6018 (unsigned int)unixmode, fname ));
6019 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6020 return map_nt_error_from_unix(errno);
6025 * Deal with the UNIX specific uid set.
6028 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6031 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6032 (unsigned int)set_owner, fname ));
6034 if (S_ISLNK(psbuf->st_mode)) {
6035 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6037 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6041 status = map_nt_error_from_unix(errno);
6042 if (delete_on_fail) {
6043 SMB_VFS_UNLINK(conn,fname);
6050 * Deal with the UNIX specific gid set.
6053 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6054 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6055 (unsigned int)set_owner, fname ));
6056 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6057 status = map_nt_error_from_unix(errno);
6058 if (delete_on_fail) {
6059 SMB_VFS_UNLINK(conn,fname);
6065 /* Deal with any size changes. */
6067 status = smb_set_file_size(conn, req,
6072 if (!NT_STATUS_IS_OK(status)) {
6076 /* Deal with any time changes. */
6078 return smb_set_file_time(conn,
6086 /****************************************************************************
6087 Deal with SMB_SET_FILE_UNIX_INFO2.
6088 ****************************************************************************/
6090 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6091 struct smb_request *req,
6096 SMB_STRUCT_STAT *psbuf)
6102 if (total_data < 116) {
6103 return NT_STATUS_INVALID_PARAMETER;
6106 /* Start by setting all the fields that are common between UNIX_BASIC
6109 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6111 if (!NT_STATUS_IS_OK(status)) {
6115 smb_fflags = IVAL(pdata, 108);
6116 smb_fmask = IVAL(pdata, 112);
6118 /* NB: We should only attempt to alter the file flags if the client
6119 * sends a non-zero mask.
6121 if (smb_fmask != 0) {
6122 int stat_fflags = 0;
6124 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6126 /* Client asked to alter a flag we don't understand. */
6127 return NT_STATUS_INVALID_PARAMETER;
6130 if (fsp && fsp->fh->fd != -1) {
6131 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6132 return NT_STATUS_NOT_SUPPORTED;
6134 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6135 return map_nt_error_from_unix(errno);
6140 /* XXX: need to add support for changing the create_time here. You
6141 * can do this for paths on Darwin with setattrlist(2). The right way
6142 * to hook this up is probably by extending the VFS utimes interface.
6145 return NT_STATUS_OK;
6148 /****************************************************************************
6149 Create a directory with POSIX semantics.
6150 ****************************************************************************/
6152 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6153 struct smb_request *req,
6157 SMB_STRUCT_STAT *psbuf,
6158 int *pdata_return_size)
6160 NTSTATUS status = NT_STATUS_OK;
6161 uint32 raw_unixmode = 0;
6162 uint32 mod_unixmode = 0;
6163 mode_t unixmode = (mode_t)0;
6164 files_struct *fsp = NULL;
6165 uint16 info_level_return = 0;
6167 char *pdata = *ppdata;
6169 if (total_data < 18) {
6170 return NT_STATUS_INVALID_PARAMETER;
6173 raw_unixmode = IVAL(pdata,8);
6174 /* Next 4 bytes are not yet defined. */
6176 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6177 if (!NT_STATUS_IS_OK(status)) {
6181 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6183 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6184 fname, (unsigned int)unixmode ));
6186 status = open_directory(conn, req,
6189 FILE_READ_ATTRIBUTES, /* Just a stat open */
6190 FILE_SHARE_NONE, /* Ignored for stat opens */
6197 if (NT_STATUS_IS_OK(status)) {
6198 close_file(fsp, NORMAL_CLOSE);
6201 info_level_return = SVAL(pdata,16);
6203 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6204 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6205 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6206 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6208 *pdata_return_size = 12;
6211 /* Realloc the data size */
6212 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6213 if (*ppdata == NULL) {
6214 *pdata_return_size = 0;
6215 return NT_STATUS_NO_MEMORY;
6219 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6220 SSVAL(pdata,2,0); /* No fnum. */
6221 SIVAL(pdata,4,info); /* Was directory created. */
6223 switch (info_level_return) {
6224 case SMB_QUERY_FILE_UNIX_BASIC:
6225 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6226 SSVAL(pdata,10,0); /* Padding. */
6227 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6229 case SMB_QUERY_FILE_UNIX_INFO2:
6230 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6231 SSVAL(pdata,10,0); /* Padding. */
6232 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6235 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6236 SSVAL(pdata,10,0); /* Padding. */
6243 /****************************************************************************
6244 Open/Create a file with POSIX semantics.
6245 ****************************************************************************/
6247 static NTSTATUS smb_posix_open(connection_struct *conn,
6248 struct smb_request *req,
6252 SMB_STRUCT_STAT *psbuf,
6253 int *pdata_return_size)
6255 bool extended_oplock_granted = False;
6256 char *pdata = *ppdata;
6258 uint32 wire_open_mode = 0;
6259 uint32 raw_unixmode = 0;
6260 uint32 mod_unixmode = 0;
6261 uint32 create_disp = 0;
6262 uint32 access_mask = 0;
6263 uint32 create_options = 0;
6264 NTSTATUS status = NT_STATUS_OK;
6265 mode_t unixmode = (mode_t)0;
6266 files_struct *fsp = NULL;
6267 int oplock_request = 0;
6269 uint16 info_level_return = 0;
6271 if (total_data < 18) {
6272 return NT_STATUS_INVALID_PARAMETER;
6275 flags = IVAL(pdata,0);
6276 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6277 if (oplock_request) {
6278 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6281 wire_open_mode = IVAL(pdata,4);
6283 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6284 return smb_posix_mkdir(conn, req,
6292 switch (wire_open_mode & SMB_ACCMODE) {
6294 access_mask = FILE_READ_DATA;
6297 access_mask = FILE_WRITE_DATA;
6300 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6303 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6304 (unsigned int)wire_open_mode ));
6305 return NT_STATUS_INVALID_PARAMETER;
6308 wire_open_mode &= ~SMB_ACCMODE;
6310 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6311 create_disp = FILE_CREATE;
6312 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6313 create_disp = FILE_OVERWRITE_IF;
6314 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6315 create_disp = FILE_OPEN_IF;
6317 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6318 (unsigned int)wire_open_mode ));
6319 return NT_STATUS_INVALID_PARAMETER;
6322 raw_unixmode = IVAL(pdata,8);
6323 /* Next 4 bytes are not yet defined. */
6325 status = unix_perms_from_wire(conn,
6328 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6331 if (!NT_STATUS_IS_OK(status)) {
6335 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6337 if (wire_open_mode & SMB_O_SYNC) {
6338 create_options |= FILE_WRITE_THROUGH;
6340 if (wire_open_mode & SMB_O_APPEND) {
6341 access_mask |= FILE_APPEND_DATA;
6343 if (wire_open_mode & SMB_O_DIRECT) {
6344 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6347 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6349 (unsigned int)wire_open_mode,
6350 (unsigned int)unixmode ));
6352 status = open_file_ntcreate(conn, req,
6356 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6358 0, /* no create options yet. */
6364 if (!NT_STATUS_IS_OK(status)) {
6368 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6369 extended_oplock_granted = True;
6372 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6373 extended_oplock_granted = True;
6376 info_level_return = SVAL(pdata,16);
6378 /* Allocate the correct return size. */
6380 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6381 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6382 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6383 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6385 *pdata_return_size = 12;
6388 /* Realloc the data size */
6389 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6390 if (*ppdata == NULL) {
6391 close_file(fsp,ERROR_CLOSE);
6392 *pdata_return_size = 0;
6393 return NT_STATUS_NO_MEMORY;
6397 if (extended_oplock_granted) {
6398 if (flags & REQUEST_BATCH_OPLOCK) {
6399 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6401 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6403 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6404 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6406 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6409 SSVAL(pdata,2,fsp->fnum);
6410 SIVAL(pdata,4,info); /* Was file created etc. */
6412 switch (info_level_return) {
6413 case SMB_QUERY_FILE_UNIX_BASIC:
6414 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6415 SSVAL(pdata,10,0); /* padding. */
6416 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6418 case SMB_QUERY_FILE_UNIX_INFO2:
6419 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6420 SSVAL(pdata,10,0); /* padding. */
6421 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6424 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6425 SSVAL(pdata,10,0); /* padding. */
6428 return NT_STATUS_OK;
6431 /****************************************************************************
6432 Delete a file with POSIX semantics.
6433 ****************************************************************************/
6435 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6436 struct smb_request *req,
6440 SMB_STRUCT_STAT *psbuf)
6442 NTSTATUS status = NT_STATUS_OK;
6443 files_struct *fsp = NULL;
6448 struct share_mode_lock *lck = NULL;
6450 if (total_data < 2) {
6451 return NT_STATUS_INVALID_PARAMETER;
6454 flags = SVAL(pdata,0);
6456 if (!VALID_STAT(*psbuf)) {
6457 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6460 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6461 !VALID_STAT_OF_DIR(*psbuf)) {
6462 return NT_STATUS_NOT_A_DIRECTORY;
6465 DEBUG(10,("smb_posix_unlink: %s %s\n",
6466 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6469 if (VALID_STAT_OF_DIR(*psbuf)) {
6470 status = open_directory(conn, req,
6474 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6477 FILE_FLAG_POSIX_SEMANTICS|0777,
6482 status = open_file_ntcreate(conn, req,
6486 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6489 FILE_FLAG_POSIX_SEMANTICS|0777,
6490 0, /* No oplock, but break existing ones. */
6495 if (!NT_STATUS_IS_OK(status)) {
6500 * Don't lie to client. If we can't really delete due to
6501 * non-POSIX opens return SHARING_VIOLATION.
6504 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6507 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6508 "lock for file %s\n", fsp->fsp_name));
6509 close_file(fsp, NORMAL_CLOSE);
6510 return NT_STATUS_INVALID_PARAMETER;
6514 * See if others still have the file open. If this is the case, then
6515 * don't delete. If all opens are POSIX delete we can set the delete
6516 * on close disposition.
6518 for (i=0; i<lck->num_share_modes; i++) {
6519 struct share_mode_entry *e = &lck->share_modes[i];
6520 if (is_valid_share_mode_entry(e)) {
6521 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6524 /* Fail with sharing violation. */
6525 close_file(fsp, NORMAL_CLOSE);
6527 return NT_STATUS_SHARING_VIOLATION;
6532 * Set the delete on close.
6534 status = smb_set_file_disposition_info(conn,
6541 if (!NT_STATUS_IS_OK(status)) {
6542 close_file(fsp, NORMAL_CLOSE);
6547 return close_file(fsp, NORMAL_CLOSE);
6550 /****************************************************************************
6551 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6552 ****************************************************************************/
6554 static void call_trans2setfilepathinfo(connection_struct *conn,
6555 struct smb_request *req,
6556 unsigned int tran_call,
6557 char **pparams, int total_params,
6558 char **ppdata, int total_data,
6559 unsigned int max_data_bytes)
6561 char *params = *pparams;
6562 char *pdata = *ppdata;
6564 SMB_STRUCT_STAT sbuf;
6566 files_struct *fsp = NULL;
6567 NTSTATUS status = NT_STATUS_OK;
6568 int data_return_size = 0;
6569 TALLOC_CTX *ctx = talloc_tos();
6572 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6578 if (tran_call == TRANSACT2_SETFILEINFO) {
6579 if (total_params < 4) {
6580 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6584 fsp = file_fsp(SVAL(params,0));
6585 /* Basic check for non-null fsp. */
6586 if (!check_fsp_open(conn, req, fsp)) {
6589 info_level = SVAL(params,2);
6591 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6593 reply_nterror(req, NT_STATUS_NO_MEMORY);
6597 if(fsp->is_directory || fsp->fh->fd == -1) {
6599 * This is actually a SETFILEINFO on a directory
6600 * handle (returned from an NT SMB). NT5.0 seems
6601 * to do this call. JRA.
6603 if (INFO_LEVEL_IS_UNIX(info_level)) {
6604 /* Always do lstat for UNIX calls. */
6605 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6606 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6607 reply_unixerror(req,ERRDOS,ERRbadpath);
6611 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6612 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6613 reply_unixerror(req,ERRDOS,ERRbadpath);
6617 } else if (fsp->print_file) {
6619 * Doing a DELETE_ON_CLOSE should cancel a print job.
6621 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6622 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6624 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6627 send_trans2_replies(conn, req, params, 2,
6632 reply_unixerror(req, ERRDOS, ERRbadpath);
6637 * Original code - this is an open file.
6639 if (!check_fsp(conn, req, fsp)) {
6643 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6644 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6645 reply_unixerror(req, ERRDOS, ERRbadfid);
6651 if (total_params < 7) {
6652 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6656 info_level = SVAL(params,0);
6657 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6658 total_params - 6, STR_TERMINATE,
6660 if (!NT_STATUS_IS_OK(status)) {
6661 reply_nterror(req, status);
6665 status = resolve_dfspath(ctx, conn,
6666 req->flags2 & FLAGS2_DFS_PATHNAMES,
6669 if (!NT_STATUS_IS_OK(status)) {
6670 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6671 reply_botherror(req,
6672 NT_STATUS_PATH_NOT_COVERED,
6673 ERRSRV, ERRbadpath);
6676 reply_nterror(req, status);
6680 status = unix_convert(ctx, conn, fname, False,
6681 &fname, NULL, &sbuf);
6682 if (!NT_STATUS_IS_OK(status)) {
6683 reply_nterror(req, status);
6687 status = check_name(conn, fname);
6688 if (!NT_STATUS_IS_OK(status)) {
6689 reply_nterror(req, status);
6693 if (INFO_LEVEL_IS_UNIX(info_level)) {
6695 * For CIFS UNIX extensions the target name may not exist.
6698 /* Always do lstat for UNIX calls. */
6699 SMB_VFS_LSTAT(conn,fname,&sbuf);
6701 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6702 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6703 reply_unixerror(req, ERRDOS, ERRbadpath);
6708 if (!CAN_WRITE(conn)) {
6709 reply_doserror(req, ERRSRV, ERRaccess);
6713 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6714 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6718 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6719 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6721 /* Realloc the parameter size */
6722 *pparams = (char *)SMB_REALLOC(*pparams,2);
6723 if (*pparams == NULL) {
6724 reply_nterror(req, NT_STATUS_NO_MEMORY);
6731 switch (info_level) {
6733 case SMB_INFO_STANDARD:
6735 status = smb_set_info_standard(conn,
6744 case SMB_INFO_SET_EA:
6746 status = smb_info_set_ea(conn,
6754 case SMB_SET_FILE_BASIC_INFO:
6755 case SMB_FILE_BASIC_INFORMATION:
6757 status = smb_set_file_basic_info(conn,
6766 case SMB_FILE_ALLOCATION_INFORMATION:
6767 case SMB_SET_FILE_ALLOCATION_INFO:
6769 status = smb_set_file_allocation_info(conn, req,
6778 case SMB_FILE_END_OF_FILE_INFORMATION:
6779 case SMB_SET_FILE_END_OF_FILE_INFO:
6781 status = smb_set_file_end_of_file_info(conn, req,
6790 case SMB_FILE_DISPOSITION_INFORMATION:
6791 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6794 /* JRA - We used to just ignore this on a path ?
6795 * Shouldn't this be invalid level on a pathname
6798 if (tran_call != TRANSACT2_SETFILEINFO) {
6799 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6802 status = smb_set_file_disposition_info(conn,
6811 case SMB_FILE_POSITION_INFORMATION:
6813 status = smb_file_position_information(conn,
6820 /* From tridge Samba4 :
6821 * MODE_INFORMATION in setfileinfo (I have no
6822 * idea what "mode information" on a file is - it takes a value of 0,
6823 * 2, 4 or 6. What could it be?).
6826 case SMB_FILE_MODE_INFORMATION:
6828 status = smb_file_mode_information(conn,
6835 * CIFS UNIX extensions.
6838 case SMB_SET_FILE_UNIX_BASIC:
6840 status = smb_set_file_unix_basic(conn, req,
6849 case SMB_SET_FILE_UNIX_INFO2:
6851 status = smb_set_file_unix_info2(conn, req,
6860 case SMB_SET_FILE_UNIX_LINK:
6862 if (tran_call != TRANSACT2_SETPATHINFO) {
6863 /* We must have a pathname for this. */
6864 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6867 status = smb_set_file_unix_link(conn, req, pdata,
6872 case SMB_SET_FILE_UNIX_HLINK:
6874 if (tran_call != TRANSACT2_SETPATHINFO) {
6875 /* We must have a pathname for this. */
6876 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6879 status = smb_set_file_unix_hlink(conn, req,
6885 case SMB_FILE_RENAME_INFORMATION:
6887 status = smb_file_rename_information(conn, req,
6893 #if defined(HAVE_POSIX_ACLS)
6894 case SMB_SET_POSIX_ACL:
6896 status = smb_set_posix_acl(conn,
6906 case SMB_SET_POSIX_LOCK:
6908 if (tran_call != TRANSACT2_SETFILEINFO) {
6909 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6912 status = smb_set_posix_lock(conn, req,
6913 pdata, total_data, fsp);
6917 case SMB_POSIX_PATH_OPEN:
6919 if (tran_call != TRANSACT2_SETPATHINFO) {
6920 /* We must have a pathname for this. */
6921 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6925 status = smb_posix_open(conn, req,
6934 case SMB_POSIX_PATH_UNLINK:
6936 if (tran_call != TRANSACT2_SETPATHINFO) {
6937 /* We must have a pathname for this. */
6938 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6942 status = smb_posix_unlink(conn, req,
6951 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6956 if (!NT_STATUS_IS_OK(status)) {
6957 if (open_was_deferred(req->mid)) {
6958 /* We have re-scheduled this call. */
6961 if (blocking_lock_was_deferred(req->mid)) {
6962 /* We have re-scheduled this call. */
6965 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6966 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6967 ERRSRV, ERRbadpath);
6970 if (info_level == SMB_POSIX_PATH_OPEN) {
6971 reply_openerror(req, status);
6975 reply_nterror(req, status);
6980 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
6986 /****************************************************************************
6987 Reply to a TRANS2_MKDIR (make directory with extended attributes).
6988 ****************************************************************************/
6990 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
6991 char **pparams, int total_params,
6992 char **ppdata, int total_data,
6993 unsigned int max_data_bytes)
6995 char *params = *pparams;
6996 char *pdata = *ppdata;
6997 char *directory = NULL;
6998 SMB_STRUCT_STAT sbuf;
6999 NTSTATUS status = NT_STATUS_OK;
7000 struct ea_list *ea_list = NULL;
7001 TALLOC_CTX *ctx = talloc_tos();
7003 if (!CAN_WRITE(conn)) {
7004 reply_doserror(req, ERRSRV, ERRaccess);
7008 if (total_params < 5) {
7009 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7013 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7014 total_params - 4, STR_TERMINATE,
7016 if (!NT_STATUS_IS_OK(status)) {
7017 reply_nterror(req, status);
7021 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7023 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7024 if (!NT_STATUS_IS_OK(status)) {
7025 reply_nterror(req, status);
7029 status = check_name(conn, directory);
7030 if (!NT_STATUS_IS_OK(status)) {
7031 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7032 reply_nterror(req, status);
7036 /* Any data in this call is an EA list. */
7037 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7038 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7043 * OS/2 workplace shell seems to send SET_EA requests of "null"
7044 * length (4 bytes containing IVAL 4).
7045 * They seem to have no effect. Bug #3212. JRA.
7048 if (total_data != 4) {
7049 if (total_data < 10) {
7050 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7054 if (IVAL(pdata,0) > total_data) {
7055 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7056 IVAL(pdata,0), (unsigned int)total_data));
7057 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7061 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7064 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7067 } else if (IVAL(pdata,0) != 4) {
7068 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7072 status = create_directory(conn, req, directory);
7074 if (!NT_STATUS_IS_OK(status)) {
7075 reply_nterror(req, status);
7079 /* Try and set any given EA. */
7081 status = set_ea(conn, NULL, directory, ea_list);
7082 if (!NT_STATUS_IS_OK(status)) {
7083 reply_nterror(req, status);
7088 /* Realloc the parameter and data sizes */
7089 *pparams = (char *)SMB_REALLOC(*pparams,2);
7090 if(*pparams == NULL) {
7091 reply_nterror(req, NT_STATUS_NO_MEMORY);
7098 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7103 /****************************************************************************
7104 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7105 We don't actually do this - we just send a null response.
7106 ****************************************************************************/
7108 static void call_trans2findnotifyfirst(connection_struct *conn,
7109 struct smb_request *req,
7110 char **pparams, int total_params,
7111 char **ppdata, int total_data,
7112 unsigned int max_data_bytes)
7114 static uint16 fnf_handle = 257;
7115 char *params = *pparams;
7118 if (total_params < 6) {
7119 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7123 info_level = SVAL(params,4);
7124 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7126 switch (info_level) {
7131 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7135 /* Realloc the parameter and data sizes */
7136 *pparams = (char *)SMB_REALLOC(*pparams,6);
7137 if (*pparams == NULL) {
7138 reply_nterror(req, NT_STATUS_NO_MEMORY);
7143 SSVAL(params,0,fnf_handle);
7144 SSVAL(params,2,0); /* No changes */
7145 SSVAL(params,4,0); /* No EA errors */
7152 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7157 /****************************************************************************
7158 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7159 changes). Currently this does nothing.
7160 ****************************************************************************/
7162 static void call_trans2findnotifynext(connection_struct *conn,
7163 struct smb_request *req,
7164 char **pparams, int total_params,
7165 char **ppdata, int total_data,
7166 unsigned int max_data_bytes)
7168 char *params = *pparams;
7170 DEBUG(3,("call_trans2findnotifynext\n"));
7172 /* Realloc the parameter and data sizes */
7173 *pparams = (char *)SMB_REALLOC(*pparams,4);
7174 if (*pparams == NULL) {
7175 reply_nterror(req, NT_STATUS_NO_MEMORY);
7180 SSVAL(params,0,0); /* No changes */
7181 SSVAL(params,2,0); /* No EA errors */
7183 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7188 /****************************************************************************
7189 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7190 ****************************************************************************/
7192 static void call_trans2getdfsreferral(connection_struct *conn,
7193 struct smb_request *req,
7194 char **pparams, int total_params,
7195 char **ppdata, int total_data,
7196 unsigned int max_data_bytes)
7198 char *params = *pparams;
7199 char *pathname = NULL;
7201 int max_referral_level;
7202 NTSTATUS status = NT_STATUS_OK;
7203 TALLOC_CTX *ctx = talloc_tos();
7205 DEBUG(10,("call_trans2getdfsreferral\n"));
7207 if (total_params < 3) {
7208 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7212 max_referral_level = SVAL(params,0);
7214 if(!lp_host_msdfs()) {
7215 reply_doserror(req, ERRDOS, ERRbadfunc);
7219 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7220 total_params - 2, STR_TERMINATE);
7222 reply_nterror(req, NT_STATUS_NOT_FOUND);
7225 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7226 ppdata,&status)) < 0) {
7227 reply_nterror(req, status);
7231 SSVAL(req->inbuf, smb_flg2,
7232 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7233 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7238 #define LMCAT_SPL 0x53
7239 #define LMFUNC_GETJOBID 0x60
7241 /****************************************************************************
7242 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7243 ****************************************************************************/
7245 static void call_trans2ioctl(connection_struct *conn,
7246 struct smb_request *req,
7247 char **pparams, int total_params,
7248 char **ppdata, int total_data,
7249 unsigned int max_data_bytes)
7251 char *pdata = *ppdata;
7252 files_struct *fsp = file_fsp(SVAL(req->inbuf,smb_vwv15));
7254 /* check for an invalid fid before proceeding */
7257 reply_doserror(req, ERRDOS, ERRbadfid);
7261 if ((SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7262 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7263 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7264 if (*ppdata == NULL) {
7265 reply_nterror(req, NT_STATUS_NO_MEMORY);
7270 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7271 CAN ACCEPT THIS IN UNICODE. JRA. */
7273 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7274 srvstr_push(pdata, req->flags2, pdata + 2,
7275 global_myname(), 15,
7276 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7277 srvstr_push(pdata, req->flags2, pdata+18,
7278 lp_servicename(SNUM(conn)), 13,
7279 STR_ASCII|STR_TERMINATE); /* Service name */
7280 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7285 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7286 reply_doserror(req, ERRSRV, ERRerror);
7289 /****************************************************************************
7290 Reply to a SMBfindclose (stop trans2 directory search).
7291 ****************************************************************************/
7293 void reply_findclose(struct smb_request *req)
7297 START_PROFILE(SMBfindclose);
7300 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7301 END_PROFILE(SMBfindclose);
7305 dptr_num = SVALS(req->inbuf,smb_vwv0);
7307 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7309 dptr_close(&dptr_num);
7311 reply_outbuf(req, 0, 0);
7313 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7315 END_PROFILE(SMBfindclose);
7319 /****************************************************************************
7320 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7321 ****************************************************************************/
7323 void reply_findnclose(struct smb_request *req)
7327 START_PROFILE(SMBfindnclose);
7330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7331 END_PROFILE(SMBfindnclose);
7335 dptr_num = SVAL(req->inbuf,smb_vwv0);
7337 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7339 /* We never give out valid handles for a
7340 findnotifyfirst - so any dptr_num is ok here.
7343 reply_outbuf(req, 0, 0);
7345 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7347 END_PROFILE(SMBfindnclose);
7351 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7352 struct trans_state *state)
7354 if (Protocol >= PROTOCOL_NT1) {
7355 req->flags2 |= 0x40; /* IS_LONG_NAME */
7356 SSVAL(req->inbuf,smb_flg2,req->flags2);
7359 if (conn->encrypt_level == Required && !req->encrypted) {
7360 if (state->call != TRANSACT2_QFSINFO &&
7361 state->call != TRANSACT2_SETFSINFO) {
7362 DEBUG(0,("handle_trans2: encryption required "
7364 (unsigned int)state->call));
7365 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7370 /* Now we must call the relevant TRANS2 function */
7371 switch(state->call) {
7372 case TRANSACT2_OPEN:
7374 START_PROFILE(Trans2_open);
7375 call_trans2open(conn, req,
7376 &state->param, state->total_param,
7377 &state->data, state->total_data,
7378 state->max_data_return);
7379 END_PROFILE(Trans2_open);
7383 case TRANSACT2_FINDFIRST:
7385 START_PROFILE(Trans2_findfirst);
7386 call_trans2findfirst(conn, req,
7387 &state->param, state->total_param,
7388 &state->data, state->total_data,
7389 state->max_data_return);
7390 END_PROFILE(Trans2_findfirst);
7394 case TRANSACT2_FINDNEXT:
7396 START_PROFILE(Trans2_findnext);
7397 call_trans2findnext(conn, req,
7398 &state->param, state->total_param,
7399 &state->data, state->total_data,
7400 state->max_data_return);
7401 END_PROFILE(Trans2_findnext);
7405 case TRANSACT2_QFSINFO:
7407 START_PROFILE(Trans2_qfsinfo);
7408 call_trans2qfsinfo(conn, req,
7409 &state->param, state->total_param,
7410 &state->data, state->total_data,
7411 state->max_data_return);
7412 END_PROFILE(Trans2_qfsinfo);
7416 case TRANSACT2_SETFSINFO:
7418 START_PROFILE(Trans2_setfsinfo);
7419 call_trans2setfsinfo(conn, req,
7420 &state->param, state->total_param,
7421 &state->data, state->total_data,
7422 state->max_data_return);
7423 END_PROFILE(Trans2_setfsinfo);
7427 case TRANSACT2_QPATHINFO:
7428 case TRANSACT2_QFILEINFO:
7430 START_PROFILE(Trans2_qpathinfo);
7431 call_trans2qfilepathinfo(conn, req, state->call,
7432 &state->param, state->total_param,
7433 &state->data, state->total_data,
7434 state->max_data_return);
7435 END_PROFILE(Trans2_qpathinfo);
7439 case TRANSACT2_SETPATHINFO:
7440 case TRANSACT2_SETFILEINFO:
7442 START_PROFILE(Trans2_setpathinfo);
7443 call_trans2setfilepathinfo(conn, req, state->call,
7444 &state->param, state->total_param,
7445 &state->data, state->total_data,
7446 state->max_data_return);
7447 END_PROFILE(Trans2_setpathinfo);
7451 case TRANSACT2_FINDNOTIFYFIRST:
7453 START_PROFILE(Trans2_findnotifyfirst);
7454 call_trans2findnotifyfirst(conn, req,
7455 &state->param, state->total_param,
7456 &state->data, state->total_data,
7457 state->max_data_return);
7458 END_PROFILE(Trans2_findnotifyfirst);
7462 case TRANSACT2_FINDNOTIFYNEXT:
7464 START_PROFILE(Trans2_findnotifynext);
7465 call_trans2findnotifynext(conn, req,
7466 &state->param, state->total_param,
7467 &state->data, state->total_data,
7468 state->max_data_return);
7469 END_PROFILE(Trans2_findnotifynext);
7473 case TRANSACT2_MKDIR:
7475 START_PROFILE(Trans2_mkdir);
7476 call_trans2mkdir(conn, req,
7477 &state->param, state->total_param,
7478 &state->data, state->total_data,
7479 state->max_data_return);
7480 END_PROFILE(Trans2_mkdir);
7484 case TRANSACT2_GET_DFS_REFERRAL:
7486 START_PROFILE(Trans2_get_dfs_referral);
7487 call_trans2getdfsreferral(conn, req,
7488 &state->param, state->total_param,
7489 &state->data, state->total_data,
7490 state->max_data_return);
7491 END_PROFILE(Trans2_get_dfs_referral);
7495 case TRANSACT2_IOCTL:
7497 START_PROFILE(Trans2_ioctl);
7498 call_trans2ioctl(conn, req,
7499 &state->param, state->total_param,
7500 &state->data, state->total_data,
7501 state->max_data_return);
7502 END_PROFILE(Trans2_ioctl);
7507 /* Error in request */
7508 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7509 reply_doserror(req, ERRSRV,ERRerror);
7513 /****************************************************************************
7514 Reply to a SMBtrans2.
7515 ****************************************************************************/
7517 void reply_trans2(struct smb_request *req)
7519 connection_struct *conn = req->conn;
7524 unsigned int tran_call;
7526 unsigned int av_size;
7527 struct trans_state *state;
7530 START_PROFILE(SMBtrans2);
7532 if (req->wct < 14) {
7533 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7534 END_PROFILE(SMBtrans2);
7538 dsoff = SVAL(req->inbuf, smb_dsoff);
7539 dscnt = SVAL(req->inbuf, smb_dscnt);
7540 psoff = SVAL(req->inbuf, smb_psoff);
7541 pscnt = SVAL(req->inbuf, smb_pscnt);
7542 tran_call = SVAL(req->inbuf, smb_setup0);
7543 size = smb_len(req->inbuf) + 4;
7544 av_size = smb_len(req->inbuf);
7546 result = allow_new_trans(conn->pending_trans, req->mid);
7547 if (!NT_STATUS_IS_OK(result)) {
7548 DEBUG(2, ("Got invalid trans2 request: %s\n",
7549 nt_errstr(result)));
7550 reply_nterror(req, result);
7551 END_PROFILE(SMBtrans2);
7556 switch (tran_call) {
7557 /* List the allowed trans2 calls on IPC$ */
7558 case TRANSACT2_OPEN:
7559 case TRANSACT2_GET_DFS_REFERRAL:
7560 case TRANSACT2_QFILEINFO:
7561 case TRANSACT2_QFSINFO:
7562 case TRANSACT2_SETFSINFO:
7565 reply_doserror(req, ERRSRV, ERRaccess);
7566 END_PROFILE(SMBtrans2);
7571 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7572 DEBUG(0, ("talloc failed\n"));
7573 reply_nterror(req, NT_STATUS_NO_MEMORY);
7574 END_PROFILE(SMBtrans2);
7578 state->cmd = SMBtrans2;
7580 state->mid = req->mid;
7581 state->vuid = req->vuid;
7582 state->setup_count = SVAL(req->inbuf, smb_suwcnt);
7583 state->setup = NULL;
7584 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7585 state->param = NULL;
7586 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7588 state->max_param_return = SVAL(req->inbuf, smb_mprcnt);
7589 state->max_data_return = SVAL(req->inbuf, smb_mdrcnt);
7590 state->max_setup_return = SVAL(req->inbuf, smb_msrcnt);
7591 state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0);
7592 state->one_way = BITSETW(req->inbuf+smb_vwv5,1);
7594 state->call = tran_call;
7596 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7597 is so as a sanity check */
7598 if (state->setup_count != 1) {
7600 * Need to have rc=0 for ioctl to get job id for OS/2.
7601 * Network printing will fail if function is not successful.
7602 * Similar function in reply.c will be used if protocol
7603 * is LANMAN1.0 instead of LM1.2X002.
7604 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7605 * outbuf doesn't have to be set(only job id is used).
7607 if ( (state->setup_count == 4)
7608 && (tran_call == TRANSACT2_IOCTL)
7609 && (SVAL(req->inbuf,(smb_setup+4)) == LMCAT_SPL)
7610 && (SVAL(req->inbuf,(smb_setup+6)) == LMFUNC_GETJOBID)) {
7611 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7613 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7614 DEBUG(2,("Transaction is %d\n",tran_call));
7616 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7617 END_PROFILE(SMBtrans2);
7622 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7625 if (state->total_data) {
7626 /* Can't use talloc here, the core routines do realloc on the
7627 * params and data. */
7628 state->data = (char *)SMB_MALLOC(state->total_data);
7629 if (state->data == NULL) {
7630 DEBUG(0,("reply_trans2: data malloc fail for %u "
7631 "bytes !\n", (unsigned int)state->total_data));
7633 reply_nterror(req, NT_STATUS_NO_MEMORY);
7634 END_PROFILE(SMBtrans2);
7638 if (dscnt > state->total_data ||
7639 dsoff+dscnt < dsoff) {
7643 if (dsoff > av_size ||
7645 dsoff+dscnt > av_size) {
7649 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7652 if (state->total_param) {
7653 /* Can't use talloc here, the core routines do realloc on the
7654 * params and data. */
7655 state->param = (char *)SMB_MALLOC(state->total_param);
7656 if (state->param == NULL) {
7657 DEBUG(0,("reply_trans: param malloc fail for %u "
7658 "bytes !\n", (unsigned int)state->total_param));
7659 SAFE_FREE(state->data);
7661 reply_nterror(req, NT_STATUS_NO_MEMORY);
7662 END_PROFILE(SMBtrans2);
7666 if (pscnt > state->total_param ||
7667 psoff+pscnt < psoff) {
7671 if (psoff > av_size ||
7673 psoff+pscnt > av_size) {
7677 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7680 state->received_data = dscnt;
7681 state->received_param = pscnt;
7683 if ((state->received_param == state->total_param) &&
7684 (state->received_data == state->total_data)) {
7686 handle_trans2(conn, req, state);
7688 SAFE_FREE(state->data);
7689 SAFE_FREE(state->param);
7691 END_PROFILE(SMBtrans2);
7695 DLIST_ADD(conn->pending_trans, state);
7697 /* We need to send an interim response then receive the rest
7698 of the parameter/data bytes */
7699 reply_outbuf(req, 0, 0);
7700 show_msg((char *)req->outbuf);
7701 END_PROFILE(SMBtrans2);
7706 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7707 SAFE_FREE(state->data);
7708 SAFE_FREE(state->param);
7710 END_PROFILE(SMBtrans2);
7711 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7715 /****************************************************************************
7716 Reply to a SMBtranss2
7717 ****************************************************************************/
7719 void reply_transs2(struct smb_request *req)
7721 connection_struct *conn = req->conn;
7722 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7723 struct trans_state *state;
7725 unsigned int av_size;
7727 START_PROFILE(SMBtranss2);
7729 show_msg((char *)req->inbuf);
7732 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7733 END_PROFILE(SMBtranss2);
7737 size = smb_len(req->inbuf)+4;
7738 av_size = smb_len(req->inbuf);
7740 for (state = conn->pending_trans; state != NULL;
7741 state = state->next) {
7742 if (state->mid == req->mid) {
7747 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7748 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7749 END_PROFILE(SMBtranss2);
7753 /* Revise state->total_param and state->total_data in case they have
7754 changed downwards */
7756 if (SVAL(req->inbuf, smb_tpscnt) < state->total_param)
7757 state->total_param = SVAL(req->inbuf, smb_tpscnt);
7758 if (SVAL(req->inbuf, smb_tdscnt) < state->total_data)
7759 state->total_data = SVAL(req->inbuf, smb_tdscnt);
7761 pcnt = SVAL(req->inbuf, smb_spscnt);
7762 poff = SVAL(req->inbuf, smb_spsoff);
7763 pdisp = SVAL(req->inbuf, smb_spsdisp);
7765 dcnt = SVAL(req->inbuf, smb_sdscnt);
7766 doff = SVAL(req->inbuf, smb_sdsoff);
7767 ddisp = SVAL(req->inbuf, smb_sdsdisp);
7769 state->received_param += pcnt;
7770 state->received_data += dcnt;
7772 if ((state->received_data > state->total_data) ||
7773 (state->received_param > state->total_param))
7777 if (pdisp > state->total_param ||
7778 pcnt > state->total_param ||
7779 pdisp+pcnt > state->total_param ||
7780 pdisp+pcnt < pdisp) {
7784 if (poff > av_size ||
7786 poff+pcnt > av_size ||
7791 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,
7796 if (ddisp > state->total_data ||
7797 dcnt > state->total_data ||
7798 ddisp+dcnt > state->total_data ||
7799 ddisp+dcnt < ddisp) {
7803 if (ddisp > av_size ||
7805 ddisp+dcnt > av_size ||
7806 ddisp+dcnt < ddisp) {
7810 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,
7814 if ((state->received_param < state->total_param) ||
7815 (state->received_data < state->total_data)) {
7816 END_PROFILE(SMBtranss2);
7821 * construct_reply_common will copy smb_com from inbuf to
7822 * outbuf. SMBtranss2 is wrong here.
7824 SCVAL(req->inbuf,smb_com,SMBtrans2);
7826 handle_trans2(conn, req, state);
7828 DLIST_REMOVE(conn->pending_trans, state);
7829 SAFE_FREE(state->data);
7830 SAFE_FREE(state->param);
7833 END_PROFILE(SMBtranss2);
7838 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7839 DLIST_REMOVE(conn->pending_trans, state);
7840 SAFE_FREE(state->data);
7841 SAFE_FREE(state->param);
7843 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7844 END_PROFILE(SMBtranss2);