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 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
62 /********************************************************************
63 Given a stat buffer return the allocated size on disk, taking into
65 ********************************************************************/
67 uint64_t 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 = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_blocks;
78 ret = (uint64_t)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);
772 * We might have SMBtrans2s in req which was transferred to
773 * the outbuf, fix that.
775 SCVAL(req->outbuf, smb_com, SMBtrans2);
777 /* Set total params and data to be sent */
778 SSVAL(req->outbuf,smb_tprcnt,paramsize);
779 SSVAL(req->outbuf,smb_tdrcnt,datasize);
781 /* Calculate how many parameters and data we can fit into
782 * this packet. Parameters get precedence
785 params_sent_thistime = MIN(params_to_send,useable_space);
786 data_sent_thistime = useable_space - params_sent_thistime;
787 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
789 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
791 /* smb_proff is the offset from the start of the SMB header to the
792 parameter bytes, however the first 4 bytes of outbuf are
793 the Netbios over TCP header. Thus use smb_base() to subtract
794 them from the calculation */
796 SSVAL(req->outbuf,smb_proff,
797 ((smb_buf(req->outbuf)+alignment_offset)
798 - smb_base(req->outbuf)));
800 if(params_sent_thistime == 0)
801 SSVAL(req->outbuf,smb_prdisp,0);
803 /* Absolute displacement of param bytes sent in this packet */
804 SSVAL(req->outbuf,smb_prdisp,pp - params);
806 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
807 if(data_sent_thistime == 0) {
808 SSVAL(req->outbuf,smb_droff,0);
809 SSVAL(req->outbuf,smb_drdisp, 0);
811 /* The offset of the data bytes is the offset of the
812 parameter bytes plus the number of parameters being sent this time */
813 SSVAL(req->outbuf, smb_droff,
814 ((smb_buf(req->outbuf)+alignment_offset)
815 - smb_base(req->outbuf))
816 + params_sent_thistime + data_alignment_offset);
817 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
820 /* Initialize the padding for alignment */
822 if (alignment_offset != 0) {
823 memset(smb_buf(req->outbuf), 0, alignment_offset);
826 /* Copy the param bytes into the packet */
828 if(params_sent_thistime) {
829 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
830 params_sent_thistime);
833 /* Copy in the data bytes */
834 if(data_sent_thistime) {
835 if (data_alignment_offset != 0) {
836 memset((smb_buf(req->outbuf)+alignment_offset+
837 params_sent_thistime), 0,
838 data_alignment_offset);
840 memcpy(smb_buf(req->outbuf)+alignment_offset
841 +params_sent_thistime+data_alignment_offset,
842 pd,data_sent_thistime);
845 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
846 params_sent_thistime, data_sent_thistime, useable_space));
847 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
848 params_to_send, data_to_send, paramsize, datasize));
851 error_packet_set((char *)req->outbuf,
852 ERRDOS,ERRbufferoverflow,
853 STATUS_BUFFER_OVERFLOW,
857 /* Send the packet */
858 show_msg((char *)req->outbuf);
859 if (!srv_send_smb(smbd_server_fd(),
861 IS_CONN_ENCRYPTED(conn)))
862 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
864 TALLOC_FREE(req->outbuf);
866 pp += params_sent_thistime;
867 pd += data_sent_thistime;
869 params_to_send -= params_sent_thistime;
870 data_to_send -= data_sent_thistime;
873 if(params_to_send < 0 || data_to_send < 0) {
874 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
875 params_to_send, data_to_send));
883 /****************************************************************************
884 Reply to a TRANSACT2_OPEN.
885 ****************************************************************************/
887 static void call_trans2open(connection_struct *conn,
888 struct smb_request *req,
889 char **pparams, int total_params,
890 char **ppdata, int total_data,
891 unsigned int max_data_bytes)
893 char *params = *pparams;
894 char *pdata = *ppdata;
899 bool return_additional_info;
910 SMB_STRUCT_STAT sbuf;
913 struct ea_list *ea_list = NULL;
918 uint32 create_disposition;
919 uint32 create_options = 0;
920 TALLOC_CTX *ctx = talloc_tos();
923 * Ensure we have enough parameters to perform the operation.
926 if (total_params < 29) {
927 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
931 flags = SVAL(params, 0);
932 deny_mode = SVAL(params, 2);
933 open_attr = SVAL(params,6);
934 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
935 if (oplock_request) {
936 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
940 return_additional_info = BITSETW(params,0);
941 open_sattr = SVAL(params, 4);
942 open_time = make_unix_date3(params+8);
944 open_ofun = SVAL(params,12);
945 open_size = IVAL(params,14);
949 reply_doserror(req, ERRSRV, ERRaccess);
953 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
954 total_params - 28, STR_TERMINATE,
956 if (!NT_STATUS_IS_OK(status)) {
957 reply_nterror(req, status);
961 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
962 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
963 (unsigned int)open_ofun, open_size));
965 if (open_ofun == 0) {
966 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
970 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
975 reply_doserror(req, ERRDOS, ERRbadaccess);
979 /* Any data in this call is an EA list. */
980 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
981 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
985 if (total_data != 4) {
986 if (total_data < 10) {
987 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
991 if (IVAL(pdata,0) > total_data) {
992 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
993 IVAL(pdata,0), (unsigned int)total_data));
994 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
998 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1001 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1004 } else if (IVAL(pdata,0) != 4) {
1005 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1009 status = SMB_VFS_CREATE_FILE(
1012 0, /* root_dir_fid */
1014 true, /* is_dos_path */
1015 access_mask, /* access_mask */
1016 share_mode, /* share_access */
1017 create_disposition, /* create_disposition*/
1018 create_options, /* create_options */
1019 open_attr, /* file_attributes */
1020 oplock_request, /* oplock_request */
1021 open_size, /* allocation_size */
1023 ea_list, /* ea_list */
1025 &smb_action, /* pinfo */
1028 if (!NT_STATUS_IS_OK(status)) {
1029 if (open_was_deferred(req->mid)) {
1030 /* We have re-scheduled this call. */
1033 reply_openerror(req, status);
1037 size = get_file_size(sbuf);
1038 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1039 mtime = sbuf.st_mtime;
1040 inode = sbuf.st_ino;
1042 close_file(req, fsp, ERROR_CLOSE);
1043 reply_doserror(req, ERRDOS,ERRnoaccess);
1047 /* Realloc the size of parameters and data we will return */
1048 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1049 if(*pparams == NULL ) {
1050 reply_nterror(req, NT_STATUS_NO_MEMORY);
1055 SSVAL(params,0,fsp->fnum);
1056 SSVAL(params,2,fattr);
1057 srv_put_dos_date2(params,4, mtime);
1058 SIVAL(params,8, (uint32)size);
1059 SSVAL(params,12,deny_mode);
1060 SSVAL(params,14,0); /* open_type - file or directory. */
1061 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1063 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1064 smb_action |= EXTENDED_OPLOCK_GRANTED;
1067 SSVAL(params,18,smb_action);
1070 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1072 SIVAL(params,20,inode);
1073 SSVAL(params,24,0); /* Padding. */
1075 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1076 SIVAL(params, 26, ea_size);
1078 SIVAL(params, 26, 0);
1081 /* Send the required number of replies */
1082 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1085 /*********************************************************
1086 Routine to check if a given string matches exactly.
1087 as a special case a mask of "." does NOT match. That
1088 is required for correct wildcard semantics
1089 Case can be significant or not.
1090 **********************************************************/
1092 static bool exact_match(connection_struct *conn,
1096 if (mask[0] == '.' && mask[1] == 0)
1098 if (conn->case_sensitive)
1099 return strcmp(str,mask)==0;
1100 if (StrCaseCmp(str,mask) != 0) {
1103 if (dptr_has_wild(conn->dirptr)) {
1109 /****************************************************************************
1110 Return the filetype for UNIX extensions.
1111 ****************************************************************************/
1113 static uint32 unix_filetype(mode_t mode)
1116 return UNIX_TYPE_FILE;
1117 else if(S_ISDIR(mode))
1118 return UNIX_TYPE_DIR;
1120 else if(S_ISLNK(mode))
1121 return UNIX_TYPE_SYMLINK;
1124 else if(S_ISCHR(mode))
1125 return UNIX_TYPE_CHARDEV;
1128 else if(S_ISBLK(mode))
1129 return UNIX_TYPE_BLKDEV;
1132 else if(S_ISFIFO(mode))
1133 return UNIX_TYPE_FIFO;
1136 else if(S_ISSOCK(mode))
1137 return UNIX_TYPE_SOCKET;
1140 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1141 return UNIX_TYPE_UNKNOWN;
1144 /****************************************************************************
1145 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1146 ****************************************************************************/
1148 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1150 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1151 SMB_STRUCT_STAT *psbuf,
1153 enum perm_type ptype,
1158 if (perms == SMB_MODE_NO_CHANGE) {
1159 if (!VALID_STAT(*psbuf)) {
1160 return NT_STATUS_INVALID_PARAMETER;
1162 *ret_perms = psbuf->st_mode;
1163 return NT_STATUS_OK;
1167 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1168 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1169 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1170 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1171 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1172 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1173 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1174 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1175 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1177 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1180 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1183 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1188 /* Apply mode mask */
1189 ret &= lp_create_mask(SNUM(conn));
1190 /* Add in force bits */
1191 ret |= lp_force_create_mode(SNUM(conn));
1194 ret &= lp_dir_mask(SNUM(conn));
1195 /* Add in force bits */
1196 ret |= lp_force_dir_mode(SNUM(conn));
1198 case PERM_EXISTING_FILE:
1199 /* Apply mode mask */
1200 ret &= lp_security_mask(SNUM(conn));
1201 /* Add in force bits */
1202 ret |= lp_force_security_mode(SNUM(conn));
1204 case PERM_EXISTING_DIR:
1205 /* Apply mode mask */
1206 ret &= lp_dir_security_mask(SNUM(conn));
1207 /* Add in force bits */
1208 ret |= lp_force_dir_security_mode(SNUM(conn));
1213 return NT_STATUS_OK;
1216 /****************************************************************************
1217 Needed to show the msdfs symlinks as directories. Modifies psbuf
1218 to be a directory if it's a msdfs link.
1219 ****************************************************************************/
1221 static bool check_msdfs_link(connection_struct *conn,
1222 const char *pathname,
1223 SMB_STRUCT_STAT *psbuf)
1225 int saved_errno = errno;
1226 if(lp_host_msdfs() &&
1227 lp_msdfs_root(SNUM(conn)) &&
1228 is_msdfs_link(conn, pathname, psbuf)) {
1230 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1233 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1234 errno = saved_errno;
1237 errno = saved_errno;
1242 /****************************************************************************
1243 Get a level dependent lanman2 dir entry.
1244 ****************************************************************************/
1246 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1247 connection_struct *conn,
1249 const char *path_mask,
1252 int requires_resume_key,
1258 int space_remaining,
1260 bool *got_exact_match,
1261 int *last_entry_off,
1262 struct ea_list *name_list)
1266 SMB_STRUCT_STAT sbuf;
1267 const char *mask = NULL;
1268 char *pathreal = NULL;
1269 const char *fname = NULL;
1270 char *p, *q, *pdata = *ppdata;
1274 SMB_OFF_T file_size = 0;
1275 uint64_t allocation_size = 0;
1277 struct timespec mdate_ts, adate_ts, create_date_ts;
1278 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1280 char *last_entry_ptr;
1282 uint32 nt_extmode; /* Used for NT connections instead of mode */
1283 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1284 bool check_mangled_names = lp_manglednames(conn->params);
1285 char mangled_name[13]; /* mangled 8.3 name. */
1287 *out_of_space = False;
1288 *got_exact_match = False;
1290 ZERO_STRUCT(mdate_ts);
1291 ZERO_STRUCT(adate_ts);
1292 ZERO_STRUCT(create_date_ts);
1294 if (!conn->dirptr) {
1298 p = strrchr_m(path_mask,'/');
1301 mask = talloc_strdup(ctx,"*.*");
1311 bool ms_dfs_link = False;
1313 /* Needed if we run out of space */
1314 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1315 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1318 * Due to bugs in NT client redirectors we are not using
1319 * resume keys any more - set them to zero.
1320 * Check out the related comments in findfirst/findnext.
1326 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1327 (long)conn->dirptr,curr_dirpos));
1334 * fname may get mangled, dname is never mangled.
1335 * Whenever we're accessing the filesystem we use
1336 * pathreal which is composed from dname.
1342 /* Mangle fname if it's an illegal name. */
1343 if (mangle_must_mangle(dname,conn->params)) {
1344 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1345 continue; /* Error - couldn't mangle. */
1347 fname = mangled_name;
1350 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1351 got_match = mask_match(fname, mask, conn->case_sensitive);
1354 if(!got_match && check_mangled_names &&
1355 !mangle_is_8_3(fname, False, conn->params)) {
1357 * It turns out that NT matches wildcards against
1358 * both long *and* short names. This may explain some
1359 * of the wildcard wierdness from old DOS clients
1360 * that some people have been seeing.... JRA.
1362 /* Force the mangling into 8.3. */
1363 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1364 continue; /* Error - couldn't mangle. */
1367 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1368 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1373 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1375 if (dont_descend && !isdots) {
1381 pathreal = talloc_asprintf(ctx,
1386 pathreal = talloc_asprintf(ctx,
1396 if (INFO_LEVEL_IS_UNIX(info_level)) {
1397 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1398 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1399 pathreal,strerror(errno)));
1400 TALLOC_FREE(pathreal);
1403 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1404 /* Needed to show the msdfs symlinks as
1407 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1409 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1410 pathreal,strerror(errno)));
1411 TALLOC_FREE(pathreal);
1417 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1419 mode = dos_mode(conn,pathreal,&sbuf);
1422 if (!dir_check_ftype(conn,mode,dirtype)) {
1423 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1424 TALLOC_FREE(pathreal);
1428 if (!(mode & aDIR)) {
1429 file_size = get_file_size(sbuf);
1431 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1433 mdate_ts = get_mtimespec(&sbuf);
1434 adate_ts = get_atimespec(&sbuf);
1435 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1437 if (ask_sharemode) {
1438 struct timespec write_time_ts;
1439 struct file_id fileid;
1441 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1442 get_file_infos(fileid, NULL, &write_time_ts);
1443 if (!null_timespec(write_time_ts)) {
1444 mdate_ts = write_time_ts;
1448 if (lp_dos_filetime_resolution(SNUM(conn))) {
1449 dos_filetime_timespec(&create_date_ts);
1450 dos_filetime_timespec(&mdate_ts);
1451 dos_filetime_timespec(&adate_ts);
1454 create_date = convert_timespec_to_time_t(create_date_ts);
1455 mdate = convert_timespec_to_time_t(mdate_ts);
1456 adate = convert_timespec_to_time_t(adate_ts);
1458 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1462 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1469 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1471 switch (info_level) {
1472 case SMB_FIND_INFO_STANDARD:
1473 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1474 if(requires_resume_key) {
1478 srv_put_dos_date2(p,0,create_date);
1479 srv_put_dos_date2(p,4,adate);
1480 srv_put_dos_date2(p,8,mdate);
1481 SIVAL(p,12,(uint32)file_size);
1482 SIVAL(p,16,(uint32)allocation_size);
1486 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1487 p += ucs2_align(base_data, p, 0);
1489 len = srvstr_push(base_data, flags2, p,
1490 fname, PTR_DIFF(end_data, p),
1492 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1494 SCVAL(nameptr, -1, len - 2);
1496 SCVAL(nameptr, -1, 0);
1500 SCVAL(nameptr, -1, len - 1);
1502 SCVAL(nameptr, -1, 0);
1508 case SMB_FIND_EA_SIZE:
1509 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1510 if(requires_resume_key) {
1514 srv_put_dos_date2(p,0,create_date);
1515 srv_put_dos_date2(p,4,adate);
1516 srv_put_dos_date2(p,8,mdate);
1517 SIVAL(p,12,(uint32)file_size);
1518 SIVAL(p,16,(uint32)allocation_size);
1521 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1522 SIVAL(p,22,ea_size); /* Extended attributes */
1526 len = srvstr_push(base_data, flags2,
1527 p, fname, PTR_DIFF(end_data, p),
1528 STR_TERMINATE | STR_NOALIGN);
1529 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1542 SCVAL(nameptr,0,len);
1544 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1547 case SMB_FIND_EA_LIST:
1549 struct ea_list *file_list = NULL;
1552 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1556 if(requires_resume_key) {
1560 srv_put_dos_date2(p,0,create_date);
1561 srv_put_dos_date2(p,4,adate);
1562 srv_put_dos_date2(p,8,mdate);
1563 SIVAL(p,12,(uint32)file_size);
1564 SIVAL(p,16,(uint32)allocation_size);
1566 p += 22; /* p now points to the EA area. */
1568 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1569 name_list = ea_list_union(name_list, file_list, &ea_len);
1571 /* We need to determine if this entry will fit in the space available. */
1572 /* Max string size is 255 bytes. */
1573 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1574 /* Move the dirptr back to prev_dirpos */
1575 dptr_SeekDir(conn->dirptr, prev_dirpos);
1576 *out_of_space = True;
1577 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1578 return False; /* Not finished - just out of space */
1581 /* Push the ea_data followed by the name. */
1582 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1584 len = srvstr_push(base_data, flags2,
1585 p + 1, fname, PTR_DIFF(end_data, p+1),
1586 STR_TERMINATE | STR_NOALIGN);
1587 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1600 SCVAL(nameptr,0,len);
1602 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1606 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1607 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1608 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1610 SIVAL(p,0,reskey); p += 4;
1611 put_long_date_timespec(p,create_date_ts); p += 8;
1612 put_long_date_timespec(p,adate_ts); p += 8;
1613 put_long_date_timespec(p,mdate_ts); p += 8;
1614 put_long_date_timespec(p,mdate_ts); p += 8;
1615 SOFF_T(p,0,file_size); p += 8;
1616 SOFF_T(p,0,allocation_size); p += 8;
1617 SIVAL(p,0,nt_extmode); p += 4;
1618 q = p; p += 4; /* q is placeholder for name length. */
1620 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1621 SIVAL(p,0,ea_size); /* Extended attributes */
1624 /* Clear the short name buffer. This is
1625 * IMPORTANT as not doing so will trigger
1626 * a Win2k client bug. JRA.
1628 if (!was_8_3 && check_mangled_names) {
1629 if (!name_to_8_3(fname,mangled_name,True,
1631 /* Error - mangle failed ! */
1632 memset(mangled_name,'\0',12);
1634 mangled_name[12] = 0;
1635 len = srvstr_push(base_data, flags2,
1636 p+2, mangled_name, 24,
1637 STR_UPPER|STR_UNICODE);
1639 memset(p + 2 + len,'\0',24 - len);
1646 len = srvstr_push(base_data, flags2, p,
1647 fname, PTR_DIFF(end_data, p),
1648 STR_TERMINATE_ASCII);
1651 SIVAL(p,0,0); /* Ensure any padding is null. */
1652 len = PTR_DIFF(p, pdata);
1653 len = (len + 3) & ~3;
1658 case SMB_FIND_FILE_DIRECTORY_INFO:
1659 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1661 SIVAL(p,0,reskey); p += 4;
1662 put_long_date_timespec(p,create_date_ts); p += 8;
1663 put_long_date_timespec(p,adate_ts); p += 8;
1664 put_long_date_timespec(p,mdate_ts); p += 8;
1665 put_long_date_timespec(p,mdate_ts); p += 8;
1666 SOFF_T(p,0,file_size); p += 8;
1667 SOFF_T(p,0,allocation_size); p += 8;
1668 SIVAL(p,0,nt_extmode); p += 4;
1669 len = srvstr_push(base_data, flags2,
1670 p + 4, fname, PTR_DIFF(end_data, p+4),
1671 STR_TERMINATE_ASCII);
1674 SIVAL(p,0,0); /* Ensure any padding is null. */
1675 len = PTR_DIFF(p, pdata);
1676 len = (len + 3) & ~3;
1681 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1682 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1684 SIVAL(p,0,reskey); p += 4;
1685 put_long_date_timespec(p,create_date_ts); p += 8;
1686 put_long_date_timespec(p,adate_ts); p += 8;
1687 put_long_date_timespec(p,mdate_ts); p += 8;
1688 put_long_date_timespec(p,mdate_ts); p += 8;
1689 SOFF_T(p,0,file_size); p += 8;
1690 SOFF_T(p,0,allocation_size); p += 8;
1691 SIVAL(p,0,nt_extmode); p += 4;
1692 q = p; p += 4; /* q is placeholder for name length. */
1694 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1695 SIVAL(p,0,ea_size); /* Extended attributes */
1698 len = srvstr_push(base_data, flags2, p,
1699 fname, PTR_DIFF(end_data, p),
1700 STR_TERMINATE_ASCII);
1704 SIVAL(p,0,0); /* Ensure any padding is null. */
1705 len = PTR_DIFF(p, pdata);
1706 len = (len + 3) & ~3;
1711 case SMB_FIND_FILE_NAMES_INFO:
1712 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1714 SIVAL(p,0,reskey); p += 4;
1716 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1717 acl on a dir (tridge) */
1718 len = srvstr_push(base_data, flags2, p,
1719 fname, PTR_DIFF(end_data, p),
1720 STR_TERMINATE_ASCII);
1723 SIVAL(p,0,0); /* Ensure any padding is null. */
1724 len = PTR_DIFF(p, pdata);
1725 len = (len + 3) & ~3;
1730 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1731 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1733 SIVAL(p,0,reskey); p += 4;
1734 put_long_date_timespec(p,create_date_ts); p += 8;
1735 put_long_date_timespec(p,adate_ts); p += 8;
1736 put_long_date_timespec(p,mdate_ts); p += 8;
1737 put_long_date_timespec(p,mdate_ts); p += 8;
1738 SOFF_T(p,0,file_size); p += 8;
1739 SOFF_T(p,0,allocation_size); p += 8;
1740 SIVAL(p,0,nt_extmode); p += 4;
1741 q = p; p += 4; /* q is placeholder for name length. */
1743 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1744 SIVAL(p,0,ea_size); /* Extended attributes */
1747 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1748 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1749 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1750 len = srvstr_push(base_data, flags2, p,
1751 fname, PTR_DIFF(end_data, p),
1752 STR_TERMINATE_ASCII);
1755 SIVAL(p,0,0); /* Ensure any padding is null. */
1756 len = PTR_DIFF(p, pdata);
1757 len = (len + 3) & ~3;
1762 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1763 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1764 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1766 SIVAL(p,0,reskey); p += 4;
1767 put_long_date_timespec(p,create_date_ts); p += 8;
1768 put_long_date_timespec(p,adate_ts); p += 8;
1769 put_long_date_timespec(p,mdate_ts); p += 8;
1770 put_long_date_timespec(p,mdate_ts); p += 8;
1771 SOFF_T(p,0,file_size); p += 8;
1772 SOFF_T(p,0,allocation_size); p += 8;
1773 SIVAL(p,0,nt_extmode); p += 4;
1774 q = p; p += 4; /* q is placeholder for name length */
1776 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1777 SIVAL(p,0,ea_size); /* Extended attributes */
1780 /* Clear the short name buffer. This is
1781 * IMPORTANT as not doing so will trigger
1782 * a Win2k client bug. JRA.
1784 if (!was_8_3 && check_mangled_names) {
1785 if (!name_to_8_3(fname,mangled_name,True,
1787 /* Error - mangle failed ! */
1788 memset(mangled_name,'\0',12);
1790 mangled_name[12] = 0;
1791 len = srvstr_push(base_data, flags2,
1792 p+2, mangled_name, 24,
1793 STR_UPPER|STR_UNICODE);
1796 memset(p + 2 + len,'\0',24 - len);
1803 SSVAL(p,0,0); p += 2; /* Reserved ? */
1804 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1805 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1806 len = srvstr_push(base_data, flags2, p,
1807 fname, PTR_DIFF(end_data, p),
1808 STR_TERMINATE_ASCII);
1811 SIVAL(p,0,0); /* Ensure any padding is null. */
1812 len = PTR_DIFF(p, pdata);
1813 len = (len + 3) & ~3;
1818 /* CIFS UNIX Extension. */
1820 case SMB_FIND_FILE_UNIX:
1821 case SMB_FIND_FILE_UNIX_INFO2:
1823 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1825 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1827 if (info_level == SMB_FIND_FILE_UNIX) {
1828 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1829 p = store_file_unix_basic(conn, p,
1831 len = srvstr_push(base_data, flags2, p,
1832 fname, PTR_DIFF(end_data, p),
1835 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1836 p = store_file_unix_basic_info2(conn, p,
1840 len = srvstr_push(base_data, flags2, p, fname,
1841 PTR_DIFF(end_data, p), 0);
1842 SIVAL(nameptr, 0, len);
1846 SIVAL(p,0,0); /* Ensure any padding is null. */
1848 len = PTR_DIFF(p, pdata);
1849 len = (len + 3) & ~3;
1850 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1852 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1861 if (PTR_DIFF(p,pdata) > space_remaining) {
1862 /* Move the dirptr back to prev_dirpos */
1863 dptr_SeekDir(conn->dirptr, prev_dirpos);
1864 *out_of_space = True;
1865 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1866 return False; /* Not finished - just out of space */
1869 /* Setup the last entry pointer, as an offset from base_data */
1870 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1871 /* Advance the data pointer to the next slot */
1877 /****************************************************************************
1878 Reply to a TRANS2_FINDFIRST.
1879 ****************************************************************************/
1881 static void call_trans2findfirst(connection_struct *conn,
1882 struct smb_request *req,
1883 char **pparams, int total_params,
1884 char **ppdata, int total_data,
1885 unsigned int max_data_bytes)
1887 /* We must be careful here that we don't return more than the
1888 allowed number of data bytes. If this means returning fewer than
1889 maxentries then so be it. We assume that the redirector has
1890 enough room for the fixed number of parameter bytes it has
1892 char *params = *pparams;
1893 char *pdata = *ppdata;
1897 uint16 findfirst_flags;
1898 bool close_after_first;
1900 bool requires_resume_key;
1902 char *directory = NULL;
1905 int last_entry_off=0;
1909 bool finished = False;
1910 bool dont_descend = False;
1911 bool out_of_space = False;
1912 int space_remaining;
1913 bool mask_contains_wcard = False;
1914 SMB_STRUCT_STAT sbuf;
1915 struct ea_list *ea_list = NULL;
1916 NTSTATUS ntstatus = NT_STATUS_OK;
1917 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1918 TALLOC_CTX *ctx = talloc_tos();
1920 if (total_params < 13) {
1921 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1925 dirtype = SVAL(params,0);
1926 maxentries = SVAL(params,2);
1927 findfirst_flags = SVAL(params,4);
1928 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1929 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1930 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1931 info_level = SVAL(params,6);
1933 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1934 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1935 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1936 info_level, max_data_bytes));
1939 /* W2K3 seems to treat zero as 1. */
1943 switch (info_level) {
1944 case SMB_FIND_INFO_STANDARD:
1945 case SMB_FIND_EA_SIZE:
1946 case SMB_FIND_EA_LIST:
1947 case SMB_FIND_FILE_DIRECTORY_INFO:
1948 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1949 case SMB_FIND_FILE_NAMES_INFO:
1950 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1951 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1952 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1954 case SMB_FIND_FILE_UNIX:
1955 case SMB_FIND_FILE_UNIX_INFO2:
1956 /* Always use filesystem for UNIX mtime query. */
1957 ask_sharemode = false;
1958 if (!lp_unix_extensions()) {
1959 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1964 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1968 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1969 params+12, total_params - 12,
1970 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1971 if (!NT_STATUS_IS_OK(ntstatus)) {
1972 reply_nterror(req, ntstatus);
1976 ntstatus = resolve_dfspath_wcard(ctx, conn,
1977 req->flags2 & FLAGS2_DFS_PATHNAMES,
1980 &mask_contains_wcard);
1981 if (!NT_STATUS_IS_OK(ntstatus)) {
1982 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1983 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1984 ERRSRV, ERRbadpath);
1987 reply_nterror(req, ntstatus);
1991 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1992 if (!NT_STATUS_IS_OK(ntstatus)) {
1993 reply_nterror(req, ntstatus);
1997 ntstatus = check_name(conn, directory);
1998 if (!NT_STATUS_IS_OK(ntstatus)) {
1999 reply_nterror(req, ntstatus);
2003 p = strrchr_m(directory,'/');
2005 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2006 if((directory[0] == '.') && (directory[1] == '\0')) {
2007 mask = talloc_strdup(ctx,"*");
2009 reply_nterror(req, NT_STATUS_NO_MEMORY);
2012 mask_contains_wcard = True;
2014 directory = talloc_strdup(talloc_tos(), "./");
2016 reply_nterror(req, NT_STATUS_NO_MEMORY);
2023 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2025 if (info_level == SMB_FIND_EA_LIST) {
2028 if (total_data < 4) {
2029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2033 ea_size = IVAL(pdata,0);
2034 if (ea_size != total_data) {
2035 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2036 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2037 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2041 if (!lp_ea_support(SNUM(conn))) {
2042 reply_doserror(req, ERRDOS, ERReasnotsupported);
2046 /* Pull out the list of names. */
2047 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2049 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2054 *ppdata = (char *)SMB_REALLOC(
2055 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2056 if(*ppdata == NULL ) {
2057 reply_nterror(req, NT_STATUS_NO_MEMORY);
2061 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2063 /* Realloc the params space */
2064 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2065 if (*pparams == NULL) {
2066 reply_nterror(req, NT_STATUS_NO_MEMORY);
2071 /* Save the wildcard match and attribs we are using on this directory -
2072 needed as lanman2 assumes these are being saved between calls */
2074 ntstatus = dptr_create(conn,
2080 mask_contains_wcard,
2084 if (!NT_STATUS_IS_OK(ntstatus)) {
2085 reply_nterror(req, ntstatus);
2089 dptr_num = dptr_dnum(conn->dirptr);
2090 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2092 /* We don't need to check for VOL here as this is returned by
2093 a different TRANS2 call. */
2095 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2096 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2097 dont_descend = True;
2100 space_remaining = max_data_bytes;
2101 out_of_space = False;
2103 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2104 bool got_exact_match = False;
2106 /* this is a heuristic to avoid seeking the dirptr except when
2107 absolutely necessary. It allows for a filename of about 40 chars */
2108 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2109 out_of_space = True;
2112 finished = !get_lanman2_dir_entry(ctx,
2115 mask,dirtype,info_level,
2116 requires_resume_key,dont_descend,
2119 space_remaining, &out_of_space,
2121 &last_entry_off, ea_list);
2124 if (finished && out_of_space)
2127 if (!finished && !out_of_space)
2131 * As an optimisation if we know we aren't looking
2132 * for a wildcard name (ie. the name matches the wildcard exactly)
2133 * then we can finish on any (first) match.
2134 * This speeds up large directory searches. JRA.
2140 /* Ensure space_remaining never goes -ve. */
2141 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2142 space_remaining = 0;
2143 out_of_space = true;
2145 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2149 /* Check if we can close the dirptr */
2150 if(close_after_first || (finished && close_if_end)) {
2151 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2152 dptr_close(&dptr_num);
2156 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2157 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2158 * the protocol level is less than NT1. Tested with smbclient. JRA.
2159 * This should fix the OS/2 client bug #2335.
2162 if(numentries == 0) {
2163 dptr_close(&dptr_num);
2164 if (Protocol < PROTOCOL_NT1) {
2165 reply_doserror(req, ERRDOS, ERRnofiles);
2168 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2169 ERRDOS, ERRbadfile);
2174 /* At this point pdata points to numentries directory entries. */
2176 /* Set up the return parameter block */
2177 SSVAL(params,0,dptr_num);
2178 SSVAL(params,2,numentries);
2179 SSVAL(params,4,finished);
2180 SSVAL(params,6,0); /* Never an EA error */
2181 SSVAL(params,8,last_entry_off);
2183 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2186 if ((! *directory) && dptr_path(dptr_num)) {
2187 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2189 reply_nterror(req, NT_STATUS_NO_MEMORY);
2193 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2194 smb_fn_name(req->cmd),
2195 mask, directory, dirtype, numentries ) );
2198 * Force a name mangle here to ensure that the
2199 * mask as an 8.3 name is top of the mangled cache.
2200 * The reasons for this are subtle. Don't remove
2201 * this code unless you know what you are doing
2202 * (see PR#13758). JRA.
2205 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2206 char mangled_name[13];
2207 name_to_8_3(mask, mangled_name, True, conn->params);
2213 /****************************************************************************
2214 Reply to a TRANS2_FINDNEXT.
2215 ****************************************************************************/
2217 static void call_trans2findnext(connection_struct *conn,
2218 struct smb_request *req,
2219 char **pparams, int total_params,
2220 char **ppdata, int total_data,
2221 unsigned int max_data_bytes)
2223 /* We must be careful here that we don't return more than the
2224 allowed number of data bytes. If this means returning fewer than
2225 maxentries then so be it. We assume that the redirector has
2226 enough room for the fixed number of parameter bytes it has
2228 char *params = *pparams;
2229 char *pdata = *ppdata;
2235 uint16 findnext_flags;
2236 bool close_after_request;
2238 bool requires_resume_key;
2240 bool mask_contains_wcard = False;
2241 char *resume_name = NULL;
2242 const char *mask = NULL;
2243 const char *directory = NULL;
2247 int i, last_entry_off=0;
2248 bool finished = False;
2249 bool dont_descend = False;
2250 bool out_of_space = False;
2251 int space_remaining;
2252 struct ea_list *ea_list = NULL;
2253 NTSTATUS ntstatus = NT_STATUS_OK;
2254 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2255 TALLOC_CTX *ctx = talloc_tos();
2257 if (total_params < 13) {
2258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2262 dptr_num = SVAL(params,0);
2263 maxentries = SVAL(params,2);
2264 info_level = SVAL(params,4);
2265 resume_key = IVAL(params,6);
2266 findnext_flags = SVAL(params,10);
2267 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2268 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2269 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2270 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2272 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2274 total_params - 12, STR_TERMINATE, &ntstatus,
2275 &mask_contains_wcard);
2276 if (!NT_STATUS_IS_OK(ntstatus)) {
2277 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2278 complain (it thinks we're asking for the directory above the shared
2279 path or an invalid name). Catch this as the resume name is only compared, never used in
2280 a file access. JRA. */
2281 srvstr_pull_talloc(ctx, params, req->flags2,
2282 &resume_name, params+12,
2286 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2287 reply_nterror(req, ntstatus);
2292 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2293 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2294 resume_key = %d resume name = %s continue=%d level = %d\n",
2295 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2296 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2299 /* W2K3 seems to treat zero as 1. */
2303 switch (info_level) {
2304 case SMB_FIND_INFO_STANDARD:
2305 case SMB_FIND_EA_SIZE:
2306 case SMB_FIND_EA_LIST:
2307 case SMB_FIND_FILE_DIRECTORY_INFO:
2308 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2309 case SMB_FIND_FILE_NAMES_INFO:
2310 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2311 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2312 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2314 case SMB_FIND_FILE_UNIX:
2315 case SMB_FIND_FILE_UNIX_INFO2:
2316 /* Always use filesystem for UNIX mtime query. */
2317 ask_sharemode = false;
2318 if (!lp_unix_extensions()) {
2319 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2324 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2328 if (info_level == SMB_FIND_EA_LIST) {
2331 if (total_data < 4) {
2332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2336 ea_size = IVAL(pdata,0);
2337 if (ea_size != total_data) {
2338 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2339 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2340 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2344 if (!lp_ea_support(SNUM(conn))) {
2345 reply_doserror(req, ERRDOS, ERReasnotsupported);
2349 /* Pull out the list of names. */
2350 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2352 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2357 *ppdata = (char *)SMB_REALLOC(
2358 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2359 if(*ppdata == NULL) {
2360 reply_nterror(req, NT_STATUS_NO_MEMORY);
2365 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2367 /* Realloc the params space */
2368 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2369 if(*pparams == NULL ) {
2370 reply_nterror(req, NT_STATUS_NO_MEMORY);
2376 /* Check that the dptr is valid */
2377 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2378 reply_doserror(req, ERRDOS, ERRnofiles);
2382 string_set(&conn->dirpath,dptr_path(dptr_num));
2384 /* Get the wildcard mask from the dptr */
2385 if((p = dptr_wcard(dptr_num))== NULL) {
2386 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2387 reply_doserror(req, ERRDOS, ERRnofiles);
2392 directory = conn->dirpath;
2394 /* Get the attr mask from the dptr */
2395 dirtype = dptr_attr(dptr_num);
2397 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2398 dptr_num, mask, dirtype,
2400 dptr_TellDir(conn->dirptr)));
2402 /* We don't need to check for VOL here as this is returned by
2403 a different TRANS2 call. */
2405 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2406 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2407 dont_descend = True;
2410 space_remaining = max_data_bytes;
2411 out_of_space = False;
2414 * Seek to the correct position. We no longer use the resume key but
2415 * depend on the last file name instead.
2418 if(*resume_name && !continue_bit) {
2421 long current_pos = 0;
2423 * Remember, name_to_8_3 is called by
2424 * get_lanman2_dir_entry(), so the resume name
2425 * could be mangled. Ensure we check the unmangled name.
2428 if (mangle_is_mangled(resume_name, conn->params)) {
2429 char *new_resume_name = NULL;
2430 mangle_lookup_name_from_8_3(ctx,
2434 if (new_resume_name) {
2435 resume_name = new_resume_name;
2440 * Fix for NT redirector problem triggered by resume key indexes
2441 * changing between directory scans. We now return a resume key of 0
2442 * and instead look for the filename to continue from (also given
2443 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2444 * findfirst/findnext (as is usual) then the directory pointer
2445 * should already be at the correct place.
2448 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2449 } /* end if resume_name && !continue_bit */
2451 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2452 bool got_exact_match = False;
2454 /* this is a heuristic to avoid seeking the dirptr except when
2455 absolutely necessary. It allows for a filename of about 40 chars */
2456 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2457 out_of_space = True;
2460 finished = !get_lanman2_dir_entry(ctx,
2463 mask,dirtype,info_level,
2464 requires_resume_key,dont_descend,
2467 space_remaining, &out_of_space,
2469 &last_entry_off, ea_list);
2472 if (finished && out_of_space)
2475 if (!finished && !out_of_space)
2479 * As an optimisation if we know we aren't looking
2480 * for a wildcard name (ie. the name matches the wildcard exactly)
2481 * then we can finish on any (first) match.
2482 * This speeds up large directory searches. JRA.
2488 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2491 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2492 smb_fn_name(req->cmd),
2493 mask, directory, dirtype, numentries ) );
2495 /* Check if we can close the dirptr */
2496 if(close_after_request || (finished && close_if_end)) {
2497 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2498 dptr_close(&dptr_num); /* This frees up the saved mask */
2501 /* Set up the return parameter block */
2502 SSVAL(params,0,numentries);
2503 SSVAL(params,2,finished);
2504 SSVAL(params,4,0); /* Never an EA error */
2505 SSVAL(params,6,last_entry_off);
2507 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2513 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2515 E_md4hash(lp_servicename(SNUM(conn)),objid);
2519 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2521 SMB_ASSERT(extended_info != NULL);
2523 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2524 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2525 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2526 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2527 #ifdef SAMBA_VERSION_REVISION
2528 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2530 extended_info->samba_subversion = 0;
2531 #ifdef SAMBA_VERSION_RC_RELEASE
2532 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2534 #ifdef SAMBA_VERSION_PRE_RELEASE
2535 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2538 #ifdef SAMBA_VERSION_VENDOR_PATCH
2539 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2541 extended_info->samba_gitcommitdate = 0;
2542 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2543 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2546 memset(extended_info->samba_version_string, 0,
2547 sizeof(extended_info->samba_version_string));
2549 snprintf (extended_info->samba_version_string,
2550 sizeof(extended_info->samba_version_string),
2551 "%s", samba_version_string());
2554 /****************************************************************************
2555 Reply to a TRANS2_QFSINFO (query filesystem info).
2556 ****************************************************************************/
2558 static void call_trans2qfsinfo(connection_struct *conn,
2559 struct smb_request *req,
2560 char **pparams, int total_params,
2561 char **ppdata, int total_data,
2562 unsigned int max_data_bytes)
2564 char *pdata, *end_data;
2565 char *params = *pparams;
2569 const char *vname = volume_label(SNUM(conn));
2570 int snum = SNUM(conn);
2571 char *fstype = lp_fstype(SNUM(conn));
2572 uint32 additional_flags = 0;
2574 if (total_params < 2) {
2575 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2579 info_level = SVAL(params,0);
2582 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2583 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2584 "info level (0x%x) on IPC$.\n",
2585 (unsigned int)info_level));
2586 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2591 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2592 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2593 DEBUG(0,("call_trans2qfsinfo: encryption required "
2594 "and info level 0x%x sent.\n",
2595 (unsigned int)info_level));
2596 exit_server_cleanly("encryption required "
2602 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2604 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2605 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2606 reply_doserror(req, ERRSRV, ERRinvdevice);
2610 *ppdata = (char *)SMB_REALLOC(
2611 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2612 if (*ppdata == NULL ) {
2613 reply_nterror(req, NT_STATUS_NO_MEMORY);
2618 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2619 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2621 switch (info_level) {
2622 case SMB_INFO_ALLOCATION:
2624 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2626 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2627 reply_unixerror(req, ERRHRD, ERRgeneral);
2631 block_size = lp_block_size(snum);
2632 if (bsize < block_size) {
2633 uint64_t factor = block_size/bsize;
2638 if (bsize > block_size) {
2639 uint64_t factor = bsize/block_size;
2644 bytes_per_sector = 512;
2645 sectors_per_unit = bsize/bytes_per_sector;
2647 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2648 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2649 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2651 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2652 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2653 SIVAL(pdata,l1_cUnit,dsize);
2654 SIVAL(pdata,l1_cUnitAvail,dfree);
2655 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2659 case SMB_INFO_VOLUME:
2660 /* Return volume name */
2662 * Add volume serial number - hash of a combination of
2663 * the called hostname and the service name.
2665 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2667 * Win2k3 and previous mess this up by sending a name length
2668 * one byte short. I believe only older clients (OS/2 Win9x) use
2669 * this call so try fixing this by adding a terminating null to
2670 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2674 pdata+l2_vol_szVolLabel, vname,
2675 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2676 STR_NOALIGN|STR_TERMINATE);
2677 SCVAL(pdata,l2_vol_cch,len);
2678 data_len = l2_vol_szVolLabel + len;
2679 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2680 (unsigned)st.st_ctime, len, vname));
2683 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2684 case SMB_FS_ATTRIBUTE_INFORMATION:
2686 additional_flags = 0;
2687 #if defined(HAVE_SYS_QUOTAS)
2688 additional_flags |= FILE_VOLUME_QUOTAS;
2691 if(lp_nt_acl_support(SNUM(conn))) {
2692 additional_flags |= FILE_PERSISTENT_ACLS;
2695 /* Capabilities are filled in at connection time through STATVFS call */
2696 additional_flags |= conn->fs_capabilities;
2698 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2699 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2700 additional_flags); /* FS ATTRIBUTES */
2702 SIVAL(pdata,4,255); /* Max filename component length */
2703 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2704 and will think we can't do long filenames */
2705 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2706 PTR_DIFF(end_data, pdata+12),
2709 data_len = 12 + len;
2712 case SMB_QUERY_FS_LABEL_INFO:
2713 case SMB_FS_LABEL_INFORMATION:
2714 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2715 PTR_DIFF(end_data, pdata+4), 0);
2720 case SMB_QUERY_FS_VOLUME_INFO:
2721 case SMB_FS_VOLUME_INFORMATION:
2724 * Add volume serial number - hash of a combination of
2725 * the called hostname and the service name.
2727 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2728 (str_checksum(get_local_machine_name())<<16));
2730 /* Max label len is 32 characters. */
2731 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2732 PTR_DIFF(end_data, pdata+18),
2734 SIVAL(pdata,12,len);
2737 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2738 (int)strlen(vname),vname, lp_servicename(snum)));
2741 case SMB_QUERY_FS_SIZE_INFO:
2742 case SMB_FS_SIZE_INFORMATION:
2744 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2746 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2747 reply_unixerror(req, ERRHRD, ERRgeneral);
2750 block_size = lp_block_size(snum);
2751 if (bsize < block_size) {
2752 uint64_t factor = block_size/bsize;
2757 if (bsize > block_size) {
2758 uint64_t factor = bsize/block_size;
2763 bytes_per_sector = 512;
2764 sectors_per_unit = bsize/bytes_per_sector;
2765 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2766 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2767 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2768 SBIG_UINT(pdata,0,dsize);
2769 SBIG_UINT(pdata,8,dfree);
2770 SIVAL(pdata,16,sectors_per_unit);
2771 SIVAL(pdata,20,bytes_per_sector);
2775 case SMB_FS_FULL_SIZE_INFORMATION:
2777 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2779 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2780 reply_unixerror(req, ERRHRD, ERRgeneral);
2783 block_size = lp_block_size(snum);
2784 if (bsize < block_size) {
2785 uint64_t factor = block_size/bsize;
2790 if (bsize > block_size) {
2791 uint64_t factor = bsize/block_size;
2796 bytes_per_sector = 512;
2797 sectors_per_unit = bsize/bytes_per_sector;
2798 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2799 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2800 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2801 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2802 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2803 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2804 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2805 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2809 case SMB_QUERY_FS_DEVICE_INFO:
2810 case SMB_FS_DEVICE_INFORMATION:
2812 SIVAL(pdata,0,0); /* dev type */
2813 SIVAL(pdata,4,0); /* characteristics */
2816 #ifdef HAVE_SYS_QUOTAS
2817 case SMB_FS_QUOTA_INFORMATION:
2819 * what we have to send --metze:
2821 * Unknown1: 24 NULL bytes
2822 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2823 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2824 * Quota Flags: 2 byte :
2825 * Unknown3: 6 NULL bytes
2829 * details for Quota Flags:
2831 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2832 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2833 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2834 * 0x0001 Enable Quotas: enable quota for this fs
2838 /* we need to fake up a fsp here,
2839 * because its not send in this call
2842 SMB_NTQUOTA_STRUCT quotas;
2845 ZERO_STRUCT(quotas);
2851 if (conn->server_info->utok.uid != 0) {
2852 DEBUG(0,("set_user_quota: access_denied "
2853 "service [%s] user [%s]\n",
2854 lp_servicename(SNUM(conn)),
2855 conn->server_info->unix_name));
2856 reply_doserror(req, ERRDOS, ERRnoaccess);
2860 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2861 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2862 reply_doserror(req, ERRSRV, ERRerror);
2868 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2870 /* Unknown1 24 NULL bytes*/
2871 SBIG_UINT(pdata,0,(uint64_t)0);
2872 SBIG_UINT(pdata,8,(uint64_t)0);
2873 SBIG_UINT(pdata,16,(uint64_t)0);
2875 /* Default Soft Quota 8 bytes */
2876 SBIG_UINT(pdata,24,quotas.softlim);
2878 /* Default Hard Quota 8 bytes */
2879 SBIG_UINT(pdata,32,quotas.hardlim);
2881 /* Quota flag 2 bytes */
2882 SSVAL(pdata,40,quotas.qflags);
2884 /* Unknown3 6 NULL bytes */
2890 #endif /* HAVE_SYS_QUOTAS */
2891 case SMB_FS_OBJECTID_INFORMATION:
2893 unsigned char objid[16];
2894 struct smb_extended_info extended_info;
2895 memcpy(pdata,create_volume_objectid(conn, objid),16);
2896 samba_extended_info_version (&extended_info);
2897 SIVAL(pdata,16,extended_info.samba_magic);
2898 SIVAL(pdata,20,extended_info.samba_version);
2899 SIVAL(pdata,24,extended_info.samba_subversion);
2900 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2901 memcpy(pdata+36,extended_info.samba_version_string,28);
2907 * Query the version and capabilities of the CIFS UNIX extensions
2911 case SMB_QUERY_CIFS_UNIX_INFO:
2913 bool large_write = lp_min_receive_file_size() &&
2914 !srv_is_signing_active();
2915 bool large_read = !srv_is_signing_active();
2916 int encrypt_caps = 0;
2918 if (!lp_unix_extensions()) {
2919 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2923 switch (conn->encrypt_level) {
2929 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2932 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2933 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2934 large_write = false;
2940 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2941 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2943 /* We have POSIX ACLs, pathname, encryption,
2944 * large read/write, and locking capability. */
2946 SBIG_UINT(pdata,4,((uint64_t)(
2947 CIFS_UNIX_POSIX_ACLS_CAP|
2948 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2949 CIFS_UNIX_FCNTL_LOCKS_CAP|
2950 CIFS_UNIX_EXTATTR_CAP|
2951 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2953 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2955 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2959 case SMB_QUERY_POSIX_FS_INFO:
2962 vfs_statvfs_struct svfs;
2964 if (!lp_unix_extensions()) {
2965 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2969 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2973 SIVAL(pdata,0,svfs.OptimalTransferSize);
2974 SIVAL(pdata,4,svfs.BlockSize);
2975 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2976 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2977 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2978 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2979 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2980 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2981 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2983 } else if (rc == EOPNOTSUPP) {
2984 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2986 #endif /* EOPNOTSUPP */
2988 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2989 reply_doserror(req, ERRSRV, ERRerror);
2995 case SMB_QUERY_POSIX_WHOAMI:
3001 if (!lp_unix_extensions()) {
3002 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3006 if (max_data_bytes < 40) {
3007 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3011 /* We ARE guest if global_sid_Builtin_Guests is
3012 * in our list of SIDs.
3014 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3015 conn->server_info->ptok)) {
3016 flags |= SMB_WHOAMI_GUEST;
3019 /* We are NOT guest if global_sid_Authenticated_Users
3020 * is in our list of SIDs.
3022 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3023 conn->server_info->ptok)) {
3024 flags &= ~SMB_WHOAMI_GUEST;
3027 /* NOTE: 8 bytes for UID/GID, irrespective of native
3028 * platform size. This matches
3029 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3031 data_len = 4 /* flags */
3038 + 4 /* pad/reserved */
3039 + (conn->server_info->utok.ngroups * 8)
3041 + (conn->server_info->ptok->num_sids *
3045 SIVAL(pdata, 0, flags);
3046 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3048 (uint64_t)conn->server_info->utok.uid);
3049 SBIG_UINT(pdata, 16,
3050 (uint64_t)conn->server_info->utok.gid);
3053 if (data_len >= max_data_bytes) {
3054 /* Potential overflow, skip the GIDs and SIDs. */
3056 SIVAL(pdata, 24, 0); /* num_groups */
3057 SIVAL(pdata, 28, 0); /* num_sids */
3058 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3059 SIVAL(pdata, 36, 0); /* reserved */
3065 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3066 SIVAL(pdata, 28, conn->server_info->num_sids);
3068 /* We walk the SID list twice, but this call is fairly
3069 * infrequent, and I don't expect that it's performance
3070 * sensitive -- jpeach
3072 for (i = 0, sid_bytes = 0;
3073 i < conn->server_info->ptok->num_sids; ++i) {
3074 sid_bytes += ndr_size_dom_sid(
3075 &conn->server_info->ptok->user_sids[i],
3079 /* SID list byte count */
3080 SIVAL(pdata, 32, sid_bytes);
3082 /* 4 bytes pad/reserved - must be zero */
3083 SIVAL(pdata, 36, 0);
3087 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3088 SBIG_UINT(pdata, data_len,
3089 (uint64_t)conn->server_info->utok.groups[i]);
3095 i < conn->server_info->ptok->num_sids; ++i) {
3096 int sid_len = ndr_size_dom_sid(
3097 &conn->server_info->ptok->user_sids[i],
3100 sid_linearize(pdata + data_len, sid_len,
3101 &conn->server_info->ptok->user_sids[i]);
3102 data_len += sid_len;
3108 case SMB_MAC_QUERY_FS_INFO:
3110 * Thursby MAC extension... ONLY on NTFS filesystems
3111 * once we do streams then we don't need this
3113 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3115 SIVAL(pdata,84,0x100); /* Don't support mac... */
3120 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3125 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3128 DEBUG( 4, ( "%s info_level = %d\n",
3129 smb_fn_name(req->cmd), info_level) );
3134 /****************************************************************************
3135 Reply to a TRANS2_SETFSINFO (set filesystem info).
3136 ****************************************************************************/
3138 static void call_trans2setfsinfo(connection_struct *conn,
3139 struct smb_request *req,
3140 char **pparams, int total_params,
3141 char **ppdata, int total_data,
3142 unsigned int max_data_bytes)
3144 char *pdata = *ppdata;
3145 char *params = *pparams;
3148 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3151 if (total_params < 4) {
3152 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3154 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3158 info_level = SVAL(params,2);
3161 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3162 info_level != SMB_SET_CIFS_UNIX_INFO) {
3163 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3164 "info level (0x%x) on IPC$.\n",
3165 (unsigned int)info_level));
3166 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3171 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3172 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3173 DEBUG(0,("call_trans2setfsinfo: encryption required "
3174 "and info level 0x%x sent.\n",
3175 (unsigned int)info_level));
3176 exit_server_cleanly("encryption required "
3182 switch(info_level) {
3183 case SMB_SET_CIFS_UNIX_INFO:
3185 uint16 client_unix_major;
3186 uint16 client_unix_minor;
3187 uint32 client_unix_cap_low;
3188 uint32 client_unix_cap_high;
3190 if (!lp_unix_extensions()) {
3192 NT_STATUS_INVALID_LEVEL);
3196 /* There should be 12 bytes of capabilities set. */
3197 if (total_data < 8) {
3200 NT_STATUS_INVALID_PARAMETER);
3203 client_unix_major = SVAL(pdata,0);
3204 client_unix_minor = SVAL(pdata,2);
3205 client_unix_cap_low = IVAL(pdata,4);
3206 client_unix_cap_high = IVAL(pdata,8);
3207 /* Just print these values for now. */
3208 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3209 cap_low = 0x%x, cap_high = 0x%x\n",
3210 (unsigned int)client_unix_major,
3211 (unsigned int)client_unix_minor,
3212 (unsigned int)client_unix_cap_low,
3213 (unsigned int)client_unix_cap_high ));
3215 /* Here is where we must switch to posix pathname processing... */
3216 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3217 lp_set_posix_pathnames();
3218 mangle_change_to_posix();
3221 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3222 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3223 /* Client that knows how to do posix locks,
3224 * but not posix open/mkdir operations. Set a
3225 * default type for read/write checks. */
3227 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3233 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3236 size_t param_len = 0;
3237 size_t data_len = total_data;
3239 if (!lp_unix_extensions()) {
3242 NT_STATUS_INVALID_LEVEL);
3246 if (lp_smb_encrypt(SNUM(conn)) == false) {
3249 NT_STATUS_NOT_SUPPORTED);
3253 DEBUG( 4,("call_trans2setfsinfo: "
3254 "request transport encryption.\n"));
3256 status = srv_request_encryption_setup(conn,
3257 (unsigned char **)ppdata,
3259 (unsigned char **)pparams,
3262 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3263 !NT_STATUS_IS_OK(status)) {
3264 reply_nterror(req, status);
3268 send_trans2_replies(conn, req,
3275 if (NT_STATUS_IS_OK(status)) {
3276 /* Server-side transport
3277 * encryption is now *on*. */
3278 status = srv_encryption_start(conn);
3279 if (!NT_STATUS_IS_OK(status)) {
3280 exit_server_cleanly(
3281 "Failure in setting "
3282 "up encrypted transport");
3288 case SMB_FS_QUOTA_INFORMATION:
3290 files_struct *fsp = NULL;
3291 SMB_NTQUOTA_STRUCT quotas;
3293 ZERO_STRUCT(quotas);
3296 if ((conn->server_info->utok.uid != 0)
3297 ||!CAN_WRITE(conn)) {
3298 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3299 lp_servicename(SNUM(conn)),
3300 conn->server_info->unix_name));
3301 reply_doserror(req, ERRSRV, ERRaccess);
3305 /* note: normaly there're 48 bytes,
3306 * but we didn't use the last 6 bytes for now
3309 fsp = file_fsp(req, SVAL(params,0));
3311 if (!check_fsp_ntquota_handle(conn, req,
3313 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3315 req, NT_STATUS_INVALID_HANDLE);
3319 if (total_data < 42) {
3320 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3324 NT_STATUS_INVALID_PARAMETER);
3328 /* unknown_1 24 NULL bytes in pdata*/
3330 /* the soft quotas 8 bytes (uint64_t)*/
3331 quotas.softlim = (uint64_t)IVAL(pdata,24);
3332 #ifdef LARGE_SMB_OFF_T
3333 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3334 #else /* LARGE_SMB_OFF_T */
3335 if ((IVAL(pdata,28) != 0)&&
3336 ((quotas.softlim != 0xFFFFFFFF)||
3337 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3338 /* more than 32 bits? */
3341 NT_STATUS_INVALID_PARAMETER);
3344 #endif /* LARGE_SMB_OFF_T */
3346 /* the hard quotas 8 bytes (uint64_t)*/
3347 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3348 #ifdef LARGE_SMB_OFF_T
3349 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3350 #else /* LARGE_SMB_OFF_T */
3351 if ((IVAL(pdata,36) != 0)&&
3352 ((quotas.hardlim != 0xFFFFFFFF)||
3353 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3354 /* more than 32 bits? */
3357 NT_STATUS_INVALID_PARAMETER);
3360 #endif /* LARGE_SMB_OFF_T */
3362 /* quota_flags 2 bytes **/
3363 quotas.qflags = SVAL(pdata,40);
3365 /* unknown_2 6 NULL bytes follow*/
3367 /* now set the quotas */
3368 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3369 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3370 reply_doserror(req, ERRSRV, ERRerror);
3377 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3379 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3385 * sending this reply works fine,
3386 * but I'm not sure it's the same
3387 * like windows do...
3390 reply_outbuf(req, 10, 0);
3393 #if defined(HAVE_POSIX_ACLS)
3394 /****************************************************************************
3395 Utility function to count the number of entries in a POSIX acl.
3396 ****************************************************************************/
3398 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3400 unsigned int ace_count = 0;
3401 int entry_id = SMB_ACL_FIRST_ENTRY;
3402 SMB_ACL_ENTRY_T entry;
3404 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3406 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3407 entry_id = SMB_ACL_NEXT_ENTRY;
3414 /****************************************************************************
3415 Utility function to marshall a POSIX acl into wire format.
3416 ****************************************************************************/
3418 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3420 int entry_id = SMB_ACL_FIRST_ENTRY;
3421 SMB_ACL_ENTRY_T entry;
3423 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3424 SMB_ACL_TAG_T tagtype;
3425 SMB_ACL_PERMSET_T permset;
3426 unsigned char perms = 0;
3427 unsigned int own_grp;
3430 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3431 entry_id = SMB_ACL_NEXT_ENTRY;
3434 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3435 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3439 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3440 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3444 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3445 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3446 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3448 SCVAL(pdata,1,perms);
3451 case SMB_ACL_USER_OBJ:
3452 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3453 own_grp = (unsigned int)pst->st_uid;
3454 SIVAL(pdata,2,own_grp);
3459 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3461 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3464 own_grp = (unsigned int)*puid;
3465 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3466 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3467 SIVAL(pdata,2,own_grp);
3471 case SMB_ACL_GROUP_OBJ:
3472 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3473 own_grp = (unsigned int)pst->st_gid;
3474 SIVAL(pdata,2,own_grp);
3479 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3481 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3484 own_grp = (unsigned int)*pgid;
3485 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3486 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3487 SIVAL(pdata,2,own_grp);
3492 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3493 SIVAL(pdata,2,0xFFFFFFFF);
3494 SIVAL(pdata,6,0xFFFFFFFF);
3497 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3498 SIVAL(pdata,2,0xFFFFFFFF);
3499 SIVAL(pdata,6,0xFFFFFFFF);
3502 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3505 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3512 /****************************************************************************
3513 Store the FILE_UNIX_BASIC info.
3514 ****************************************************************************/
3516 static char *store_file_unix_basic(connection_struct *conn,
3519 const SMB_STRUCT_STAT *psbuf)
3521 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3522 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3524 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3527 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3530 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3531 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3532 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3535 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3539 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3543 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3546 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3550 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3554 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3557 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3561 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3568 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3569 * the chflags(2) (or equivalent) flags.
3571 * XXX: this really should be behind the VFS interface. To do this, we would
3572 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3573 * Each VFS module could then implement its own mapping as appropriate for the
3574 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3576 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3580 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3584 { UF_IMMUTABLE, EXT_IMMUTABLE },
3588 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3592 { UF_HIDDEN, EXT_HIDDEN },
3595 /* Do not remove. We need to guarantee that this array has at least one
3596 * entry to build on HP-UX.
3602 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3603 uint32 *smb_fflags, uint32 *smb_fmask)
3605 #ifdef HAVE_STAT_ST_FLAGS
3608 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3609 *smb_fmask |= info2_flags_map[i].smb_fflag;
3610 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3611 *smb_fflags |= info2_flags_map[i].smb_fflag;
3614 #endif /* HAVE_STAT_ST_FLAGS */
3617 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3618 const uint32 smb_fflags,
3619 const uint32 smb_fmask,
3622 #ifdef HAVE_STAT_ST_FLAGS
3623 uint32 max_fmask = 0;
3626 *stat_fflags = psbuf->st_flags;
3628 /* For each flags requested in smb_fmask, check the state of the
3629 * corresponding flag in smb_fflags and set or clear the matching
3633 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3634 max_fmask |= info2_flags_map[i].smb_fflag;
3635 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3636 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3637 *stat_fflags |= info2_flags_map[i].stat_fflag;
3639 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3644 /* If smb_fmask is asking to set any bits that are not supported by
3645 * our flag mappings, we should fail.
3647 if ((smb_fmask & max_fmask) != smb_fmask) {
3654 #endif /* HAVE_STAT_ST_FLAGS */
3658 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3659 * of file flags and birth (create) time.
3661 static char *store_file_unix_basic_info2(connection_struct *conn,
3664 const SMB_STRUCT_STAT *psbuf)
3666 uint32 file_flags = 0;
3667 uint32 flags_mask = 0;
3669 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3671 /* Create (birth) time 64 bit */
3672 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3675 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3676 SIVAL(pdata, 0, file_flags); /* flags */
3677 SIVAL(pdata, 4, flags_mask); /* mask */
3683 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3684 const struct stream_struct *streams,
3686 unsigned int max_data_bytes,
3687 unsigned int *data_size)
3690 unsigned int ofs = 0;
3692 for (i=0; i<num_streams; i++) {
3693 unsigned int next_offset;
3695 smb_ucs2_t *namebuf;
3697 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3698 streams[i].name, &namelen) ||
3701 return NT_STATUS_INVALID_PARAMETER;
3705 * name_buf is now null-terminated, we need to marshall as not
3711 if (ofs + 24 + namelen > max_data_bytes) {
3712 TALLOC_FREE(namebuf);
3713 return NT_STATUS_BUFFER_TOO_SMALL;
3716 SIVAL(data, ofs+4, namelen);
3717 SOFF_T(data, ofs+8, streams[i].size);
3718 SOFF_T(data, ofs+16, streams[i].alloc_size);
3719 memcpy(data+ofs+24, namebuf, namelen);
3720 TALLOC_FREE(namebuf);
3722 next_offset = ofs + 24 + namelen;
3724 if (i == num_streams-1) {
3725 SIVAL(data, ofs, 0);
3728 unsigned int align = ndr_align_size(next_offset, 8);
3730 if (next_offset + align > max_data_bytes) {
3731 return NT_STATUS_BUFFER_TOO_SMALL;
3734 memset(data+next_offset, 0, align);
3735 next_offset += align;
3737 SIVAL(data, ofs, next_offset - ofs);
3746 return NT_STATUS_OK;
3749 /****************************************************************************
3750 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3751 ****************************************************************************/
3753 static void call_trans2qpipeinfo(connection_struct *conn,
3754 struct smb_request *req,
3755 unsigned int tran_call,
3756 char **pparams, int total_params,
3757 char **ppdata, int total_data,
3758 unsigned int max_data_bytes)
3760 char *params = *pparams;
3761 char *pdata = *ppdata;
3762 unsigned int data_size = 0;
3763 unsigned int param_size = 2;
3768 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3772 if (total_params < 4) {
3773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3777 fsp = file_fsp(req, SVAL(params,0));
3778 if (!fsp_is_np(fsp)) {
3779 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3783 info_level = SVAL(params,2);
3785 *pparams = (char *)SMB_REALLOC(*pparams,2);
3786 if (*pparams == NULL) {
3787 reply_nterror(req, NT_STATUS_NO_MEMORY);
3792 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3793 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3794 if (*ppdata == NULL ) {
3795 reply_nterror(req, NT_STATUS_NO_MEMORY);
3800 switch (info_level) {
3801 case SMB_FILE_STANDARD_INFORMATION:
3803 SOFF_T(pdata,0,4096LL);
3810 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3814 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3820 /****************************************************************************
3821 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3822 file name or file id).
3823 ****************************************************************************/
3825 static void call_trans2qfilepathinfo(connection_struct *conn,
3826 struct smb_request *req,
3827 unsigned int tran_call,
3828 char **pparams, int total_params,
3829 char **ppdata, int total_data,
3830 unsigned int max_data_bytes)
3832 char *params = *pparams;
3833 char *pdata = *ppdata;
3834 char *dstart, *dend;
3838 SMB_OFF_T file_size=0;
3839 uint64_t allocation_size=0;
3840 unsigned int data_size = 0;
3841 unsigned int param_size = 2;
3842 SMB_STRUCT_STAT sbuf;
3843 char *dos_fname = NULL;
3849 bool delete_pending = False;
3851 time_t create_time, mtime, atime;
3852 struct timespec create_time_ts, mtime_ts, atime_ts;
3853 struct timespec write_time_ts;
3854 files_struct *fsp = NULL;
3855 struct file_id fileid;
3856 struct ea_list *ea_list = NULL;
3857 char *lock_data = NULL;
3858 bool ms_dfs_link = false;
3859 TALLOC_CTX *ctx = talloc_tos();
3862 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3867 ZERO_STRUCT(write_time_ts);
3869 if (tran_call == TRANSACT2_QFILEINFO) {
3870 if (total_params < 4) {
3871 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3876 call_trans2qpipeinfo(conn, req, tran_call,
3877 pparams, total_params,
3883 fsp = file_fsp(req, SVAL(params,0));
3884 info_level = SVAL(params,2);
3886 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3888 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3889 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3893 /* Initial check for valid fsp ptr. */
3894 if (!check_fsp_open(conn, req, fsp)) {
3898 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3900 reply_nterror(req, NT_STATUS_NO_MEMORY);
3904 if(fsp->fake_file_handle) {
3906 * This is actually for the QUOTA_FAKE_FILE --metze
3909 /* We know this name is ok, it's already passed the checks. */
3911 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3913 * This is actually a QFILEINFO on a directory
3914 * handle (returned from an NT SMB). NT5.0 seems
3915 * to do this call. JRA.
3918 if (INFO_LEVEL_IS_UNIX(info_level)) {
3919 /* Always do lstat for UNIX calls. */
3920 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3921 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3922 reply_unixerror(req,ERRDOS,ERRbadpath);
3925 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3926 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3927 reply_unixerror(req, ERRDOS, ERRbadpath);
3931 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3932 get_file_infos(fileid, &delete_pending, &write_time_ts);
3935 * Original code - this is an open file.
3937 if (!check_fsp(conn, req, fsp)) {
3941 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3942 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3943 reply_unixerror(req, ERRDOS, ERRbadfid);
3946 pos = fsp->fh->position_information;
3947 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3948 get_file_infos(fileid, &delete_pending, &write_time_ts);
3952 NTSTATUS status = NT_STATUS_OK;
3955 if (total_params < 7) {
3956 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3960 info_level = SVAL(params,0);
3962 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3964 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3965 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3969 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3971 STR_TERMINATE, &status);
3972 if (!NT_STATUS_IS_OK(status)) {
3973 reply_nterror(req, status);
3977 status = resolve_dfspath(ctx,
3979 req->flags2 & FLAGS2_DFS_PATHNAMES,
3982 if (!NT_STATUS_IS_OK(status)) {
3983 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3984 reply_botherror(req,
3985 NT_STATUS_PATH_NOT_COVERED,
3986 ERRSRV, ERRbadpath);
3988 reply_nterror(req, status);
3992 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3993 if (!NT_STATUS_IS_OK(status)) {
3994 reply_nterror(req, status);
3997 status = check_name(conn, fname);
3998 if (!NT_STATUS_IS_OK(status)) {
3999 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
4000 reply_nterror(req, status);
4004 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4005 && is_ntfs_stream_name(fname)) {
4007 SMB_STRUCT_STAT bsbuf;
4009 status = split_ntfs_stream_name(talloc_tos(), fname,
4011 if (!NT_STATUS_IS_OK(status)) {
4012 DEBUG(10, ("create_file_unixpath: "
4013 "split_ntfs_stream_name failed: %s\n",
4014 nt_errstr(status)));
4015 reply_nterror(req, status);
4019 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4021 if (INFO_LEVEL_IS_UNIX(info_level)) {
4022 /* Always do lstat for UNIX calls. */
4023 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4024 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4025 reply_unixerror(req,ERRDOS,ERRbadpath);
4029 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4030 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4031 reply_unixerror(req,ERRDOS,ERRbadpath);
4036 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4037 get_file_infos(fileid, &delete_pending, NULL);
4038 if (delete_pending) {
4039 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4044 if (INFO_LEVEL_IS_UNIX(info_level)) {
4045 /* Always do lstat for UNIX calls. */
4046 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4047 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4048 reply_unixerror(req, ERRDOS, ERRbadpath);
4052 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4053 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4056 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4057 reply_unixerror(req, ERRDOS, ERRbadpath);
4062 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4063 get_file_infos(fileid, &delete_pending, &write_time_ts);
4064 if (delete_pending) {
4065 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4070 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4071 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4075 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4076 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4078 p = strrchr_m(fname,'/');
4085 mode = dos_mode_msdfs(conn,fname,&sbuf);
4087 mode = dos_mode(conn,fname,&sbuf);
4090 mode = FILE_ATTRIBUTE_NORMAL;
4092 nlink = sbuf.st_nlink;
4094 if (nlink && (mode&aDIR)) {
4098 if ((nlink > 0) && delete_pending) {
4102 fullpathname = fname;
4104 file_size = get_file_size(sbuf);
4106 /* Pull out any data sent here before we realloc. */
4107 switch (info_level) {
4108 case SMB_INFO_QUERY_EAS_FROM_LIST:
4110 /* Pull any EA list from the data portion. */
4113 if (total_data < 4) {
4115 req, NT_STATUS_INVALID_PARAMETER);
4118 ea_size = IVAL(pdata,0);
4120 if (total_data > 0 && ea_size != total_data) {
4121 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4122 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4124 req, NT_STATUS_INVALID_PARAMETER);
4128 if (!lp_ea_support(SNUM(conn))) {
4129 reply_doserror(req, ERRDOS,
4130 ERReasnotsupported);
4134 /* Pull out the list of names. */
4135 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4138 req, NT_STATUS_INVALID_PARAMETER);
4144 case SMB_QUERY_POSIX_LOCK:
4146 if (fsp == NULL || fsp->fh->fd == -1) {
4147 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4151 if (total_data != POSIX_LOCK_DATA_SIZE) {
4153 req, NT_STATUS_INVALID_PARAMETER);
4157 /* Copy the lock range data. */
4158 lock_data = (char *)TALLOC_MEMDUP(
4159 ctx, pdata, total_data);
4161 reply_nterror(req, NT_STATUS_NO_MEMORY);
4169 *pparams = (char *)SMB_REALLOC(*pparams,2);
4170 if (*pparams == NULL) {
4171 reply_nterror(req, NT_STATUS_NO_MEMORY);
4176 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4177 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4178 if (*ppdata == NULL ) {
4179 reply_nterror(req, NT_STATUS_NO_MEMORY);
4184 dend = dstart + data_size - 1;
4186 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4187 mtime_ts = get_mtimespec(&sbuf);
4188 atime_ts = get_atimespec(&sbuf);
4190 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4193 /* Do we have this path open ? */
4195 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4196 fsp1 = file_find_di_first(fileid);
4197 if (fsp1 && fsp1->initial_allocation_size) {
4198 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4202 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4203 mtime_ts = write_time_ts;
4206 if (lp_dos_filetime_resolution(SNUM(conn))) {
4207 dos_filetime_timespec(&create_time_ts);
4208 dos_filetime_timespec(&mtime_ts);
4209 dos_filetime_timespec(&atime_ts);
4212 create_time = convert_timespec_to_time_t(create_time_ts);
4213 mtime = convert_timespec_to_time_t(mtime_ts);
4214 atime = convert_timespec_to_time_t(atime_ts);
4216 /* NT expects the name to be in an exact form of the *full*
4217 filename. See the trans2 torture test */
4218 if (ISDOT(base_name)) {
4219 dos_fname = talloc_strdup(ctx, "\\");
4221 reply_nterror(req, NT_STATUS_NO_MEMORY);
4225 dos_fname = talloc_asprintf(ctx,
4229 reply_nterror(req, NT_STATUS_NO_MEMORY);
4232 string_replace(dos_fname, '/', '\\');
4235 switch (info_level) {
4236 case SMB_INFO_STANDARD:
4237 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4239 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4240 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4241 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4242 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4243 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4244 SSVAL(pdata,l1_attrFile,mode);
4247 case SMB_INFO_QUERY_EA_SIZE:
4249 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4250 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4252 srv_put_dos_date2(pdata,0,create_time);
4253 srv_put_dos_date2(pdata,4,atime);
4254 srv_put_dos_date2(pdata,8,mtime); /* write time */
4255 SIVAL(pdata,12,(uint32)file_size);
4256 SIVAL(pdata,16,(uint32)allocation_size);
4257 SSVAL(pdata,20,mode);
4258 SIVAL(pdata,22,ea_size);
4262 case SMB_INFO_IS_NAME_VALID:
4263 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4264 if (tran_call == TRANSACT2_QFILEINFO) {
4265 /* os/2 needs this ? really ?*/
4266 reply_doserror(req, ERRDOS, ERRbadfunc);
4273 case SMB_INFO_QUERY_EAS_FROM_LIST:
4275 size_t total_ea_len = 0;
4276 struct ea_list *ea_file_list = NULL;
4278 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4280 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4281 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4283 if (!ea_list || (total_ea_len > data_size)) {
4285 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4289 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4293 case SMB_INFO_QUERY_ALL_EAS:
4295 /* We have data_size bytes to put EA's into. */
4296 size_t total_ea_len = 0;
4298 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4300 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4301 if (!ea_list || (total_ea_len > data_size)) {
4303 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4307 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4311 case SMB_FILE_BASIC_INFORMATION:
4312 case SMB_QUERY_FILE_BASIC_INFO:
4314 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4315 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4316 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4318 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4322 put_long_date_timespec(pdata,create_time_ts);
4323 put_long_date_timespec(pdata+8,atime_ts);
4324 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4325 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4326 SIVAL(pdata,32,mode);
4328 DEBUG(5,("SMB_QFBI - "));
4329 DEBUG(5,("create: %s ", ctime(&create_time)));
4330 DEBUG(5,("access: %s ", ctime(&atime)));
4331 DEBUG(5,("write: %s ", ctime(&mtime)));
4332 DEBUG(5,("change: %s ", ctime(&mtime)));
4333 DEBUG(5,("mode: %x\n", mode));
4336 case SMB_FILE_STANDARD_INFORMATION:
4337 case SMB_QUERY_FILE_STANDARD_INFO:
4339 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4341 SOFF_T(pdata,0,allocation_size);
4342 SOFF_T(pdata,8,file_size);
4343 SIVAL(pdata,16,nlink);
4344 SCVAL(pdata,20,delete_pending?1:0);
4345 SCVAL(pdata,21,(mode&aDIR)?1:0);
4346 SSVAL(pdata,22,0); /* Padding. */
4349 case SMB_FILE_EA_INFORMATION:
4350 case SMB_QUERY_FILE_EA_INFO:
4352 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4353 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4355 SIVAL(pdata,0,ea_size);
4359 /* Get the 8.3 name - used if NT SMB was negotiated. */
4360 case SMB_QUERY_FILE_ALT_NAME_INFO:
4361 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4363 char mangled_name[13];
4364 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4365 if (!name_to_8_3(base_name,mangled_name,
4366 True,conn->params)) {
4369 NT_STATUS_NO_MEMORY);
4371 len = srvstr_push(dstart, req->flags2,
4372 pdata+4, mangled_name,
4373 PTR_DIFF(dend, pdata+4),
4375 data_size = 4 + len;
4380 case SMB_QUERY_FILE_NAME_INFO:
4382 this must be *exactly* right for ACLs on mapped drives to work
4384 len = srvstr_push(dstart, req->flags2,
4386 PTR_DIFF(dend, pdata+4),
4388 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4389 data_size = 4 + len;
4393 case SMB_FILE_ALLOCATION_INFORMATION:
4394 case SMB_QUERY_FILE_ALLOCATION_INFO:
4395 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4397 SOFF_T(pdata,0,allocation_size);
4400 case SMB_FILE_END_OF_FILE_INFORMATION:
4401 case SMB_QUERY_FILE_END_OF_FILEINFO:
4402 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4404 SOFF_T(pdata,0,file_size);
4407 case SMB_QUERY_FILE_ALL_INFO:
4408 case SMB_FILE_ALL_INFORMATION:
4410 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4411 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4412 put_long_date_timespec(pdata,create_time_ts);
4413 put_long_date_timespec(pdata+8,atime_ts);
4414 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4415 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4416 SIVAL(pdata,32,mode);
4417 SIVAL(pdata,36,0); /* padding. */
4419 SOFF_T(pdata,0,allocation_size);
4420 SOFF_T(pdata,8,file_size);
4421 SIVAL(pdata,16,nlink);
4422 SCVAL(pdata,20,delete_pending);
4423 SCVAL(pdata,21,(mode&aDIR)?1:0);
4426 SIVAL(pdata,0,ea_size);
4427 pdata += 4; /* EA info */
4428 len = srvstr_push(dstart, req->flags2,
4430 PTR_DIFF(dend, pdata+4),
4434 data_size = PTR_DIFF(pdata,(*ppdata));
4437 case SMB_FILE_INTERNAL_INFORMATION:
4438 /* This should be an index number - looks like
4441 I think this causes us to fail the IFSKIT
4442 BasicFileInformationTest. -tpot */
4444 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4445 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4446 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4450 case SMB_FILE_ACCESS_INFORMATION:
4451 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4453 SIVAL(pdata,0,fsp->access_mask);
4455 /* GENERIC_EXECUTE mapping from Windows */
4456 SIVAL(pdata,0,0x12019F);
4461 case SMB_FILE_NAME_INFORMATION:
4462 /* Pathname with leading '\'. */
4465 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4466 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4467 SIVAL(pdata,0,byte_len);
4468 data_size = 4 + byte_len;
4472 case SMB_FILE_DISPOSITION_INFORMATION:
4473 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4475 SCVAL(pdata,0,delete_pending);
4478 case SMB_FILE_POSITION_INFORMATION:
4479 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4481 SOFF_T(pdata,0,pos);
4484 case SMB_FILE_MODE_INFORMATION:
4485 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4486 SIVAL(pdata,0,mode);
4490 case SMB_FILE_ALIGNMENT_INFORMATION:
4491 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4492 SIVAL(pdata,0,0); /* No alignment needed. */
4497 * NT4 server just returns "invalid query" to this - if we try
4498 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4501 /* The first statement above is false - verified using Thursby
4502 * client against NT4 -- gcolley.
4504 case SMB_QUERY_FILE_STREAM_INFO:
4505 case SMB_FILE_STREAM_INFORMATION: {
4506 unsigned int num_streams;
4507 struct stream_struct *streams;
4510 DEBUG(10,("call_trans2qfilepathinfo: "
4511 "SMB_FILE_STREAM_INFORMATION\n"));
4513 status = SMB_VFS_STREAMINFO(
4514 conn, fsp, fname, talloc_tos(),
4515 &num_streams, &streams);
4517 if (!NT_STATUS_IS_OK(status)) {
4518 DEBUG(10, ("could not get stream info: %s\n",
4519 nt_errstr(status)));
4520 reply_nterror(req, status);
4524 status = marshall_stream_info(num_streams, streams,
4525 pdata, max_data_bytes,
4528 if (!NT_STATUS_IS_OK(status)) {
4529 DEBUG(10, ("marshall_stream_info failed: %s\n",
4530 nt_errstr(status)));
4531 reply_nterror(req, status);
4535 TALLOC_FREE(streams);
4539 case SMB_QUERY_COMPRESSION_INFO:
4540 case SMB_FILE_COMPRESSION_INFORMATION:
4541 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4542 SOFF_T(pdata,0,file_size);
4543 SIVAL(pdata,8,0); /* ??? */
4544 SIVAL(pdata,12,0); /* ??? */
4548 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4549 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4550 put_long_date_timespec(pdata,create_time_ts);
4551 put_long_date_timespec(pdata+8,atime_ts);
4552 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4553 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4554 SOFF_T(pdata,32,allocation_size);
4555 SOFF_T(pdata,40,file_size);
4556 SIVAL(pdata,48,mode);
4557 SIVAL(pdata,52,0); /* ??? */
4561 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4562 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4563 SIVAL(pdata,0,mode);
4569 * CIFS UNIX Extensions.
4572 case SMB_QUERY_FILE_UNIX_BASIC:
4574 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4575 data_size = PTR_DIFF(pdata,(*ppdata));
4579 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4581 for (i=0; i<100; i++)
4582 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4588 case SMB_QUERY_FILE_UNIX_INFO2:
4590 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4591 data_size = PTR_DIFF(pdata,(*ppdata));
4595 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4597 for (i=0; i<100; i++)
4598 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4604 case SMB_QUERY_FILE_UNIX_LINK:
4606 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4609 reply_nterror(req, NT_STATUS_NO_MEMORY);
4613 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4615 if(!S_ISLNK(sbuf.st_mode)) {
4616 reply_unixerror(req, ERRSRV,
4621 reply_unixerror(req, ERRDOS, ERRbadlink);
4624 len = SMB_VFS_READLINK(conn,fullpathname,
4627 reply_unixerror(req, ERRDOS,
4632 len = srvstr_push(dstart, req->flags2,
4634 PTR_DIFF(dend, pdata),
4637 data_size = PTR_DIFF(pdata,(*ppdata));
4642 #if defined(HAVE_POSIX_ACLS)
4643 case SMB_QUERY_POSIX_ACL:
4645 SMB_ACL_T file_acl = NULL;
4646 SMB_ACL_T def_acl = NULL;
4647 uint16 num_file_acls = 0;
4648 uint16 num_def_acls = 0;
4650 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4651 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4653 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4656 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4657 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4661 NT_STATUS_NOT_IMPLEMENTED);
4665 if (S_ISDIR(sbuf.st_mode)) {
4666 if (fsp && fsp->is_directory) {
4667 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4669 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4671 def_acl = free_empty_sys_acl(conn, def_acl);
4674 num_file_acls = count_acl_entries(conn, file_acl);
4675 num_def_acls = count_acl_entries(conn, def_acl);
4677 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4678 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4680 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4681 SMB_POSIX_ACL_HEADER_SIZE) ));
4683 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4686 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4690 NT_STATUS_BUFFER_TOO_SMALL);
4694 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4695 SSVAL(pdata,2,num_file_acls);
4696 SSVAL(pdata,4,num_def_acls);
4697 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4699 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4702 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4705 req, NT_STATUS_INTERNAL_ERROR);
4708 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4710 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4713 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4717 NT_STATUS_INTERNAL_ERROR);
4722 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4725 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4727 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4733 case SMB_QUERY_POSIX_LOCK:
4735 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4739 enum brl_type lock_type;
4741 if (total_data != POSIX_LOCK_DATA_SIZE) {
4743 req, NT_STATUS_INVALID_PARAMETER);
4747 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4748 case POSIX_LOCK_TYPE_READ:
4749 lock_type = READ_LOCK;
4751 case POSIX_LOCK_TYPE_WRITE:
4752 lock_type = WRITE_LOCK;
4754 case POSIX_LOCK_TYPE_UNLOCK:
4756 /* There's no point in asking for an unlock... */
4759 NT_STATUS_INVALID_PARAMETER);
4763 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4764 #if defined(HAVE_LONGLONG)
4765 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4766 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4767 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4768 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4769 #else /* HAVE_LONGLONG */
4770 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4771 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4772 #endif /* HAVE_LONGLONG */
4774 status = query_lock(fsp,
4781 if (ERROR_WAS_LOCK_DENIED(status)) {
4782 /* Here we need to report who has it locked... */
4783 data_size = POSIX_LOCK_DATA_SIZE;
4785 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4786 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4787 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4788 #if defined(HAVE_LONGLONG)
4789 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4790 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4791 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4792 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4793 #else /* HAVE_LONGLONG */
4794 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4795 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4796 #endif /* HAVE_LONGLONG */
4798 } else if (NT_STATUS_IS_OK(status)) {
4799 /* For success we just return a copy of what we sent
4800 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4801 data_size = POSIX_LOCK_DATA_SIZE;
4802 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4803 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4805 reply_nterror(req, status);
4812 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4816 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4822 /****************************************************************************
4823 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4825 ****************************************************************************/
4827 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4828 connection_struct *conn,
4829 const char *oldname_in,
4830 const char *newname_in)
4832 SMB_STRUCT_STAT sbuf1, sbuf2;
4833 char *last_component_oldname = NULL;
4834 char *last_component_newname = NULL;
4835 char *oldname = NULL;
4836 char *newname = NULL;
4837 NTSTATUS status = NT_STATUS_OK;
4842 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4843 &last_component_oldname, &sbuf1);
4844 if (!NT_STATUS_IS_OK(status)) {
4848 status = check_name(conn, oldname);
4849 if (!NT_STATUS_IS_OK(status)) {
4853 /* source must already exist. */
4854 if (!VALID_STAT(sbuf1)) {
4855 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4858 status = unix_convert(ctx, conn, newname_in, False, &newname,
4859 &last_component_newname, &sbuf2);
4860 if (!NT_STATUS_IS_OK(status)) {
4864 status = check_name(conn, newname);
4865 if (!NT_STATUS_IS_OK(status)) {
4869 /* Disallow if newname already exists. */
4870 if (VALID_STAT(sbuf2)) {
4871 return NT_STATUS_OBJECT_NAME_COLLISION;
4874 /* No links from a directory. */
4875 if (S_ISDIR(sbuf1.st_mode)) {
4876 return NT_STATUS_FILE_IS_A_DIRECTORY;
4879 /* Ensure this is within the share. */
4880 status = check_reduced_name(conn, oldname);
4881 if (!NT_STATUS_IS_OK(status)) {
4885 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4887 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4888 status = map_nt_error_from_unix(errno);
4889 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4890 nt_errstr(status), newname, oldname));
4896 /****************************************************************************
4897 Deal with setting the time from any of the setfilepathinfo functions.
4898 ****************************************************************************/
4900 NTSTATUS smb_set_file_time(connection_struct *conn,
4903 const SMB_STRUCT_STAT *psbuf,
4904 struct timespec ts[2],
4905 bool setting_write_time)
4908 FILE_NOTIFY_CHANGE_LAST_ACCESS
4909 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4911 if (!VALID_STAT(*psbuf)) {
4912 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4915 /* get some defaults (no modifications) if any info is zero or -1. */
4916 if (null_timespec(ts[0])) {
4917 ts[0] = get_atimespec(psbuf);
4918 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4921 if (null_timespec(ts[1])) {
4922 ts[1] = get_mtimespec(psbuf);
4923 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4926 if (!setting_write_time) {
4927 /* ts[1] comes from change time, not write time. */
4928 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4931 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4932 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4935 * Try and set the times of this file if
4936 * they are different from the current values.
4940 struct timespec mts = get_mtimespec(psbuf);
4941 struct timespec ats = get_atimespec(psbuf);
4942 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4943 return NT_STATUS_OK;
4947 if (setting_write_time) {
4949 * This was a setfileinfo on an open file.
4950 * NT does this a lot. We also need to
4951 * set the time here, as it can be read by
4952 * FindFirst/FindNext and with the patch for bug #2045
4953 * in smbd/fileio.c it ensures that this timestamp is
4954 * kept sticky even after a write. We save the request
4955 * away and will set it on file close and after a write. JRA.
4958 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4959 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4962 if (fsp->base_fsp) {
4963 set_sticky_write_time_fsp(fsp->base_fsp, ts[1]);
4965 set_sticky_write_time_fsp(fsp, ts[1]);
4968 set_sticky_write_time_path(conn, fname,
4969 vfs_file_id_from_sbuf(conn, psbuf),
4974 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4976 if (fsp && fsp->base_fsp) {
4977 fname = fsp->base_fsp->fsp_name;
4980 if(file_ntimes(conn, fname, ts)!=0) {
4981 return map_nt_error_from_unix(errno);
4983 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4985 return NT_STATUS_OK;
4988 /****************************************************************************
4989 Deal with setting the dosmode from any of the setfilepathinfo functions.
4990 ****************************************************************************/
4992 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4994 SMB_STRUCT_STAT *psbuf,
4997 if (!VALID_STAT(*psbuf)) {
4998 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5002 if (S_ISDIR(psbuf->st_mode)) {
5009 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5011 /* check the mode isn't different, before changing it */
5012 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5014 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5015 fname, (unsigned int)dosmode ));
5017 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5018 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5019 fname, strerror(errno)));
5020 return map_nt_error_from_unix(errno);
5023 return NT_STATUS_OK;
5026 /****************************************************************************
5027 Deal with setting the size from any of the setfilepathinfo functions.
5028 ****************************************************************************/
5030 static NTSTATUS smb_set_file_size(connection_struct *conn,
5031 struct smb_request *req,
5034 SMB_STRUCT_STAT *psbuf,
5037 NTSTATUS status = NT_STATUS_OK;
5038 files_struct *new_fsp = NULL;
5040 if (!VALID_STAT(*psbuf)) {
5041 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5044 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5046 if (size == get_file_size(*psbuf)) {
5047 return NT_STATUS_OK;
5050 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5051 fname, (double)size ));
5053 if (fsp && fsp->fh->fd != -1) {
5054 /* Handle based call. */
5055 if (vfs_set_filelen(fsp, size) == -1) {
5056 return map_nt_error_from_unix(errno);
5058 trigger_write_time_update_immediate(fsp);
5059 return NT_STATUS_OK;
5062 status = SMB_VFS_CREATE_FILE(
5065 0, /* root_dir_fid */
5067 false, /* is_dos_path */
5068 FILE_WRITE_ATTRIBUTES, /* access_mask */
5069 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5071 FILE_OPEN, /* create_disposition*/
5072 0, /* create_options */
5073 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5074 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5075 0, /* allocation_size */
5078 &new_fsp, /* result */
5082 if (!NT_STATUS_IS_OK(status)) {
5083 /* NB. We check for open_was_deferred in the caller. */
5087 if (vfs_set_filelen(new_fsp, size) == -1) {
5088 status = map_nt_error_from_unix(errno);
5089 close_file(req, new_fsp,NORMAL_CLOSE);
5093 trigger_write_time_update_immediate(new_fsp);
5094 close_file(req, new_fsp,NORMAL_CLOSE);
5095 return NT_STATUS_OK;
5098 /****************************************************************************
5099 Deal with SMB_INFO_SET_EA.
5100 ****************************************************************************/
5102 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5108 struct ea_list *ea_list = NULL;
5109 TALLOC_CTX *ctx = NULL;
5110 NTSTATUS status = NT_STATUS_OK;
5112 if (total_data < 10) {
5114 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5115 length. They seem to have no effect. Bug #3212. JRA */
5117 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5118 /* We're done. We only get EA info in this call. */
5119 return NT_STATUS_OK;
5122 return NT_STATUS_INVALID_PARAMETER;
5125 if (IVAL(pdata,0) > total_data) {
5126 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5127 IVAL(pdata,0), (unsigned int)total_data));
5128 return NT_STATUS_INVALID_PARAMETER;
5132 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5134 return NT_STATUS_INVALID_PARAMETER;
5136 status = set_ea(conn, fsp, fname, ea_list);
5141 /****************************************************************************
5142 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5143 ****************************************************************************/
5145 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5150 SMB_STRUCT_STAT *psbuf)
5152 NTSTATUS status = NT_STATUS_OK;
5153 bool delete_on_close;
5156 if (total_data < 1) {
5157 return NT_STATUS_INVALID_PARAMETER;
5161 return NT_STATUS_INVALID_HANDLE;
5164 delete_on_close = (CVAL(pdata,0) ? True : False);
5165 dosmode = dos_mode(conn, fname, psbuf);
5167 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5168 "delete_on_close = %u\n",
5170 (unsigned int)dosmode,
5171 (unsigned int)delete_on_close ));
5173 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5175 if (!NT_STATUS_IS_OK(status)) {
5179 /* The set is across all open files on this dev/inode pair. */
5180 if (!set_delete_on_close(fsp, delete_on_close,
5181 &conn->server_info->utok)) {
5182 return NT_STATUS_ACCESS_DENIED;
5184 return NT_STATUS_OK;
5187 /****************************************************************************
5188 Deal with SMB_FILE_POSITION_INFORMATION.
5189 ****************************************************************************/
5191 static NTSTATUS smb_file_position_information(connection_struct *conn,
5196 uint64_t position_information;
5198 if (total_data < 8) {
5199 return NT_STATUS_INVALID_PARAMETER;
5203 /* Ignore on pathname based set. */
5204 return NT_STATUS_OK;
5207 position_information = (uint64_t)IVAL(pdata,0);
5208 #ifdef LARGE_SMB_OFF_T
5209 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5210 #else /* LARGE_SMB_OFF_T */
5211 if (IVAL(pdata,4) != 0) {
5212 /* more than 32 bits? */
5213 return NT_STATUS_INVALID_PARAMETER;
5215 #endif /* LARGE_SMB_OFF_T */
5217 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5218 fsp->fsp_name, (double)position_information ));
5219 fsp->fh->position_information = position_information;
5220 return NT_STATUS_OK;
5223 /****************************************************************************
5224 Deal with SMB_FILE_MODE_INFORMATION.
5225 ****************************************************************************/
5227 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5233 if (total_data < 4) {
5234 return NT_STATUS_INVALID_PARAMETER;
5236 mode = IVAL(pdata,0);
5237 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5238 return NT_STATUS_INVALID_PARAMETER;
5240 return NT_STATUS_OK;
5243 /****************************************************************************
5244 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5245 ****************************************************************************/
5247 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5248 struct smb_request *req,
5253 char *link_target = NULL;
5254 const char *newname = fname;
5255 NTSTATUS status = NT_STATUS_OK;
5256 TALLOC_CTX *ctx = talloc_tos();
5258 /* Set a symbolic link. */
5259 /* Don't allow this if follow links is false. */
5261 if (total_data == 0) {
5262 return NT_STATUS_INVALID_PARAMETER;
5265 if (!lp_symlinks(SNUM(conn))) {
5266 return NT_STATUS_ACCESS_DENIED;
5269 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5270 total_data, STR_TERMINATE);
5273 return NT_STATUS_INVALID_PARAMETER;
5276 /* !widelinks forces the target path to be within the share. */
5277 /* This means we can interpret the target as a pathname. */
5278 if (!lp_widelinks(SNUM(conn))) {
5279 char *rel_name = NULL;
5280 char *last_dirp = NULL;
5282 if (*link_target == '/') {
5283 /* No absolute paths allowed. */
5284 return NT_STATUS_ACCESS_DENIED;
5286 rel_name = talloc_strdup(ctx,newname);
5288 return NT_STATUS_NO_MEMORY;
5290 last_dirp = strrchr_m(rel_name, '/');
5292 last_dirp[1] = '\0';
5294 rel_name = talloc_strdup(ctx,"./");
5296 return NT_STATUS_NO_MEMORY;
5299 rel_name = talloc_asprintf_append(rel_name,
5303 return NT_STATUS_NO_MEMORY;
5306 status = check_name(conn, rel_name);
5307 if (!NT_STATUS_IS_OK(status)) {
5312 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5313 newname, link_target ));
5315 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5316 return map_nt_error_from_unix(errno);
5319 return NT_STATUS_OK;
5322 /****************************************************************************
5323 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5324 ****************************************************************************/
5326 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5327 struct smb_request *req,
5328 const char *pdata, int total_data,
5331 char *oldname = NULL;
5332 TALLOC_CTX *ctx = talloc_tos();
5333 NTSTATUS status = NT_STATUS_OK;
5335 /* Set a hard link. */
5336 if (total_data == 0) {
5337 return NT_STATUS_INVALID_PARAMETER;
5340 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5341 total_data, STR_TERMINATE, &status);
5342 if (!NT_STATUS_IS_OK(status)) {
5346 status = resolve_dfspath(ctx, conn,
5347 req->flags2 & FLAGS2_DFS_PATHNAMES,
5350 if (!NT_STATUS_IS_OK(status)) {
5354 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5357 return hardlink_internals(ctx, conn, oldname, fname);
5360 /****************************************************************************
5361 Deal with SMB_FILE_RENAME_INFORMATION.
5362 ****************************************************************************/
5364 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5365 struct smb_request *req,
5374 char *newname = NULL;
5375 char *base_name = NULL;
5376 bool dest_has_wcard = False;
5377 NTSTATUS status = NT_STATUS_OK;
5379 TALLOC_CTX *ctx = talloc_tos();
5381 if (total_data < 13) {
5382 return NT_STATUS_INVALID_PARAMETER;
5385 overwrite = (CVAL(pdata,0) ? True : False);
5386 root_fid = IVAL(pdata,4);
5387 len = IVAL(pdata,8);
5389 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5390 return NT_STATUS_INVALID_PARAMETER;
5393 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5396 if (!NT_STATUS_IS_OK(status)) {
5400 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5403 status = resolve_dfspath_wcard(ctx, conn,
5404 req->flags2 & FLAGS2_DFS_PATHNAMES,
5408 if (!NT_STATUS_IS_OK(status)) {
5412 /* Check the new name has no '/' characters. */
5413 if (strchr_m(newname, '/')) {
5414 return NT_STATUS_NOT_SUPPORTED;
5417 if (fsp && fsp->base_fsp) {
5418 if (newname[0] != ':') {
5419 return NT_STATUS_NOT_SUPPORTED;
5421 base_name = talloc_asprintf(ctx, "%s%s",
5422 fsp->base_fsp->fsp_name,
5425 return NT_STATUS_NO_MEMORY;
5428 if (is_ntfs_stream_name(newname)) {
5429 return NT_STATUS_NOT_SUPPORTED;
5432 /* Create the base directory. */
5433 base_name = talloc_strdup(ctx, fname);
5435 return NT_STATUS_NO_MEMORY;
5437 p = strrchr_m(base_name, '/');
5441 base_name = talloc_strdup(ctx, "./");
5443 return NT_STATUS_NO_MEMORY;
5446 /* Append the new name. */
5447 base_name = talloc_asprintf_append(base_name,
5451 return NT_STATUS_NO_MEMORY;
5456 SMB_STRUCT_STAT sbuf;
5457 char *newname_last_component = NULL;
5461 status = unix_convert(ctx, conn, newname, False,
5463 &newname_last_component,
5466 /* If an error we expect this to be
5467 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5469 if (!NT_STATUS_IS_OK(status)
5470 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5475 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5476 fsp->fnum, fsp->fsp_name, base_name ));
5477 status = rename_internals_fsp(conn, fsp, base_name,
5478 newname_last_component, 0,
5481 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5482 fname, base_name ));
5483 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5484 overwrite, False, dest_has_wcard,
5485 FILE_WRITE_ATTRIBUTES);
5491 /****************************************************************************
5492 Deal with SMB_SET_POSIX_ACL.
5493 ****************************************************************************/
5495 #if defined(HAVE_POSIX_ACLS)
5496 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5501 SMB_STRUCT_STAT *psbuf)
5503 uint16 posix_acl_version;
5504 uint16 num_file_acls;
5505 uint16 num_def_acls;
5506 bool valid_file_acls = True;
5507 bool valid_def_acls = True;
5509 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5510 return NT_STATUS_INVALID_PARAMETER;
5512 posix_acl_version = SVAL(pdata,0);
5513 num_file_acls = SVAL(pdata,2);
5514 num_def_acls = SVAL(pdata,4);
5516 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5517 valid_file_acls = False;
5521 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5522 valid_def_acls = False;
5526 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5527 return NT_STATUS_INVALID_PARAMETER;
5530 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5531 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5532 return NT_STATUS_INVALID_PARAMETER;
5535 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5536 fname ? fname : fsp->fsp_name,
5537 (unsigned int)num_file_acls,
5538 (unsigned int)num_def_acls));
5540 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5541 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5542 return map_nt_error_from_unix(errno);
5545 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5546 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5547 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5548 return map_nt_error_from_unix(errno);
5550 return NT_STATUS_OK;
5554 /****************************************************************************
5555 Deal with SMB_SET_POSIX_LOCK.
5556 ****************************************************************************/
5558 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5559 struct smb_request *req,
5567 bool blocking_lock = False;
5568 enum brl_type lock_type;
5570 NTSTATUS status = NT_STATUS_OK;
5572 if (fsp == NULL || fsp->fh->fd == -1) {
5573 return NT_STATUS_INVALID_HANDLE;
5576 if (total_data != POSIX_LOCK_DATA_SIZE) {
5577 return NT_STATUS_INVALID_PARAMETER;
5580 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5581 case POSIX_LOCK_TYPE_READ:
5582 lock_type = READ_LOCK;
5584 case POSIX_LOCK_TYPE_WRITE:
5585 /* Return the right POSIX-mappable error code for files opened read-only. */
5586 if (!fsp->can_write) {
5587 return NT_STATUS_INVALID_HANDLE;
5589 lock_type = WRITE_LOCK;
5591 case POSIX_LOCK_TYPE_UNLOCK:
5592 lock_type = UNLOCK_LOCK;
5595 return NT_STATUS_INVALID_PARAMETER;
5598 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5599 blocking_lock = False;
5600 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5601 blocking_lock = True;
5603 return NT_STATUS_INVALID_PARAMETER;
5606 if (!lp_blocking_locks(SNUM(conn))) {
5607 blocking_lock = False;
5610 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5611 #if defined(HAVE_LONGLONG)
5612 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5613 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5614 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5615 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5616 #else /* HAVE_LONGLONG */
5617 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5618 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5619 #endif /* HAVE_LONGLONG */
5621 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5622 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5624 (unsigned int)lock_type,
5625 (unsigned int)lock_pid,
5629 if (lock_type == UNLOCK_LOCK) {
5630 status = do_unlock(smbd_messaging_context(),
5637 uint32 block_smbpid;
5639 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5650 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5652 * A blocking lock was requested. Package up
5653 * this smb into a queued request and push it
5654 * onto the blocking lock queue.
5656 if(push_blocking_lock_request(br_lck,
5659 -1, /* infinite timeout. */
5667 TALLOC_FREE(br_lck);
5671 TALLOC_FREE(br_lck);
5677 /****************************************************************************
5678 Deal with SMB_INFO_STANDARD.
5679 ****************************************************************************/
5681 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5686 const SMB_STRUCT_STAT *psbuf)
5688 struct timespec ts[2];
5690 if (total_data < 12) {
5691 return NT_STATUS_INVALID_PARAMETER;
5695 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5697 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5699 DEBUG(10,("smb_set_info_standard: file %s\n",
5700 fname ? fname : fsp->fsp_name ));
5702 return smb_set_file_time(conn,
5710 /****************************************************************************
5711 Deal with SMB_SET_FILE_BASIC_INFO.
5712 ****************************************************************************/
5714 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5719 SMB_STRUCT_STAT *psbuf)
5721 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5722 struct timespec write_time;
5723 struct timespec changed_time;
5725 struct timespec ts[2];
5726 NTSTATUS status = NT_STATUS_OK;
5727 bool setting_write_time = true;
5729 if (total_data < 36) {
5730 return NT_STATUS_INVALID_PARAMETER;
5733 /* Set the attributes */
5734 dosmode = IVAL(pdata,32);
5735 status = smb_set_file_dosmode(conn,
5739 if (!NT_STATUS_IS_OK(status)) {
5743 /* Ignore create time at offset pdata. */
5746 ts[0] = interpret_long_date(pdata+8);
5748 write_time = interpret_long_date(pdata+16);
5749 changed_time = interpret_long_date(pdata+24);
5752 ts[1] = timespec_min(&write_time, &changed_time);
5754 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5758 /* Prefer a defined time to an undefined one. */
5759 if (null_timespec(ts[1])) {
5760 if (null_timespec(write_time)) {
5761 ts[1] = changed_time;
5762 setting_write_time = false;
5768 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5769 fname ? fname : fsp->fsp_name ));
5771 return smb_set_file_time(conn,
5776 setting_write_time);
5779 /****************************************************************************
5780 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5781 ****************************************************************************/
5783 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5784 struct smb_request *req,
5789 SMB_STRUCT_STAT *psbuf)
5791 uint64_t allocation_size = 0;
5792 NTSTATUS status = NT_STATUS_OK;
5793 files_struct *new_fsp = NULL;
5795 if (!VALID_STAT(*psbuf)) {
5796 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5799 if (total_data < 8) {
5800 return NT_STATUS_INVALID_PARAMETER;
5803 allocation_size = (uint64_t)IVAL(pdata,0);
5804 #ifdef LARGE_SMB_OFF_T
5805 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5806 #else /* LARGE_SMB_OFF_T */
5807 if (IVAL(pdata,4) != 0) {
5808 /* more than 32 bits? */
5809 return NT_STATUS_INVALID_PARAMETER;
5811 #endif /* LARGE_SMB_OFF_T */
5813 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5814 fname, (double)allocation_size ));
5816 if (allocation_size) {
5817 allocation_size = smb_roundup(conn, allocation_size);
5820 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5821 fname, (double)allocation_size ));
5823 if (fsp && fsp->fh->fd != -1) {
5824 /* Open file handle. */
5825 /* Only change if needed. */
5826 if (allocation_size != get_file_size(*psbuf)) {
5827 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5828 return map_nt_error_from_unix(errno);
5831 /* But always update the time. */
5833 * This is equivalent to a write. Ensure it's seen immediately
5834 * if there are no pending writes.
5836 trigger_write_time_update_immediate(fsp);
5837 return NT_STATUS_OK;
5840 /* Pathname or stat or directory file. */
5842 status = SMB_VFS_CREATE_FILE(
5845 0, /* root_dir_fid */
5847 false, /* is_dos_path */
5848 FILE_WRITE_DATA, /* access_mask */
5849 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5851 FILE_OPEN, /* create_disposition*/
5852 0, /* create_options */
5853 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5854 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5855 0, /* allocation_size */
5858 &new_fsp, /* result */
5862 if (!NT_STATUS_IS_OK(status)) {
5863 /* NB. We check for open_was_deferred in the caller. */
5867 /* Only change if needed. */
5868 if (allocation_size != get_file_size(*psbuf)) {
5869 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5870 status = map_nt_error_from_unix(errno);
5871 close_file(req, new_fsp, NORMAL_CLOSE);
5876 /* Changing the allocation size should set the last mod time. */
5878 * This is equivalent to a write. Ensure it's seen immediately
5879 * if there are no pending writes.
5881 trigger_write_time_update_immediate(new_fsp);
5883 close_file(req, new_fsp, NORMAL_CLOSE);
5884 return NT_STATUS_OK;
5887 /****************************************************************************
5888 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5889 ****************************************************************************/
5891 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5892 struct smb_request *req,
5897 SMB_STRUCT_STAT *psbuf)
5901 if (total_data < 8) {
5902 return NT_STATUS_INVALID_PARAMETER;
5905 size = IVAL(pdata,0);
5906 #ifdef LARGE_SMB_OFF_T
5907 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5908 #else /* LARGE_SMB_OFF_T */
5909 if (IVAL(pdata,4) != 0) {
5910 /* more than 32 bits? */
5911 return NT_STATUS_INVALID_PARAMETER;
5913 #endif /* LARGE_SMB_OFF_T */
5914 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5915 "file %s to %.0f\n", fname, (double)size ));
5917 return smb_set_file_size(conn, req,
5924 /****************************************************************************
5925 Allow a UNIX info mknod.
5926 ****************************************************************************/
5928 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5932 SMB_STRUCT_STAT *psbuf)
5934 uint32 file_type = IVAL(pdata,56);
5935 #if defined(HAVE_MAKEDEV)
5936 uint32 dev_major = IVAL(pdata,60);
5937 uint32 dev_minor = IVAL(pdata,68);
5939 SMB_DEV_T dev = (SMB_DEV_T)0;
5940 uint32 raw_unixmode = IVAL(pdata,84);
5944 if (total_data < 100) {
5945 return NT_STATUS_INVALID_PARAMETER;
5948 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5949 if (!NT_STATUS_IS_OK(status)) {
5953 #if defined(HAVE_MAKEDEV)
5954 dev = makedev(dev_major, dev_minor);
5957 switch (file_type) {
5958 #if defined(S_IFIFO)
5959 case UNIX_TYPE_FIFO:
5960 unixmode |= S_IFIFO;
5963 #if defined(S_IFSOCK)
5964 case UNIX_TYPE_SOCKET:
5965 unixmode |= S_IFSOCK;
5968 #if defined(S_IFCHR)
5969 case UNIX_TYPE_CHARDEV:
5970 unixmode |= S_IFCHR;
5973 #if defined(S_IFBLK)
5974 case UNIX_TYPE_BLKDEV:
5975 unixmode |= S_IFBLK;
5979 return NT_STATUS_INVALID_PARAMETER;
5982 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5983 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5985 /* Ok - do the mknod. */
5986 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5987 return map_nt_error_from_unix(errno);
5990 /* If any of the other "set" calls fail we
5991 * don't want to end up with a half-constructed mknod.
5994 if (lp_inherit_perms(SNUM(conn))) {
5995 inherit_access_posix_acl(
5996 conn, parent_dirname(fname),
6000 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
6001 status = map_nt_error_from_unix(errno);
6002 SMB_VFS_UNLINK(conn,fname);
6005 return NT_STATUS_OK;
6008 /****************************************************************************
6009 Deal with SMB_SET_FILE_UNIX_BASIC.
6010 ****************************************************************************/
6012 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6013 struct smb_request *req,
6018 SMB_STRUCT_STAT *psbuf)
6020 struct timespec ts[2];
6021 uint32 raw_unixmode;
6024 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6025 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6026 NTSTATUS status = NT_STATUS_OK;
6027 bool delete_on_fail = False;
6028 enum perm_type ptype;
6030 if (total_data < 100) {
6031 return NT_STATUS_INVALID_PARAMETER;
6034 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6035 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6036 size=IVAL(pdata,0); /* first 8 Bytes are size */
6037 #ifdef LARGE_SMB_OFF_T
6038 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6039 #else /* LARGE_SMB_OFF_T */
6040 if (IVAL(pdata,4) != 0) {
6041 /* more than 32 bits? */
6042 return NT_STATUS_INVALID_PARAMETER;
6044 #endif /* LARGE_SMB_OFF_T */
6047 ts[0] = interpret_long_date(pdata+24); /* access_time */
6048 ts[1] = interpret_long_date(pdata+32); /* modification_time */
6049 set_owner = (uid_t)IVAL(pdata,40);
6050 set_grp = (gid_t)IVAL(pdata,48);
6051 raw_unixmode = IVAL(pdata,84);
6053 if (VALID_STAT(*psbuf)) {
6054 if (S_ISDIR(psbuf->st_mode)) {
6055 ptype = PERM_EXISTING_DIR;
6057 ptype = PERM_EXISTING_FILE;
6060 ptype = PERM_NEW_FILE;
6063 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6064 if (!NT_STATUS_IS_OK(status)) {
6068 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6069 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6070 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6072 if (!VALID_STAT(*psbuf)) {
6074 * The only valid use of this is to create character and block
6075 * devices, and named pipes. This is deprecated (IMHO) and
6076 * a new info level should be used for mknod. JRA.
6079 status = smb_unix_mknod(conn,
6084 if (!NT_STATUS_IS_OK(status)) {
6088 /* Ensure we don't try and change anything else. */
6089 raw_unixmode = SMB_MODE_NO_CHANGE;
6090 size = get_file_size(*psbuf);
6091 ts[0] = get_atimespec(psbuf);
6092 ts[1] = get_mtimespec(psbuf);
6094 * We continue here as we might want to change the
6097 delete_on_fail = True;
6101 /* Horrible backwards compatibility hack as an old server bug
6102 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6106 size = get_file_size(*psbuf);
6111 * Deal with the UNIX specific mode set.
6114 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6115 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6116 (unsigned int)unixmode, fname ));
6117 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6118 return map_nt_error_from_unix(errno);
6123 * Deal with the UNIX specific uid set.
6126 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6129 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6130 (unsigned int)set_owner, fname ));
6132 if (S_ISLNK(psbuf->st_mode)) {
6133 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6135 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6139 status = map_nt_error_from_unix(errno);
6140 if (delete_on_fail) {
6141 SMB_VFS_UNLINK(conn,fname);
6148 * Deal with the UNIX specific gid set.
6151 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6152 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6153 (unsigned int)set_owner, fname ));
6154 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6155 status = map_nt_error_from_unix(errno);
6156 if (delete_on_fail) {
6157 SMB_VFS_UNLINK(conn,fname);
6163 /* Deal with any size changes. */
6165 status = smb_set_file_size(conn, req,
6170 if (!NT_STATUS_IS_OK(status)) {
6174 /* Deal with any time changes. */
6176 return smb_set_file_time(conn,
6184 /****************************************************************************
6185 Deal with SMB_SET_FILE_UNIX_INFO2.
6186 ****************************************************************************/
6188 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6189 struct smb_request *req,
6194 SMB_STRUCT_STAT *psbuf)
6200 if (total_data < 116) {
6201 return NT_STATUS_INVALID_PARAMETER;
6204 /* Start by setting all the fields that are common between UNIX_BASIC
6207 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6209 if (!NT_STATUS_IS_OK(status)) {
6213 smb_fflags = IVAL(pdata, 108);
6214 smb_fmask = IVAL(pdata, 112);
6216 /* NB: We should only attempt to alter the file flags if the client
6217 * sends a non-zero mask.
6219 if (smb_fmask != 0) {
6220 int stat_fflags = 0;
6222 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6224 /* Client asked to alter a flag we don't understand. */
6225 return NT_STATUS_INVALID_PARAMETER;
6228 if (fsp && fsp->fh->fd != -1) {
6229 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6230 return NT_STATUS_NOT_SUPPORTED;
6232 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6233 return map_nt_error_from_unix(errno);
6238 /* XXX: need to add support for changing the create_time here. You
6239 * can do this for paths on Darwin with setattrlist(2). The right way
6240 * to hook this up is probably by extending the VFS utimes interface.
6243 return NT_STATUS_OK;
6246 /****************************************************************************
6247 Create a directory with POSIX semantics.
6248 ****************************************************************************/
6250 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6251 struct smb_request *req,
6255 SMB_STRUCT_STAT *psbuf,
6256 int *pdata_return_size)
6258 NTSTATUS status = NT_STATUS_OK;
6259 uint32 raw_unixmode = 0;
6260 uint32 mod_unixmode = 0;
6261 mode_t unixmode = (mode_t)0;
6262 files_struct *fsp = NULL;
6263 uint16 info_level_return = 0;
6265 char *pdata = *ppdata;
6267 if (total_data < 18) {
6268 return NT_STATUS_INVALID_PARAMETER;
6271 raw_unixmode = IVAL(pdata,8);
6272 /* Next 4 bytes are not yet defined. */
6274 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6275 if (!NT_STATUS_IS_OK(status)) {
6279 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6281 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6282 fname, (unsigned int)unixmode ));
6284 status = SMB_VFS_CREATE_FILE(
6287 0, /* root_dir_fid */
6289 false, /* is_dos_path */
6290 FILE_READ_ATTRIBUTES, /* access_mask */
6291 FILE_SHARE_NONE, /* share_access */
6292 FILE_CREATE, /* create_disposition*/
6293 FILE_DIRECTORY_FILE, /* create_options */
6294 mod_unixmode, /* file_attributes */
6295 0, /* oplock_request */
6296 0, /* allocation_size */
6303 if (NT_STATUS_IS_OK(status)) {
6304 close_file(req, fsp, NORMAL_CLOSE);
6307 info_level_return = SVAL(pdata,16);
6309 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6310 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6311 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6312 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6314 *pdata_return_size = 12;
6317 /* Realloc the data size */
6318 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6319 if (*ppdata == NULL) {
6320 *pdata_return_size = 0;
6321 return NT_STATUS_NO_MEMORY;
6325 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6326 SSVAL(pdata,2,0); /* No fnum. */
6327 SIVAL(pdata,4,info); /* Was directory created. */
6329 switch (info_level_return) {
6330 case SMB_QUERY_FILE_UNIX_BASIC:
6331 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6332 SSVAL(pdata,10,0); /* Padding. */
6333 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6335 case SMB_QUERY_FILE_UNIX_INFO2:
6336 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6337 SSVAL(pdata,10,0); /* Padding. */
6338 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6341 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6342 SSVAL(pdata,10,0); /* Padding. */
6349 /****************************************************************************
6350 Open/Create a file with POSIX semantics.
6351 ****************************************************************************/
6353 static NTSTATUS smb_posix_open(connection_struct *conn,
6354 struct smb_request *req,
6358 SMB_STRUCT_STAT *psbuf,
6359 int *pdata_return_size)
6361 bool extended_oplock_granted = False;
6362 char *pdata = *ppdata;
6364 uint32 wire_open_mode = 0;
6365 uint32 raw_unixmode = 0;
6366 uint32 mod_unixmode = 0;
6367 uint32 create_disp = 0;
6368 uint32 access_mask = 0;
6369 uint32 create_options = 0;
6370 NTSTATUS status = NT_STATUS_OK;
6371 mode_t unixmode = (mode_t)0;
6372 files_struct *fsp = NULL;
6373 int oplock_request = 0;
6375 uint16 info_level_return = 0;
6377 if (total_data < 18) {
6378 return NT_STATUS_INVALID_PARAMETER;
6381 flags = IVAL(pdata,0);
6382 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6383 if (oplock_request) {
6384 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6387 wire_open_mode = IVAL(pdata,4);
6389 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6390 return smb_posix_mkdir(conn, req,
6398 switch (wire_open_mode & SMB_ACCMODE) {
6400 access_mask = FILE_READ_DATA;
6403 access_mask = FILE_WRITE_DATA;
6406 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6409 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6410 (unsigned int)wire_open_mode ));
6411 return NT_STATUS_INVALID_PARAMETER;
6414 wire_open_mode &= ~SMB_ACCMODE;
6416 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6417 create_disp = FILE_CREATE;
6418 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6419 create_disp = FILE_OVERWRITE_IF;
6420 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6421 create_disp = FILE_OPEN_IF;
6423 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6424 (unsigned int)wire_open_mode ));
6425 return NT_STATUS_INVALID_PARAMETER;
6428 raw_unixmode = IVAL(pdata,8);
6429 /* Next 4 bytes are not yet defined. */
6431 status = unix_perms_from_wire(conn,
6434 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6437 if (!NT_STATUS_IS_OK(status)) {
6441 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6443 if (wire_open_mode & SMB_O_SYNC) {
6444 create_options |= FILE_WRITE_THROUGH;
6446 if (wire_open_mode & SMB_O_APPEND) {
6447 access_mask |= FILE_APPEND_DATA;
6449 if (wire_open_mode & SMB_O_DIRECT) {
6450 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6453 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6455 (unsigned int)wire_open_mode,
6456 (unsigned int)unixmode ));
6458 status = SMB_VFS_CREATE_FILE(
6461 0, /* root_dir_fid */
6463 false, /* is_dos_path */
6464 access_mask, /* access_mask */
6465 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6467 create_disp, /* create_disposition*/
6468 0, /* create_options */
6469 mod_unixmode, /* file_attributes */
6470 oplock_request, /* oplock_request */
6471 0, /* allocation_size */
6478 if (!NT_STATUS_IS_OK(status)) {
6482 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6483 extended_oplock_granted = True;
6486 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6487 extended_oplock_granted = True;
6490 info_level_return = SVAL(pdata,16);
6492 /* Allocate the correct return size. */
6494 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6495 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6496 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6497 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6499 *pdata_return_size = 12;
6502 /* Realloc the data size */
6503 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6504 if (*ppdata == NULL) {
6505 close_file(req, fsp, ERROR_CLOSE);
6506 *pdata_return_size = 0;
6507 return NT_STATUS_NO_MEMORY;
6511 if (extended_oplock_granted) {
6512 if (flags & REQUEST_BATCH_OPLOCK) {
6513 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6515 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6517 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6518 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6520 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6523 SSVAL(pdata,2,fsp->fnum);
6524 SIVAL(pdata,4,info); /* Was file created etc. */
6526 switch (info_level_return) {
6527 case SMB_QUERY_FILE_UNIX_BASIC:
6528 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6529 SSVAL(pdata,10,0); /* padding. */
6530 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6532 case SMB_QUERY_FILE_UNIX_INFO2:
6533 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6534 SSVAL(pdata,10,0); /* padding. */
6535 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6538 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6539 SSVAL(pdata,10,0); /* padding. */
6542 return NT_STATUS_OK;
6545 /****************************************************************************
6546 Delete a file with POSIX semantics.
6547 ****************************************************************************/
6549 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6550 struct smb_request *req,
6554 SMB_STRUCT_STAT *psbuf)
6556 NTSTATUS status = NT_STATUS_OK;
6557 files_struct *fsp = NULL;
6561 int create_options = 0;
6563 struct share_mode_lock *lck = NULL;
6565 if (total_data < 2) {
6566 return NT_STATUS_INVALID_PARAMETER;
6569 flags = SVAL(pdata,0);
6571 if (!VALID_STAT(*psbuf)) {
6572 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6575 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6576 !VALID_STAT_OF_DIR(*psbuf)) {
6577 return NT_STATUS_NOT_A_DIRECTORY;
6580 DEBUG(10,("smb_posix_unlink: %s %s\n",
6581 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6584 if (VALID_STAT_OF_DIR(*psbuf)) {
6585 create_options |= FILE_DIRECTORY_FILE;
6588 status = SMB_VFS_CREATE_FILE(
6591 0, /* root_dir_fid */
6593 false, /* is_dos_path */
6594 DELETE_ACCESS, /* access_mask */
6595 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6597 FILE_OPEN, /* create_disposition*/
6598 create_options, /* create_options */
6599 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
6600 0, /* oplock_request */
6601 0, /* allocation_size */
6608 if (!NT_STATUS_IS_OK(status)) {
6613 * Don't lie to client. If we can't really delete due to
6614 * non-POSIX opens return SHARING_VIOLATION.
6617 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6620 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6621 "lock for file %s\n", fsp->fsp_name));
6622 close_file(req, fsp, NORMAL_CLOSE);
6623 return NT_STATUS_INVALID_PARAMETER;
6627 * See if others still have the file open. If this is the case, then
6628 * don't delete. If all opens are POSIX delete we can set the delete
6629 * on close disposition.
6631 for (i=0; i<lck->num_share_modes; i++) {
6632 struct share_mode_entry *e = &lck->share_modes[i];
6633 if (is_valid_share_mode_entry(e)) {
6634 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6637 /* Fail with sharing violation. */
6638 close_file(req, fsp, NORMAL_CLOSE);
6640 return NT_STATUS_SHARING_VIOLATION;
6645 * Set the delete on close.
6647 status = smb_set_file_disposition_info(conn,
6654 if (!NT_STATUS_IS_OK(status)) {
6655 close_file(req, fsp, NORMAL_CLOSE);
6660 return close_file(req, fsp, NORMAL_CLOSE);
6663 /****************************************************************************
6664 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6665 ****************************************************************************/
6667 static void call_trans2setfilepathinfo(connection_struct *conn,
6668 struct smb_request *req,
6669 unsigned int tran_call,
6670 char **pparams, int total_params,
6671 char **ppdata, int total_data,
6672 unsigned int max_data_bytes)
6674 char *params = *pparams;
6675 char *pdata = *ppdata;
6677 SMB_STRUCT_STAT sbuf;
6679 files_struct *fsp = NULL;
6680 NTSTATUS status = NT_STATUS_OK;
6681 int data_return_size = 0;
6682 TALLOC_CTX *ctx = talloc_tos();
6685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6691 if (tran_call == TRANSACT2_SETFILEINFO) {
6692 if (total_params < 4) {
6693 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6697 fsp = file_fsp(req, SVAL(params,0));
6698 /* Basic check for non-null fsp. */
6699 if (!check_fsp_open(conn, req, fsp)) {
6702 info_level = SVAL(params,2);
6704 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6706 reply_nterror(req, NT_STATUS_NO_MEMORY);
6710 if(fsp->is_directory || fsp->fh->fd == -1) {
6712 * This is actually a SETFILEINFO on a directory
6713 * handle (returned from an NT SMB). NT5.0 seems
6714 * to do this call. JRA.
6716 if (INFO_LEVEL_IS_UNIX(info_level)) {
6717 /* Always do lstat for UNIX calls. */
6718 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6719 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6720 reply_unixerror(req,ERRDOS,ERRbadpath);
6724 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6725 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6726 reply_unixerror(req,ERRDOS,ERRbadpath);
6730 } else if (fsp->print_file) {
6732 * Doing a DELETE_ON_CLOSE should cancel a print job.
6734 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6735 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6737 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6740 send_trans2_replies(conn, req, params, 2,
6745 reply_unixerror(req, ERRDOS, ERRbadpath);
6750 * Original code - this is an open file.
6752 if (!check_fsp(conn, req, fsp)) {
6756 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6757 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6758 reply_unixerror(req, ERRDOS, ERRbadfid);
6764 if (total_params < 7) {
6765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6769 info_level = SVAL(params,0);
6770 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6771 total_params - 6, STR_TERMINATE,
6773 if (!NT_STATUS_IS_OK(status)) {
6774 reply_nterror(req, status);
6778 status = resolve_dfspath(ctx, conn,
6779 req->flags2 & FLAGS2_DFS_PATHNAMES,
6782 if (!NT_STATUS_IS_OK(status)) {
6783 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6784 reply_botherror(req,
6785 NT_STATUS_PATH_NOT_COVERED,
6786 ERRSRV, ERRbadpath);
6789 reply_nterror(req, status);
6793 status = unix_convert(ctx, conn, fname, False,
6794 &fname, NULL, &sbuf);
6795 if (!NT_STATUS_IS_OK(status)) {
6796 reply_nterror(req, status);
6800 status = check_name(conn, fname);
6801 if (!NT_STATUS_IS_OK(status)) {
6802 reply_nterror(req, status);
6806 if (INFO_LEVEL_IS_UNIX(info_level)) {
6808 * For CIFS UNIX extensions the target name may not exist.
6811 /* Always do lstat for UNIX calls. */
6812 SMB_VFS_LSTAT(conn,fname,&sbuf);
6814 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6815 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6816 reply_unixerror(req, ERRDOS, ERRbadpath);
6821 if (!CAN_WRITE(conn)) {
6822 reply_doserror(req, ERRSRV, ERRaccess);
6826 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6827 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6831 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6832 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6834 /* Realloc the parameter size */
6835 *pparams = (char *)SMB_REALLOC(*pparams,2);
6836 if (*pparams == NULL) {
6837 reply_nterror(req, NT_STATUS_NO_MEMORY);
6844 switch (info_level) {
6846 case SMB_INFO_STANDARD:
6848 status = smb_set_info_standard(conn,
6857 case SMB_INFO_SET_EA:
6859 status = smb_info_set_ea(conn,
6867 case SMB_SET_FILE_BASIC_INFO:
6868 case SMB_FILE_BASIC_INFORMATION:
6870 status = smb_set_file_basic_info(conn,
6879 case SMB_FILE_ALLOCATION_INFORMATION:
6880 case SMB_SET_FILE_ALLOCATION_INFO:
6882 status = smb_set_file_allocation_info(conn, req,
6891 case SMB_FILE_END_OF_FILE_INFORMATION:
6892 case SMB_SET_FILE_END_OF_FILE_INFO:
6894 status = smb_set_file_end_of_file_info(conn, req,
6903 case SMB_FILE_DISPOSITION_INFORMATION:
6904 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6907 /* JRA - We used to just ignore this on a path ?
6908 * Shouldn't this be invalid level on a pathname
6911 if (tran_call != TRANSACT2_SETFILEINFO) {
6912 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6915 status = smb_set_file_disposition_info(conn,
6924 case SMB_FILE_POSITION_INFORMATION:
6926 status = smb_file_position_information(conn,
6933 /* From tridge Samba4 :
6934 * MODE_INFORMATION in setfileinfo (I have no
6935 * idea what "mode information" on a file is - it takes a value of 0,
6936 * 2, 4 or 6. What could it be?).
6939 case SMB_FILE_MODE_INFORMATION:
6941 status = smb_file_mode_information(conn,
6948 * CIFS UNIX extensions.
6951 case SMB_SET_FILE_UNIX_BASIC:
6953 status = smb_set_file_unix_basic(conn, req,
6962 case SMB_SET_FILE_UNIX_INFO2:
6964 status = smb_set_file_unix_info2(conn, req,
6973 case SMB_SET_FILE_UNIX_LINK:
6975 if (tran_call != TRANSACT2_SETPATHINFO) {
6976 /* We must have a pathname for this. */
6977 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6980 status = smb_set_file_unix_link(conn, req, pdata,
6985 case SMB_SET_FILE_UNIX_HLINK:
6987 if (tran_call != TRANSACT2_SETPATHINFO) {
6988 /* We must have a pathname for this. */
6989 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6992 status = smb_set_file_unix_hlink(conn, req,
6998 case SMB_FILE_RENAME_INFORMATION:
7000 status = smb_file_rename_information(conn, req,
7006 #if defined(HAVE_POSIX_ACLS)
7007 case SMB_SET_POSIX_ACL:
7009 status = smb_set_posix_acl(conn,
7019 case SMB_SET_POSIX_LOCK:
7021 if (tran_call != TRANSACT2_SETFILEINFO) {
7022 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7025 status = smb_set_posix_lock(conn, req,
7026 pdata, total_data, fsp);
7030 case SMB_POSIX_PATH_OPEN:
7032 if (tran_call != TRANSACT2_SETPATHINFO) {
7033 /* We must have a pathname for this. */
7034 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7038 status = smb_posix_open(conn, req,
7047 case SMB_POSIX_PATH_UNLINK:
7049 if (tran_call != TRANSACT2_SETPATHINFO) {
7050 /* We must have a pathname for this. */
7051 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7055 status = smb_posix_unlink(conn, req,
7064 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7069 if (!NT_STATUS_IS_OK(status)) {
7070 if (open_was_deferred(req->mid)) {
7071 /* We have re-scheduled this call. */
7074 if (blocking_lock_was_deferred(req->mid)) {
7075 /* We have re-scheduled this call. */
7078 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7079 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7080 ERRSRV, ERRbadpath);
7083 if (info_level == SMB_POSIX_PATH_OPEN) {
7084 reply_openerror(req, status);
7088 reply_nterror(req, status);
7093 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7099 /****************************************************************************
7100 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7101 ****************************************************************************/
7103 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7104 char **pparams, int total_params,
7105 char **ppdata, int total_data,
7106 unsigned int max_data_bytes)
7108 char *params = *pparams;
7109 char *pdata = *ppdata;
7110 char *directory = NULL;
7111 SMB_STRUCT_STAT sbuf;
7112 NTSTATUS status = NT_STATUS_OK;
7113 struct ea_list *ea_list = NULL;
7114 TALLOC_CTX *ctx = talloc_tos();
7116 if (!CAN_WRITE(conn)) {
7117 reply_doserror(req, ERRSRV, ERRaccess);
7121 if (total_params < 5) {
7122 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7126 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7127 total_params - 4, STR_TERMINATE,
7129 if (!NT_STATUS_IS_OK(status)) {
7130 reply_nterror(req, status);
7134 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7136 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7137 if (!NT_STATUS_IS_OK(status)) {
7138 reply_nterror(req, status);
7142 status = check_name(conn, directory);
7143 if (!NT_STATUS_IS_OK(status)) {
7144 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7145 reply_nterror(req, status);
7149 /* Any data in this call is an EA list. */
7150 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7151 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7156 * OS/2 workplace shell seems to send SET_EA requests of "null"
7157 * length (4 bytes containing IVAL 4).
7158 * They seem to have no effect. Bug #3212. JRA.
7161 if (total_data != 4) {
7162 if (total_data < 10) {
7163 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7167 if (IVAL(pdata,0) > total_data) {
7168 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7169 IVAL(pdata,0), (unsigned int)total_data));
7170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7174 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7181 /* If total_data == 4 Windows doesn't care what values
7182 * are placed in that field, it just ignores them.
7183 * The System i QNTC IBM SMB client puts bad values here,
7184 * so ignore them. */
7186 status = create_directory(conn, req, directory);
7188 if (!NT_STATUS_IS_OK(status)) {
7189 reply_nterror(req, status);
7193 /* Try and set any given EA. */
7195 status = set_ea(conn, NULL, directory, ea_list);
7196 if (!NT_STATUS_IS_OK(status)) {
7197 reply_nterror(req, status);
7202 /* Realloc the parameter and data sizes */
7203 *pparams = (char *)SMB_REALLOC(*pparams,2);
7204 if(*pparams == NULL) {
7205 reply_nterror(req, NT_STATUS_NO_MEMORY);
7212 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7217 /****************************************************************************
7218 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7219 We don't actually do this - we just send a null response.
7220 ****************************************************************************/
7222 static void call_trans2findnotifyfirst(connection_struct *conn,
7223 struct smb_request *req,
7224 char **pparams, int total_params,
7225 char **ppdata, int total_data,
7226 unsigned int max_data_bytes)
7228 static uint16 fnf_handle = 257;
7229 char *params = *pparams;
7232 if (total_params < 6) {
7233 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7237 info_level = SVAL(params,4);
7238 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7240 switch (info_level) {
7245 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7249 /* Realloc the parameter and data sizes */
7250 *pparams = (char *)SMB_REALLOC(*pparams,6);
7251 if (*pparams == NULL) {
7252 reply_nterror(req, NT_STATUS_NO_MEMORY);
7257 SSVAL(params,0,fnf_handle);
7258 SSVAL(params,2,0); /* No changes */
7259 SSVAL(params,4,0); /* No EA errors */
7266 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7271 /****************************************************************************
7272 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7273 changes). Currently this does nothing.
7274 ****************************************************************************/
7276 static void call_trans2findnotifynext(connection_struct *conn,
7277 struct smb_request *req,
7278 char **pparams, int total_params,
7279 char **ppdata, int total_data,
7280 unsigned int max_data_bytes)
7282 char *params = *pparams;
7284 DEBUG(3,("call_trans2findnotifynext\n"));
7286 /* Realloc the parameter and data sizes */
7287 *pparams = (char *)SMB_REALLOC(*pparams,4);
7288 if (*pparams == NULL) {
7289 reply_nterror(req, NT_STATUS_NO_MEMORY);
7294 SSVAL(params,0,0); /* No changes */
7295 SSVAL(params,2,0); /* No EA errors */
7297 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7302 /****************************************************************************
7303 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7304 ****************************************************************************/
7306 static void call_trans2getdfsreferral(connection_struct *conn,
7307 struct smb_request *req,
7308 char **pparams, int total_params,
7309 char **ppdata, int total_data,
7310 unsigned int max_data_bytes)
7312 char *params = *pparams;
7313 char *pathname = NULL;
7315 int max_referral_level;
7316 NTSTATUS status = NT_STATUS_OK;
7317 TALLOC_CTX *ctx = talloc_tos();
7319 DEBUG(10,("call_trans2getdfsreferral\n"));
7321 if (total_params < 3) {
7322 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7326 max_referral_level = SVAL(params,0);
7328 if(!lp_host_msdfs()) {
7329 reply_doserror(req, ERRDOS, ERRbadfunc);
7333 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7334 total_params - 2, STR_TERMINATE);
7336 reply_nterror(req, NT_STATUS_NOT_FOUND);
7339 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7340 ppdata,&status)) < 0) {
7341 reply_nterror(req, status);
7345 SSVAL(req->inbuf, smb_flg2,
7346 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7347 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7352 #define LMCAT_SPL 0x53
7353 #define LMFUNC_GETJOBID 0x60
7355 /****************************************************************************
7356 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7357 ****************************************************************************/
7359 static void call_trans2ioctl(connection_struct *conn,
7360 struct smb_request *req,
7361 char **pparams, int total_params,
7362 char **ppdata, int total_data,
7363 unsigned int max_data_bytes)
7365 char *pdata = *ppdata;
7366 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7368 /* check for an invalid fid before proceeding */
7371 reply_doserror(req, ERRDOS, ERRbadfid);
7375 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7376 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7377 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7378 if (*ppdata == NULL) {
7379 reply_nterror(req, NT_STATUS_NO_MEMORY);
7384 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7385 CAN ACCEPT THIS IN UNICODE. JRA. */
7387 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7388 srvstr_push(pdata, req->flags2, pdata + 2,
7389 global_myname(), 15,
7390 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7391 srvstr_push(pdata, req->flags2, pdata+18,
7392 lp_servicename(SNUM(conn)), 13,
7393 STR_ASCII|STR_TERMINATE); /* Service name */
7394 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7399 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7400 reply_doserror(req, ERRSRV, ERRerror);
7403 /****************************************************************************
7404 Reply to a SMBfindclose (stop trans2 directory search).
7405 ****************************************************************************/
7407 void reply_findclose(struct smb_request *req)
7411 START_PROFILE(SMBfindclose);
7414 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7415 END_PROFILE(SMBfindclose);
7419 dptr_num = SVALS(req->vwv+0, 0);
7421 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7423 dptr_close(&dptr_num);
7425 reply_outbuf(req, 0, 0);
7427 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7429 END_PROFILE(SMBfindclose);
7433 /****************************************************************************
7434 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7435 ****************************************************************************/
7437 void reply_findnclose(struct smb_request *req)
7441 START_PROFILE(SMBfindnclose);
7444 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7445 END_PROFILE(SMBfindnclose);
7449 dptr_num = SVAL(req->vwv+0, 0);
7451 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7453 /* We never give out valid handles for a
7454 findnotifyfirst - so any dptr_num is ok here.
7457 reply_outbuf(req, 0, 0);
7459 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7461 END_PROFILE(SMBfindnclose);
7465 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7466 struct trans_state *state)
7468 if (Protocol >= PROTOCOL_NT1) {
7469 req->flags2 |= 0x40; /* IS_LONG_NAME */
7470 SSVAL(req->inbuf,smb_flg2,req->flags2);
7473 if (conn->encrypt_level == Required && !req->encrypted) {
7474 if (state->call != TRANSACT2_QFSINFO &&
7475 state->call != TRANSACT2_SETFSINFO) {
7476 DEBUG(0,("handle_trans2: encryption required "
7478 (unsigned int)state->call));
7479 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7484 /* Now we must call the relevant TRANS2 function */
7485 switch(state->call) {
7486 case TRANSACT2_OPEN:
7488 START_PROFILE(Trans2_open);
7489 call_trans2open(conn, req,
7490 &state->param, state->total_param,
7491 &state->data, state->total_data,
7492 state->max_data_return);
7493 END_PROFILE(Trans2_open);
7497 case TRANSACT2_FINDFIRST:
7499 START_PROFILE(Trans2_findfirst);
7500 call_trans2findfirst(conn, req,
7501 &state->param, state->total_param,
7502 &state->data, state->total_data,
7503 state->max_data_return);
7504 END_PROFILE(Trans2_findfirst);
7508 case TRANSACT2_FINDNEXT:
7510 START_PROFILE(Trans2_findnext);
7511 call_trans2findnext(conn, req,
7512 &state->param, state->total_param,
7513 &state->data, state->total_data,
7514 state->max_data_return);
7515 END_PROFILE(Trans2_findnext);
7519 case TRANSACT2_QFSINFO:
7521 START_PROFILE(Trans2_qfsinfo);
7522 call_trans2qfsinfo(conn, req,
7523 &state->param, state->total_param,
7524 &state->data, state->total_data,
7525 state->max_data_return);
7526 END_PROFILE(Trans2_qfsinfo);
7530 case TRANSACT2_SETFSINFO:
7532 START_PROFILE(Trans2_setfsinfo);
7533 call_trans2setfsinfo(conn, req,
7534 &state->param, state->total_param,
7535 &state->data, state->total_data,
7536 state->max_data_return);
7537 END_PROFILE(Trans2_setfsinfo);
7541 case TRANSACT2_QPATHINFO:
7542 case TRANSACT2_QFILEINFO:
7544 START_PROFILE(Trans2_qpathinfo);
7545 call_trans2qfilepathinfo(conn, req, state->call,
7546 &state->param, state->total_param,
7547 &state->data, state->total_data,
7548 state->max_data_return);
7549 END_PROFILE(Trans2_qpathinfo);
7553 case TRANSACT2_SETPATHINFO:
7554 case TRANSACT2_SETFILEINFO:
7556 START_PROFILE(Trans2_setpathinfo);
7557 call_trans2setfilepathinfo(conn, req, state->call,
7558 &state->param, state->total_param,
7559 &state->data, state->total_data,
7560 state->max_data_return);
7561 END_PROFILE(Trans2_setpathinfo);
7565 case TRANSACT2_FINDNOTIFYFIRST:
7567 START_PROFILE(Trans2_findnotifyfirst);
7568 call_trans2findnotifyfirst(conn, req,
7569 &state->param, state->total_param,
7570 &state->data, state->total_data,
7571 state->max_data_return);
7572 END_PROFILE(Trans2_findnotifyfirst);
7576 case TRANSACT2_FINDNOTIFYNEXT:
7578 START_PROFILE(Trans2_findnotifynext);
7579 call_trans2findnotifynext(conn, req,
7580 &state->param, state->total_param,
7581 &state->data, state->total_data,
7582 state->max_data_return);
7583 END_PROFILE(Trans2_findnotifynext);
7587 case TRANSACT2_MKDIR:
7589 START_PROFILE(Trans2_mkdir);
7590 call_trans2mkdir(conn, req,
7591 &state->param, state->total_param,
7592 &state->data, state->total_data,
7593 state->max_data_return);
7594 END_PROFILE(Trans2_mkdir);
7598 case TRANSACT2_GET_DFS_REFERRAL:
7600 START_PROFILE(Trans2_get_dfs_referral);
7601 call_trans2getdfsreferral(conn, req,
7602 &state->param, state->total_param,
7603 &state->data, state->total_data,
7604 state->max_data_return);
7605 END_PROFILE(Trans2_get_dfs_referral);
7609 case TRANSACT2_IOCTL:
7611 START_PROFILE(Trans2_ioctl);
7612 call_trans2ioctl(conn, req,
7613 &state->param, state->total_param,
7614 &state->data, state->total_data,
7615 state->max_data_return);
7616 END_PROFILE(Trans2_ioctl);
7621 /* Error in request */
7622 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7623 reply_doserror(req, ERRSRV,ERRerror);
7627 /****************************************************************************
7628 Reply to a SMBtrans2.
7629 ****************************************************************************/
7631 void reply_trans2(struct smb_request *req)
7633 connection_struct *conn = req->conn;
7638 unsigned int tran_call;
7639 struct trans_state *state;
7642 START_PROFILE(SMBtrans2);
7644 if (req->wct < 14) {
7645 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7646 END_PROFILE(SMBtrans2);
7650 dsoff = SVAL(req->vwv+12, 0);
7651 dscnt = SVAL(req->vwv+11, 0);
7652 psoff = SVAL(req->vwv+10, 0);
7653 pscnt = SVAL(req->vwv+9, 0);
7654 tran_call = SVAL(req->vwv+14, 0);
7656 result = allow_new_trans(conn->pending_trans, req->mid);
7657 if (!NT_STATUS_IS_OK(result)) {
7658 DEBUG(2, ("Got invalid trans2 request: %s\n",
7659 nt_errstr(result)));
7660 reply_nterror(req, result);
7661 END_PROFILE(SMBtrans2);
7666 switch (tran_call) {
7667 /* List the allowed trans2 calls on IPC$ */
7668 case TRANSACT2_OPEN:
7669 case TRANSACT2_GET_DFS_REFERRAL:
7670 case TRANSACT2_QFILEINFO:
7671 case TRANSACT2_QFSINFO:
7672 case TRANSACT2_SETFSINFO:
7675 reply_doserror(req, ERRSRV, ERRaccess);
7676 END_PROFILE(SMBtrans2);
7681 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7682 DEBUG(0, ("talloc failed\n"));
7683 reply_nterror(req, NT_STATUS_NO_MEMORY);
7684 END_PROFILE(SMBtrans2);
7688 state->cmd = SMBtrans2;
7690 state->mid = req->mid;
7691 state->vuid = req->vuid;
7692 state->setup_count = SVAL(req->vwv+13, 0);
7693 state->setup = NULL;
7694 state->total_param = SVAL(req->vwv+0, 0);
7695 state->param = NULL;
7696 state->total_data = SVAL(req->vwv+1, 0);
7698 state->max_param_return = SVAL(req->vwv+2, 0);
7699 state->max_data_return = SVAL(req->vwv+3, 0);
7700 state->max_setup_return = SVAL(req->vwv+4, 0);
7701 state->close_on_completion = BITSETW(req->vwv+5, 0);
7702 state->one_way = BITSETW(req->vwv+5, 1);
7704 state->call = tran_call;
7706 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7707 is so as a sanity check */
7708 if (state->setup_count != 1) {
7710 * Need to have rc=0 for ioctl to get job id for OS/2.
7711 * Network printing will fail if function is not successful.
7712 * Similar function in reply.c will be used if protocol
7713 * is LANMAN1.0 instead of LM1.2X002.
7714 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7715 * outbuf doesn't have to be set(only job id is used).
7717 if ( (state->setup_count == 4)
7718 && (tran_call == TRANSACT2_IOCTL)
7719 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7720 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7721 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7723 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7724 DEBUG(2,("Transaction is %d\n",tran_call));
7726 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7727 END_PROFILE(SMBtrans2);
7732 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7735 if (state->total_data) {
7737 if (trans_oob(state->total_data, 0, dscnt)
7738 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7742 /* Can't use talloc here, the core routines do realloc on the
7743 * params and data. */
7744 state->data = (char *)SMB_MALLOC(state->total_data);
7745 if (state->data == NULL) {
7746 DEBUG(0,("reply_trans2: data malloc fail for %u "
7747 "bytes !\n", (unsigned int)state->total_data));
7749 reply_nterror(req, NT_STATUS_NO_MEMORY);
7750 END_PROFILE(SMBtrans2);
7754 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7757 if (state->total_param) {
7759 if (trans_oob(state->total_param, 0, pscnt)
7760 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7764 /* Can't use talloc here, the core routines do realloc on the
7765 * params and data. */
7766 state->param = (char *)SMB_MALLOC(state->total_param);
7767 if (state->param == NULL) {
7768 DEBUG(0,("reply_trans: param malloc fail for %u "
7769 "bytes !\n", (unsigned int)state->total_param));
7770 SAFE_FREE(state->data);
7772 reply_nterror(req, NT_STATUS_NO_MEMORY);
7773 END_PROFILE(SMBtrans2);
7777 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7780 state->received_data = dscnt;
7781 state->received_param = pscnt;
7783 if ((state->received_param == state->total_param) &&
7784 (state->received_data == state->total_data)) {
7786 handle_trans2(conn, req, state);
7788 SAFE_FREE(state->data);
7789 SAFE_FREE(state->param);
7791 END_PROFILE(SMBtrans2);
7795 DLIST_ADD(conn->pending_trans, state);
7797 /* We need to send an interim response then receive the rest
7798 of the parameter/data bytes */
7799 reply_outbuf(req, 0, 0);
7800 show_msg((char *)req->outbuf);
7801 END_PROFILE(SMBtrans2);
7806 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7807 SAFE_FREE(state->data);
7808 SAFE_FREE(state->param);
7810 END_PROFILE(SMBtrans2);
7811 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7815 /****************************************************************************
7816 Reply to a SMBtranss2
7817 ****************************************************************************/
7819 void reply_transs2(struct smb_request *req)
7821 connection_struct *conn = req->conn;
7822 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7823 struct trans_state *state;
7825 START_PROFILE(SMBtranss2);
7827 show_msg((char *)req->inbuf);
7830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7831 END_PROFILE(SMBtranss2);
7835 for (state = conn->pending_trans; state != NULL;
7836 state = state->next) {
7837 if (state->mid == req->mid) {
7842 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7843 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7844 END_PROFILE(SMBtranss2);
7848 /* Revise state->total_param and state->total_data in case they have
7849 changed downwards */
7851 if (SVAL(req->vwv+0, 0) < state->total_param)
7852 state->total_param = SVAL(req->vwv+0, 0);
7853 if (SVAL(req->vwv+1, 0) < state->total_data)
7854 state->total_data = SVAL(req->vwv+1, 0);
7856 pcnt = SVAL(req->vwv+2, 0);
7857 poff = SVAL(req->vwv+3, 0);
7858 pdisp = SVAL(req->vwv+4, 0);
7860 dcnt = SVAL(req->vwv+5, 0);
7861 doff = SVAL(req->vwv+6, 0);
7862 ddisp = SVAL(req->vwv+7, 0);
7864 state->received_param += pcnt;
7865 state->received_data += dcnt;
7867 if ((state->received_data > state->total_data) ||
7868 (state->received_param > state->total_param))
7872 if (trans_oob(state->total_param, pdisp, pcnt)
7873 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7876 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7880 if (trans_oob(state->total_data, ddisp, dcnt)
7881 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7884 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7887 if ((state->received_param < state->total_param) ||
7888 (state->received_data < state->total_data)) {
7889 END_PROFILE(SMBtranss2);
7893 handle_trans2(conn, req, state);
7895 DLIST_REMOVE(conn->pending_trans, state);
7896 SAFE_FREE(state->data);
7897 SAFE_FREE(state->param);
7900 END_PROFILE(SMBtranss2);
7905 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7906 DLIST_REMOVE(conn->pending_trans, state);
7907 SAFE_FREE(state->data);
7908 SAFE_FREE(state->param);
7910 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7911 END_PROFILE(SMBtranss2);