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 = create_file(conn, /* conn */
1011 0, /* root_dir_fid */
1013 access_mask, /* access_mask */
1014 share_mode, /* share_access */
1015 create_disposition, /* create_disposition*/
1016 create_options, /* create_options */
1017 open_attr, /* file_attributes */
1018 oplock_request, /* oplock_request */
1019 open_size, /* allocation_size */
1021 ea_list, /* ea_list */
1023 &smb_action, /* pinfo */
1026 if (!NT_STATUS_IS_OK(status)) {
1027 if (open_was_deferred(req->mid)) {
1028 /* We have re-scheduled this call. */
1031 reply_openerror(req, status);
1035 size = get_file_size(sbuf);
1036 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1037 mtime = sbuf.st_mtime;
1038 inode = sbuf.st_ino;
1040 close_file(req, fsp, ERROR_CLOSE);
1041 reply_doserror(req, ERRDOS,ERRnoaccess);
1045 /* Realloc the size of parameters and data we will return */
1046 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1047 if(*pparams == NULL ) {
1048 reply_nterror(req, NT_STATUS_NO_MEMORY);
1053 SSVAL(params,0,fsp->fnum);
1054 SSVAL(params,2,fattr);
1055 srv_put_dos_date2(params,4, mtime);
1056 SIVAL(params,8, (uint32)size);
1057 SSVAL(params,12,deny_mode);
1058 SSVAL(params,14,0); /* open_type - file or directory. */
1059 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1061 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1062 smb_action |= EXTENDED_OPLOCK_GRANTED;
1065 SSVAL(params,18,smb_action);
1068 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1070 SIVAL(params,20,inode);
1071 SSVAL(params,24,0); /* Padding. */
1073 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1074 SIVAL(params, 26, ea_size);
1076 SIVAL(params, 26, 0);
1079 /* Send the required number of replies */
1080 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1083 /*********************************************************
1084 Routine to check if a given string matches exactly.
1085 as a special case a mask of "." does NOT match. That
1086 is required for correct wildcard semantics
1087 Case can be significant or not.
1088 **********************************************************/
1090 static bool exact_match(connection_struct *conn,
1094 if (mask[0] == '.' && mask[1] == 0)
1096 if (conn->case_sensitive)
1097 return strcmp(str,mask)==0;
1098 if (StrCaseCmp(str,mask) != 0) {
1101 if (dptr_has_wild(conn->dirptr)) {
1107 /****************************************************************************
1108 Return the filetype for UNIX extensions.
1109 ****************************************************************************/
1111 static uint32 unix_filetype(mode_t mode)
1114 return UNIX_TYPE_FILE;
1115 else if(S_ISDIR(mode))
1116 return UNIX_TYPE_DIR;
1118 else if(S_ISLNK(mode))
1119 return UNIX_TYPE_SYMLINK;
1122 else if(S_ISCHR(mode))
1123 return UNIX_TYPE_CHARDEV;
1126 else if(S_ISBLK(mode))
1127 return UNIX_TYPE_BLKDEV;
1130 else if(S_ISFIFO(mode))
1131 return UNIX_TYPE_FIFO;
1134 else if(S_ISSOCK(mode))
1135 return UNIX_TYPE_SOCKET;
1138 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1139 return UNIX_TYPE_UNKNOWN;
1142 /****************************************************************************
1143 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1144 ****************************************************************************/
1146 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1148 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1149 SMB_STRUCT_STAT *psbuf,
1151 enum perm_type ptype,
1156 if (perms == SMB_MODE_NO_CHANGE) {
1157 if (!VALID_STAT(*psbuf)) {
1158 return NT_STATUS_INVALID_PARAMETER;
1160 *ret_perms = psbuf->st_mode;
1161 return NT_STATUS_OK;
1165 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1166 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1167 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1168 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1169 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1170 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1171 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1172 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1173 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1175 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1178 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1181 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1186 /* Apply mode mask */
1187 ret &= lp_create_mask(SNUM(conn));
1188 /* Add in force bits */
1189 ret |= lp_force_create_mode(SNUM(conn));
1192 ret &= lp_dir_mask(SNUM(conn));
1193 /* Add in force bits */
1194 ret |= lp_force_dir_mode(SNUM(conn));
1196 case PERM_EXISTING_FILE:
1197 /* Apply mode mask */
1198 ret &= lp_security_mask(SNUM(conn));
1199 /* Add in force bits */
1200 ret |= lp_force_security_mode(SNUM(conn));
1202 case PERM_EXISTING_DIR:
1203 /* Apply mode mask */
1204 ret &= lp_dir_security_mask(SNUM(conn));
1205 /* Add in force bits */
1206 ret |= lp_force_dir_security_mode(SNUM(conn));
1211 return NT_STATUS_OK;
1214 /****************************************************************************
1215 Needed to show the msdfs symlinks as directories. Modifies psbuf
1216 to be a directory if it's a msdfs link.
1217 ****************************************************************************/
1219 static bool check_msdfs_link(connection_struct *conn,
1220 const char *pathname,
1221 SMB_STRUCT_STAT *psbuf)
1223 int saved_errno = errno;
1224 if(lp_host_msdfs() &&
1225 lp_msdfs_root(SNUM(conn)) &&
1226 is_msdfs_link(conn, pathname, psbuf)) {
1228 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1231 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1232 errno = saved_errno;
1235 errno = saved_errno;
1240 /****************************************************************************
1241 Get a level dependent lanman2 dir entry.
1242 ****************************************************************************/
1244 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1245 connection_struct *conn,
1247 const char *path_mask,
1250 int requires_resume_key,
1256 int space_remaining,
1258 bool *got_exact_match,
1259 int *last_entry_off,
1260 struct ea_list *name_list)
1264 SMB_STRUCT_STAT sbuf;
1265 const char *mask = NULL;
1266 char *pathreal = NULL;
1267 const char *fname = NULL;
1268 char *p, *q, *pdata = *ppdata;
1272 SMB_OFF_T file_size = 0;
1273 uint64_t allocation_size = 0;
1275 struct timespec mdate_ts, adate_ts, create_date_ts;
1276 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1278 char *last_entry_ptr;
1280 uint32 nt_extmode; /* Used for NT connections instead of mode */
1281 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1282 bool check_mangled_names = lp_manglednames(conn->params);
1283 char mangled_name[13]; /* mangled 8.3 name. */
1285 *out_of_space = False;
1286 *got_exact_match = False;
1288 ZERO_STRUCT(mdate_ts);
1289 ZERO_STRUCT(adate_ts);
1290 ZERO_STRUCT(create_date_ts);
1292 if (!conn->dirptr) {
1296 p = strrchr_m(path_mask,'/');
1299 mask = talloc_strdup(ctx,"*.*");
1309 bool ms_dfs_link = False;
1311 /* Needed if we run out of space */
1312 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1313 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1316 * Due to bugs in NT client redirectors we are not using
1317 * resume keys any more - set them to zero.
1318 * Check out the related comments in findfirst/findnext.
1324 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1325 (long)conn->dirptr,curr_dirpos));
1332 * fname may get mangled, dname is never mangled.
1333 * Whenever we're accessing the filesystem we use
1334 * pathreal which is composed from dname.
1340 /* Mangle fname if it's an illegal name. */
1341 if (mangle_must_mangle(dname,conn->params)) {
1342 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1343 continue; /* Error - couldn't mangle. */
1345 fname = mangled_name;
1348 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1349 got_match = mask_match(fname, mask, conn->case_sensitive);
1352 if(!got_match && check_mangled_names &&
1353 !mangle_is_8_3(fname, False, conn->params)) {
1355 * It turns out that NT matches wildcards against
1356 * both long *and* short names. This may explain some
1357 * of the wildcard wierdness from old DOS clients
1358 * that some people have been seeing.... JRA.
1360 /* Force the mangling into 8.3. */
1361 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1362 continue; /* Error - couldn't mangle. */
1365 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1366 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1371 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1373 if (dont_descend && !isdots) {
1379 pathreal = talloc_asprintf(ctx,
1384 pathreal = talloc_asprintf(ctx,
1394 if (INFO_LEVEL_IS_UNIX(info_level)) {
1395 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1396 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1397 pathreal,strerror(errno)));
1398 TALLOC_FREE(pathreal);
1401 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1402 /* Needed to show the msdfs symlinks as
1405 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1407 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1408 pathreal,strerror(errno)));
1409 TALLOC_FREE(pathreal);
1415 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1417 mode = dos_mode(conn,pathreal,&sbuf);
1420 if (!dir_check_ftype(conn,mode,dirtype)) {
1421 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1422 TALLOC_FREE(pathreal);
1426 if (!(mode & aDIR)) {
1427 file_size = get_file_size(sbuf);
1429 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1431 mdate_ts = get_mtimespec(&sbuf);
1432 adate_ts = get_atimespec(&sbuf);
1433 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1435 if (ask_sharemode) {
1436 struct timespec write_time_ts;
1437 struct file_id fileid;
1439 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1440 get_file_infos(fileid, NULL, &write_time_ts);
1441 if (!null_timespec(write_time_ts)) {
1442 mdate_ts = write_time_ts;
1446 if (lp_dos_filetime_resolution(SNUM(conn))) {
1447 dos_filetime_timespec(&create_date_ts);
1448 dos_filetime_timespec(&mdate_ts);
1449 dos_filetime_timespec(&adate_ts);
1452 create_date = convert_timespec_to_time_t(create_date_ts);
1453 mdate = convert_timespec_to_time_t(mdate_ts);
1454 adate = convert_timespec_to_time_t(adate_ts);
1456 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1460 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1467 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1469 switch (info_level) {
1470 case SMB_FIND_INFO_STANDARD:
1471 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1472 if(requires_resume_key) {
1476 srv_put_dos_date2(p,0,create_date);
1477 srv_put_dos_date2(p,4,adate);
1478 srv_put_dos_date2(p,8,mdate);
1479 SIVAL(p,12,(uint32)file_size);
1480 SIVAL(p,16,(uint32)allocation_size);
1484 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1485 p += ucs2_align(base_data, p, 0);
1487 len = srvstr_push(base_data, flags2, p,
1488 fname, PTR_DIFF(end_data, p),
1490 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1492 SCVAL(nameptr, -1, len - 2);
1494 SCVAL(nameptr, -1, 0);
1498 SCVAL(nameptr, -1, len - 1);
1500 SCVAL(nameptr, -1, 0);
1506 case SMB_FIND_EA_SIZE:
1507 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1508 if(requires_resume_key) {
1512 srv_put_dos_date2(p,0,create_date);
1513 srv_put_dos_date2(p,4,adate);
1514 srv_put_dos_date2(p,8,mdate);
1515 SIVAL(p,12,(uint32)file_size);
1516 SIVAL(p,16,(uint32)allocation_size);
1519 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1520 SIVAL(p,22,ea_size); /* Extended attributes */
1524 len = srvstr_push(base_data, flags2,
1525 p, fname, PTR_DIFF(end_data, p),
1526 STR_TERMINATE | STR_NOALIGN);
1527 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1540 SCVAL(nameptr,0,len);
1542 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1545 case SMB_FIND_EA_LIST:
1547 struct ea_list *file_list = NULL;
1550 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1554 if(requires_resume_key) {
1558 srv_put_dos_date2(p,0,create_date);
1559 srv_put_dos_date2(p,4,adate);
1560 srv_put_dos_date2(p,8,mdate);
1561 SIVAL(p,12,(uint32)file_size);
1562 SIVAL(p,16,(uint32)allocation_size);
1564 p += 22; /* p now points to the EA area. */
1566 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1567 name_list = ea_list_union(name_list, file_list, &ea_len);
1569 /* We need to determine if this entry will fit in the space available. */
1570 /* Max string size is 255 bytes. */
1571 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1572 /* Move the dirptr back to prev_dirpos */
1573 dptr_SeekDir(conn->dirptr, prev_dirpos);
1574 *out_of_space = True;
1575 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1576 return False; /* Not finished - just out of space */
1579 /* Push the ea_data followed by the name. */
1580 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1582 len = srvstr_push(base_data, flags2,
1583 p + 1, fname, PTR_DIFF(end_data, p+1),
1584 STR_TERMINATE | STR_NOALIGN);
1585 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1598 SCVAL(nameptr,0,len);
1600 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1604 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1605 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1606 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1608 SIVAL(p,0,reskey); p += 4;
1609 put_long_date_timespec(p,create_date_ts); p += 8;
1610 put_long_date_timespec(p,adate_ts); p += 8;
1611 put_long_date_timespec(p,mdate_ts); p += 8;
1612 put_long_date_timespec(p,mdate_ts); p += 8;
1613 SOFF_T(p,0,file_size); p += 8;
1614 SOFF_T(p,0,allocation_size); p += 8;
1615 SIVAL(p,0,nt_extmode); p += 4;
1616 q = p; p += 4; /* q is placeholder for name length. */
1618 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1619 SIVAL(p,0,ea_size); /* Extended attributes */
1622 /* Clear the short name buffer. This is
1623 * IMPORTANT as not doing so will trigger
1624 * a Win2k client bug. JRA.
1626 if (!was_8_3 && check_mangled_names) {
1627 if (!name_to_8_3(fname,mangled_name,True,
1629 /* Error - mangle failed ! */
1630 memset(mangled_name,'\0',12);
1632 mangled_name[12] = 0;
1633 len = srvstr_push(base_data, flags2,
1634 p+2, mangled_name, 24,
1635 STR_UPPER|STR_UNICODE);
1637 memset(p + 2 + len,'\0',24 - len);
1644 len = srvstr_push(base_data, flags2, p,
1645 fname, PTR_DIFF(end_data, p),
1646 STR_TERMINATE_ASCII);
1649 SIVAL(p,0,0); /* Ensure any padding is null. */
1650 len = PTR_DIFF(p, pdata);
1651 len = (len + 3) & ~3;
1656 case SMB_FIND_FILE_DIRECTORY_INFO:
1657 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1659 SIVAL(p,0,reskey); p += 4;
1660 put_long_date_timespec(p,create_date_ts); p += 8;
1661 put_long_date_timespec(p,adate_ts); p += 8;
1662 put_long_date_timespec(p,mdate_ts); p += 8;
1663 put_long_date_timespec(p,mdate_ts); p += 8;
1664 SOFF_T(p,0,file_size); p += 8;
1665 SOFF_T(p,0,allocation_size); p += 8;
1666 SIVAL(p,0,nt_extmode); p += 4;
1667 len = srvstr_push(base_data, flags2,
1668 p + 4, fname, PTR_DIFF(end_data, p+4),
1669 STR_TERMINATE_ASCII);
1672 SIVAL(p,0,0); /* Ensure any padding is null. */
1673 len = PTR_DIFF(p, pdata);
1674 len = (len + 3) & ~3;
1679 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1680 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1682 SIVAL(p,0,reskey); p += 4;
1683 put_long_date_timespec(p,create_date_ts); p += 8;
1684 put_long_date_timespec(p,adate_ts); p += 8;
1685 put_long_date_timespec(p,mdate_ts); p += 8;
1686 put_long_date_timespec(p,mdate_ts); p += 8;
1687 SOFF_T(p,0,file_size); p += 8;
1688 SOFF_T(p,0,allocation_size); p += 8;
1689 SIVAL(p,0,nt_extmode); p += 4;
1690 q = p; p += 4; /* q is placeholder for name length. */
1692 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1693 SIVAL(p,0,ea_size); /* Extended attributes */
1696 len = srvstr_push(base_data, flags2, p,
1697 fname, PTR_DIFF(end_data, p),
1698 STR_TERMINATE_ASCII);
1702 SIVAL(p,0,0); /* Ensure any padding is null. */
1703 len = PTR_DIFF(p, pdata);
1704 len = (len + 3) & ~3;
1709 case SMB_FIND_FILE_NAMES_INFO:
1710 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1712 SIVAL(p,0,reskey); p += 4;
1714 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1715 acl on a dir (tridge) */
1716 len = srvstr_push(base_data, flags2, p,
1717 fname, PTR_DIFF(end_data, p),
1718 STR_TERMINATE_ASCII);
1721 SIVAL(p,0,0); /* Ensure any padding is null. */
1722 len = PTR_DIFF(p, pdata);
1723 len = (len + 3) & ~3;
1728 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1729 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1731 SIVAL(p,0,reskey); p += 4;
1732 put_long_date_timespec(p,create_date_ts); p += 8;
1733 put_long_date_timespec(p,adate_ts); p += 8;
1734 put_long_date_timespec(p,mdate_ts); p += 8;
1735 put_long_date_timespec(p,mdate_ts); p += 8;
1736 SOFF_T(p,0,file_size); p += 8;
1737 SOFF_T(p,0,allocation_size); p += 8;
1738 SIVAL(p,0,nt_extmode); p += 4;
1739 q = p; p += 4; /* q is placeholder for name length. */
1741 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1742 SIVAL(p,0,ea_size); /* Extended attributes */
1745 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1746 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1747 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1748 len = srvstr_push(base_data, flags2, p,
1749 fname, PTR_DIFF(end_data, p),
1750 STR_TERMINATE_ASCII);
1753 SIVAL(p,0,0); /* Ensure any padding is null. */
1754 len = PTR_DIFF(p, pdata);
1755 len = (len + 3) & ~3;
1760 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1761 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1762 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1764 SIVAL(p,0,reskey); p += 4;
1765 put_long_date_timespec(p,create_date_ts); p += 8;
1766 put_long_date_timespec(p,adate_ts); p += 8;
1767 put_long_date_timespec(p,mdate_ts); p += 8;
1768 put_long_date_timespec(p,mdate_ts); p += 8;
1769 SOFF_T(p,0,file_size); p += 8;
1770 SOFF_T(p,0,allocation_size); p += 8;
1771 SIVAL(p,0,nt_extmode); p += 4;
1772 q = p; p += 4; /* q is placeholder for name length */
1774 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1775 SIVAL(p,0,ea_size); /* Extended attributes */
1778 /* Clear the short name buffer. This is
1779 * IMPORTANT as not doing so will trigger
1780 * a Win2k client bug. JRA.
1782 if (!was_8_3 && check_mangled_names) {
1783 if (!name_to_8_3(fname,mangled_name,True,
1785 /* Error - mangle failed ! */
1786 memset(mangled_name,'\0',12);
1788 mangled_name[12] = 0;
1789 len = srvstr_push(base_data, flags2,
1790 p+2, mangled_name, 24,
1791 STR_UPPER|STR_UNICODE);
1794 memset(p + 2 + len,'\0',24 - len);
1801 SSVAL(p,0,0); p += 2; /* Reserved ? */
1802 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1803 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1804 len = srvstr_push(base_data, flags2, p,
1805 fname, PTR_DIFF(end_data, p),
1806 STR_TERMINATE_ASCII);
1809 SIVAL(p,0,0); /* Ensure any padding is null. */
1810 len = PTR_DIFF(p, pdata);
1811 len = (len + 3) & ~3;
1816 /* CIFS UNIX Extension. */
1818 case SMB_FIND_FILE_UNIX:
1819 case SMB_FIND_FILE_UNIX_INFO2:
1821 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1823 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1825 if (info_level == SMB_FIND_FILE_UNIX) {
1826 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1827 p = store_file_unix_basic(conn, p,
1829 len = srvstr_push(base_data, flags2, p,
1830 fname, PTR_DIFF(end_data, p),
1833 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1834 p = store_file_unix_basic_info2(conn, p,
1838 len = srvstr_push(base_data, flags2, p, fname,
1839 PTR_DIFF(end_data, p), 0);
1840 SIVAL(nameptr, 0, len);
1844 SIVAL(p,0,0); /* Ensure any padding is null. */
1846 len = PTR_DIFF(p, pdata);
1847 len = (len + 3) & ~3;
1848 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1850 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1859 if (PTR_DIFF(p,pdata) > space_remaining) {
1860 /* Move the dirptr back to prev_dirpos */
1861 dptr_SeekDir(conn->dirptr, prev_dirpos);
1862 *out_of_space = True;
1863 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1864 return False; /* Not finished - just out of space */
1867 /* Setup the last entry pointer, as an offset from base_data */
1868 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1869 /* Advance the data pointer to the next slot */
1875 /****************************************************************************
1876 Reply to a TRANS2_FINDFIRST.
1877 ****************************************************************************/
1879 static void call_trans2findfirst(connection_struct *conn,
1880 struct smb_request *req,
1881 char **pparams, int total_params,
1882 char **ppdata, int total_data,
1883 unsigned int max_data_bytes)
1885 /* We must be careful here that we don't return more than the
1886 allowed number of data bytes. If this means returning fewer than
1887 maxentries then so be it. We assume that the redirector has
1888 enough room for the fixed number of parameter bytes it has
1890 char *params = *pparams;
1891 char *pdata = *ppdata;
1895 uint16 findfirst_flags;
1896 bool close_after_first;
1898 bool requires_resume_key;
1900 char *directory = NULL;
1903 int last_entry_off=0;
1907 bool finished = False;
1908 bool dont_descend = False;
1909 bool out_of_space = False;
1910 int space_remaining;
1911 bool mask_contains_wcard = False;
1912 SMB_STRUCT_STAT sbuf;
1913 struct ea_list *ea_list = NULL;
1914 NTSTATUS ntstatus = NT_STATUS_OK;
1915 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1916 TALLOC_CTX *ctx = talloc_tos();
1918 if (total_params < 13) {
1919 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1923 dirtype = SVAL(params,0);
1924 maxentries = SVAL(params,2);
1925 findfirst_flags = SVAL(params,4);
1926 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1927 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1928 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1929 info_level = SVAL(params,6);
1931 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1932 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1933 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1934 info_level, max_data_bytes));
1937 /* W2K3 seems to treat zero as 1. */
1941 switch (info_level) {
1942 case SMB_FIND_INFO_STANDARD:
1943 case SMB_FIND_EA_SIZE:
1944 case SMB_FIND_EA_LIST:
1945 case SMB_FIND_FILE_DIRECTORY_INFO:
1946 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1947 case SMB_FIND_FILE_NAMES_INFO:
1948 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1949 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1950 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1952 case SMB_FIND_FILE_UNIX:
1953 case SMB_FIND_FILE_UNIX_INFO2:
1954 /* Always use filesystem for UNIX mtime query. */
1955 ask_sharemode = false;
1956 if (!lp_unix_extensions()) {
1957 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1962 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1966 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1967 params+12, total_params - 12,
1968 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1969 if (!NT_STATUS_IS_OK(ntstatus)) {
1970 reply_nterror(req, ntstatus);
1974 ntstatus = resolve_dfspath_wcard(ctx, conn,
1975 req->flags2 & FLAGS2_DFS_PATHNAMES,
1978 &mask_contains_wcard);
1979 if (!NT_STATUS_IS_OK(ntstatus)) {
1980 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1981 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1982 ERRSRV, ERRbadpath);
1985 reply_nterror(req, ntstatus);
1989 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1990 if (!NT_STATUS_IS_OK(ntstatus)) {
1991 reply_nterror(req, ntstatus);
1995 ntstatus = check_name(conn, directory);
1996 if (!NT_STATUS_IS_OK(ntstatus)) {
1997 reply_nterror(req, ntstatus);
2001 p = strrchr_m(directory,'/');
2003 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2004 if((directory[0] == '.') && (directory[1] == '\0')) {
2005 mask = talloc_strdup(ctx,"*");
2007 reply_nterror(req, NT_STATUS_NO_MEMORY);
2010 mask_contains_wcard = True;
2012 directory = talloc_strdup(talloc_tos(), "./");
2014 reply_nterror(req, NT_STATUS_NO_MEMORY);
2021 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2023 if (info_level == SMB_FIND_EA_LIST) {
2026 if (total_data < 4) {
2027 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2031 ea_size = IVAL(pdata,0);
2032 if (ea_size != total_data) {
2033 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2034 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2035 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2039 if (!lp_ea_support(SNUM(conn))) {
2040 reply_doserror(req, ERRDOS, ERReasnotsupported);
2044 /* Pull out the list of names. */
2045 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2047 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2052 *ppdata = (char *)SMB_REALLOC(
2053 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2054 if(*ppdata == NULL ) {
2055 reply_nterror(req, NT_STATUS_NO_MEMORY);
2059 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2061 /* Realloc the params space */
2062 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2063 if (*pparams == NULL) {
2064 reply_nterror(req, NT_STATUS_NO_MEMORY);
2069 /* Save the wildcard match and attribs we are using on this directory -
2070 needed as lanman2 assumes these are being saved between calls */
2072 ntstatus = dptr_create(conn,
2078 mask_contains_wcard,
2082 if (!NT_STATUS_IS_OK(ntstatus)) {
2083 reply_nterror(req, ntstatus);
2087 dptr_num = dptr_dnum(conn->dirptr);
2088 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2090 /* We don't need to check for VOL here as this is returned by
2091 a different TRANS2 call. */
2093 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2094 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2095 dont_descend = True;
2098 space_remaining = max_data_bytes;
2099 out_of_space = False;
2101 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2102 bool got_exact_match = False;
2104 /* this is a heuristic to avoid seeking the dirptr except when
2105 absolutely necessary. It allows for a filename of about 40 chars */
2106 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2107 out_of_space = True;
2110 finished = !get_lanman2_dir_entry(ctx,
2113 mask,dirtype,info_level,
2114 requires_resume_key,dont_descend,
2117 space_remaining, &out_of_space,
2119 &last_entry_off, ea_list);
2122 if (finished && out_of_space)
2125 if (!finished && !out_of_space)
2129 * As an optimisation if we know we aren't looking
2130 * for a wildcard name (ie. the name matches the wildcard exactly)
2131 * then we can finish on any (first) match.
2132 * This speeds up large directory searches. JRA.
2138 /* Ensure space_remaining never goes -ve. */
2139 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2140 space_remaining = 0;
2141 out_of_space = true;
2143 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2147 /* Check if we can close the dirptr */
2148 if(close_after_first || (finished && close_if_end)) {
2149 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2150 dptr_close(&dptr_num);
2154 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2155 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2156 * the protocol level is less than NT1. Tested with smbclient. JRA.
2157 * This should fix the OS/2 client bug #2335.
2160 if(numentries == 0) {
2161 dptr_close(&dptr_num);
2162 if (Protocol < PROTOCOL_NT1) {
2163 reply_doserror(req, ERRDOS, ERRnofiles);
2166 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2167 ERRDOS, ERRbadfile);
2172 /* At this point pdata points to numentries directory entries. */
2174 /* Set up the return parameter block */
2175 SSVAL(params,0,dptr_num);
2176 SSVAL(params,2,numentries);
2177 SSVAL(params,4,finished);
2178 SSVAL(params,6,0); /* Never an EA error */
2179 SSVAL(params,8,last_entry_off);
2181 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2184 if ((! *directory) && dptr_path(dptr_num)) {
2185 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2187 reply_nterror(req, NT_STATUS_NO_MEMORY);
2191 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2192 smb_fn_name(req->cmd),
2193 mask, directory, dirtype, numentries ) );
2196 * Force a name mangle here to ensure that the
2197 * mask as an 8.3 name is top of the mangled cache.
2198 * The reasons for this are subtle. Don't remove
2199 * this code unless you know what you are doing
2200 * (see PR#13758). JRA.
2203 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2204 char mangled_name[13];
2205 name_to_8_3(mask, mangled_name, True, conn->params);
2211 /****************************************************************************
2212 Reply to a TRANS2_FINDNEXT.
2213 ****************************************************************************/
2215 static void call_trans2findnext(connection_struct *conn,
2216 struct smb_request *req,
2217 char **pparams, int total_params,
2218 char **ppdata, int total_data,
2219 unsigned int max_data_bytes)
2221 /* We must be careful here that we don't return more than the
2222 allowed number of data bytes. If this means returning fewer than
2223 maxentries then so be it. We assume that the redirector has
2224 enough room for the fixed number of parameter bytes it has
2226 char *params = *pparams;
2227 char *pdata = *ppdata;
2233 uint16 findnext_flags;
2234 bool close_after_request;
2236 bool requires_resume_key;
2238 bool mask_contains_wcard = False;
2239 char *resume_name = NULL;
2240 const char *mask = NULL;
2241 const char *directory = NULL;
2245 int i, last_entry_off=0;
2246 bool finished = False;
2247 bool dont_descend = False;
2248 bool out_of_space = False;
2249 int space_remaining;
2250 struct ea_list *ea_list = NULL;
2251 NTSTATUS ntstatus = NT_STATUS_OK;
2252 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2253 TALLOC_CTX *ctx = talloc_tos();
2255 if (total_params < 13) {
2256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2260 dptr_num = SVAL(params,0);
2261 maxentries = SVAL(params,2);
2262 info_level = SVAL(params,4);
2263 resume_key = IVAL(params,6);
2264 findnext_flags = SVAL(params,10);
2265 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2266 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2267 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2268 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2270 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2272 total_params - 12, STR_TERMINATE, &ntstatus,
2273 &mask_contains_wcard);
2274 if (!NT_STATUS_IS_OK(ntstatus)) {
2275 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2276 complain (it thinks we're asking for the directory above the shared
2277 path or an invalid name). Catch this as the resume name is only compared, never used in
2278 a file access. JRA. */
2279 srvstr_pull_talloc(ctx, params, req->flags2,
2280 &resume_name, params+12,
2284 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2285 reply_nterror(req, ntstatus);
2290 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2291 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2292 resume_key = %d resume name = %s continue=%d level = %d\n",
2293 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2294 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2297 /* W2K3 seems to treat zero as 1. */
2301 switch (info_level) {
2302 case SMB_FIND_INFO_STANDARD:
2303 case SMB_FIND_EA_SIZE:
2304 case SMB_FIND_EA_LIST:
2305 case SMB_FIND_FILE_DIRECTORY_INFO:
2306 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2307 case SMB_FIND_FILE_NAMES_INFO:
2308 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2309 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2310 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2312 case SMB_FIND_FILE_UNIX:
2313 case SMB_FIND_FILE_UNIX_INFO2:
2314 /* Always use filesystem for UNIX mtime query. */
2315 ask_sharemode = false;
2316 if (!lp_unix_extensions()) {
2317 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2322 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2326 if (info_level == SMB_FIND_EA_LIST) {
2329 if (total_data < 4) {
2330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2334 ea_size = IVAL(pdata,0);
2335 if (ea_size != total_data) {
2336 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2337 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2338 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2342 if (!lp_ea_support(SNUM(conn))) {
2343 reply_doserror(req, ERRDOS, ERReasnotsupported);
2347 /* Pull out the list of names. */
2348 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2355 *ppdata = (char *)SMB_REALLOC(
2356 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2357 if(*ppdata == NULL) {
2358 reply_nterror(req, NT_STATUS_NO_MEMORY);
2363 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2365 /* Realloc the params space */
2366 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2367 if(*pparams == NULL ) {
2368 reply_nterror(req, NT_STATUS_NO_MEMORY);
2374 /* Check that the dptr is valid */
2375 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2376 reply_doserror(req, ERRDOS, ERRnofiles);
2380 string_set(&conn->dirpath,dptr_path(dptr_num));
2382 /* Get the wildcard mask from the dptr */
2383 if((p = dptr_wcard(dptr_num))== NULL) {
2384 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2385 reply_doserror(req, ERRDOS, ERRnofiles);
2390 directory = conn->dirpath;
2392 /* Get the attr mask from the dptr */
2393 dirtype = dptr_attr(dptr_num);
2395 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2396 dptr_num, mask, dirtype,
2398 dptr_TellDir(conn->dirptr)));
2400 /* We don't need to check for VOL here as this is returned by
2401 a different TRANS2 call. */
2403 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2404 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2405 dont_descend = True;
2408 space_remaining = max_data_bytes;
2409 out_of_space = False;
2412 * Seek to the correct position. We no longer use the resume key but
2413 * depend on the last file name instead.
2416 if(*resume_name && !continue_bit) {
2419 long current_pos = 0;
2421 * Remember, name_to_8_3 is called by
2422 * get_lanman2_dir_entry(), so the resume name
2423 * could be mangled. Ensure we check the unmangled name.
2426 if (mangle_is_mangled(resume_name, conn->params)) {
2427 char *new_resume_name = NULL;
2428 mangle_lookup_name_from_8_3(ctx,
2432 if (new_resume_name) {
2433 resume_name = new_resume_name;
2438 * Fix for NT redirector problem triggered by resume key indexes
2439 * changing between directory scans. We now return a resume key of 0
2440 * and instead look for the filename to continue from (also given
2441 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2442 * findfirst/findnext (as is usual) then the directory pointer
2443 * should already be at the correct place.
2446 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2447 } /* end if resume_name && !continue_bit */
2449 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2450 bool got_exact_match = False;
2452 /* this is a heuristic to avoid seeking the dirptr except when
2453 absolutely necessary. It allows for a filename of about 40 chars */
2454 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2455 out_of_space = True;
2458 finished = !get_lanman2_dir_entry(ctx,
2461 mask,dirtype,info_level,
2462 requires_resume_key,dont_descend,
2465 space_remaining, &out_of_space,
2467 &last_entry_off, ea_list);
2470 if (finished && out_of_space)
2473 if (!finished && !out_of_space)
2477 * As an optimisation if we know we aren't looking
2478 * for a wildcard name (ie. the name matches the wildcard exactly)
2479 * then we can finish on any (first) match.
2480 * This speeds up large directory searches. JRA.
2486 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2489 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2490 smb_fn_name(req->cmd),
2491 mask, directory, dirtype, numentries ) );
2493 /* Check if we can close the dirptr */
2494 if(close_after_request || (finished && close_if_end)) {
2495 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2496 dptr_close(&dptr_num); /* This frees up the saved mask */
2499 /* Set up the return parameter block */
2500 SSVAL(params,0,numentries);
2501 SSVAL(params,2,finished);
2502 SSVAL(params,4,0); /* Never an EA error */
2503 SSVAL(params,6,last_entry_off);
2505 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2511 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2513 E_md4hash(lp_servicename(SNUM(conn)),objid);
2517 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2519 SMB_ASSERT(extended_info != NULL);
2521 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2522 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2523 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2524 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2525 #ifdef SAMBA_VERSION_REVISION
2526 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2528 extended_info->samba_subversion = 0;
2529 #ifdef SAMBA_VERSION_RC_RELEASE
2530 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2532 #ifdef SAMBA_VERSION_PRE_RELEASE
2533 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2536 #ifdef SAMBA_VERSION_VENDOR_PATCH
2537 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2539 extended_info->samba_gitcommitdate = 0;
2540 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2541 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2544 memset(extended_info->samba_version_string, 0,
2545 sizeof(extended_info->samba_version_string));
2547 snprintf (extended_info->samba_version_string,
2548 sizeof(extended_info->samba_version_string),
2549 "%s", samba_version_string());
2552 /****************************************************************************
2553 Reply to a TRANS2_QFSINFO (query filesystem info).
2554 ****************************************************************************/
2556 static void call_trans2qfsinfo(connection_struct *conn,
2557 struct smb_request *req,
2558 char **pparams, int total_params,
2559 char **ppdata, int total_data,
2560 unsigned int max_data_bytes)
2562 char *pdata, *end_data;
2563 char *params = *pparams;
2567 const char *vname = volume_label(SNUM(conn));
2568 int snum = SNUM(conn);
2569 char *fstype = lp_fstype(SNUM(conn));
2570 uint32 additional_flags = 0;
2572 if (total_params < 2) {
2573 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2577 info_level = SVAL(params,0);
2580 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2581 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2582 "info level (0x%x) on IPC$.\n",
2583 (unsigned int)info_level));
2584 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2589 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2590 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2591 DEBUG(0,("call_trans2qfsinfo: encryption required "
2592 "and info level 0x%x sent.\n",
2593 (unsigned int)info_level));
2594 exit_server_cleanly("encryption required "
2600 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2602 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2603 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2604 reply_doserror(req, ERRSRV, ERRinvdevice);
2608 *ppdata = (char *)SMB_REALLOC(
2609 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2610 if (*ppdata == NULL ) {
2611 reply_nterror(req, NT_STATUS_NO_MEMORY);
2616 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2617 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2619 switch (info_level) {
2620 case SMB_INFO_ALLOCATION:
2622 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2624 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2625 reply_unixerror(req, ERRHRD, ERRgeneral);
2629 block_size = lp_block_size(snum);
2630 if (bsize < block_size) {
2631 uint64_t factor = block_size/bsize;
2636 if (bsize > block_size) {
2637 uint64_t factor = bsize/block_size;
2642 bytes_per_sector = 512;
2643 sectors_per_unit = bsize/bytes_per_sector;
2645 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2646 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2647 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2649 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2650 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2651 SIVAL(pdata,l1_cUnit,dsize);
2652 SIVAL(pdata,l1_cUnitAvail,dfree);
2653 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2657 case SMB_INFO_VOLUME:
2658 /* Return volume name */
2660 * Add volume serial number - hash of a combination of
2661 * the called hostname and the service name.
2663 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2665 * Win2k3 and previous mess this up by sending a name length
2666 * one byte short. I believe only older clients (OS/2 Win9x) use
2667 * this call so try fixing this by adding a terminating null to
2668 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2672 pdata+l2_vol_szVolLabel, vname,
2673 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2674 STR_NOALIGN|STR_TERMINATE);
2675 SCVAL(pdata,l2_vol_cch,len);
2676 data_len = l2_vol_szVolLabel + len;
2677 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2678 (unsigned)st.st_ctime, len, vname));
2681 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2682 case SMB_FS_ATTRIBUTE_INFORMATION:
2684 additional_flags = 0;
2685 #if defined(HAVE_SYS_QUOTAS)
2686 additional_flags |= FILE_VOLUME_QUOTAS;
2689 if(lp_nt_acl_support(SNUM(conn))) {
2690 additional_flags |= FILE_PERSISTENT_ACLS;
2693 /* Capabilities are filled in at connection time through STATVFS call */
2694 additional_flags |= conn->fs_capabilities;
2696 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2697 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2698 additional_flags); /* FS ATTRIBUTES */
2700 SIVAL(pdata,4,255); /* Max filename component length */
2701 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2702 and will think we can't do long filenames */
2703 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2704 PTR_DIFF(end_data, pdata+12),
2707 data_len = 12 + len;
2710 case SMB_QUERY_FS_LABEL_INFO:
2711 case SMB_FS_LABEL_INFORMATION:
2712 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2713 PTR_DIFF(end_data, pdata+4), 0);
2718 case SMB_QUERY_FS_VOLUME_INFO:
2719 case SMB_FS_VOLUME_INFORMATION:
2722 * Add volume serial number - hash of a combination of
2723 * the called hostname and the service name.
2725 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2726 (str_checksum(get_local_machine_name())<<16));
2728 /* Max label len is 32 characters. */
2729 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2730 PTR_DIFF(end_data, pdata+18),
2732 SIVAL(pdata,12,len);
2735 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2736 (int)strlen(vname),vname, lp_servicename(snum)));
2739 case SMB_QUERY_FS_SIZE_INFO:
2740 case SMB_FS_SIZE_INFORMATION:
2742 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2744 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2745 reply_unixerror(req, ERRHRD, ERRgeneral);
2748 block_size = lp_block_size(snum);
2749 if (bsize < block_size) {
2750 uint64_t factor = block_size/bsize;
2755 if (bsize > block_size) {
2756 uint64_t factor = bsize/block_size;
2761 bytes_per_sector = 512;
2762 sectors_per_unit = bsize/bytes_per_sector;
2763 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2764 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2765 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2766 SBIG_UINT(pdata,0,dsize);
2767 SBIG_UINT(pdata,8,dfree);
2768 SIVAL(pdata,16,sectors_per_unit);
2769 SIVAL(pdata,20,bytes_per_sector);
2773 case SMB_FS_FULL_SIZE_INFORMATION:
2775 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2777 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2778 reply_unixerror(req, ERRHRD, ERRgeneral);
2781 block_size = lp_block_size(snum);
2782 if (bsize < block_size) {
2783 uint64_t factor = block_size/bsize;
2788 if (bsize > block_size) {
2789 uint64_t factor = bsize/block_size;
2794 bytes_per_sector = 512;
2795 sectors_per_unit = bsize/bytes_per_sector;
2796 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2797 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2798 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2799 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2800 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2801 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2802 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2803 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2807 case SMB_QUERY_FS_DEVICE_INFO:
2808 case SMB_FS_DEVICE_INFORMATION:
2810 SIVAL(pdata,0,0); /* dev type */
2811 SIVAL(pdata,4,0); /* characteristics */
2814 #ifdef HAVE_SYS_QUOTAS
2815 case SMB_FS_QUOTA_INFORMATION:
2817 * what we have to send --metze:
2819 * Unknown1: 24 NULL bytes
2820 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2821 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2822 * Quota Flags: 2 byte :
2823 * Unknown3: 6 NULL bytes
2827 * details for Quota Flags:
2829 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2830 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2831 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2832 * 0x0001 Enable Quotas: enable quota for this fs
2836 /* we need to fake up a fsp here,
2837 * because its not send in this call
2840 SMB_NTQUOTA_STRUCT quotas;
2843 ZERO_STRUCT(quotas);
2849 if (conn->server_info->utok.uid != 0) {
2850 DEBUG(0,("set_user_quota: access_denied "
2851 "service [%s] user [%s]\n",
2852 lp_servicename(SNUM(conn)),
2853 conn->server_info->unix_name));
2854 reply_doserror(req, ERRDOS, ERRnoaccess);
2858 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2859 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2860 reply_doserror(req, ERRSRV, ERRerror);
2866 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2868 /* Unknown1 24 NULL bytes*/
2869 SBIG_UINT(pdata,0,(uint64_t)0);
2870 SBIG_UINT(pdata,8,(uint64_t)0);
2871 SBIG_UINT(pdata,16,(uint64_t)0);
2873 /* Default Soft Quota 8 bytes */
2874 SBIG_UINT(pdata,24,quotas.softlim);
2876 /* Default Hard Quota 8 bytes */
2877 SBIG_UINT(pdata,32,quotas.hardlim);
2879 /* Quota flag 2 bytes */
2880 SSVAL(pdata,40,quotas.qflags);
2882 /* Unknown3 6 NULL bytes */
2888 #endif /* HAVE_SYS_QUOTAS */
2889 case SMB_FS_OBJECTID_INFORMATION:
2891 unsigned char objid[16];
2892 struct smb_extended_info extended_info;
2893 memcpy(pdata,create_volume_objectid(conn, objid),16);
2894 samba_extended_info_version (&extended_info);
2895 SIVAL(pdata,16,extended_info.samba_magic);
2896 SIVAL(pdata,20,extended_info.samba_version);
2897 SIVAL(pdata,24,extended_info.samba_subversion);
2898 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2899 memcpy(pdata+36,extended_info.samba_version_string,28);
2905 * Query the version and capabilities of the CIFS UNIX extensions
2909 case SMB_QUERY_CIFS_UNIX_INFO:
2911 bool large_write = lp_min_receive_file_size() &&
2912 !srv_is_signing_active();
2913 bool large_read = !srv_is_signing_active();
2914 int encrypt_caps = 0;
2916 if (!lp_unix_extensions()) {
2917 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2921 switch (conn->encrypt_level) {
2927 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2930 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2931 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2932 large_write = false;
2938 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2939 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2941 /* We have POSIX ACLs, pathname, encryption,
2942 * large read/write, and locking capability. */
2944 SBIG_UINT(pdata,4,((uint64_t)(
2945 CIFS_UNIX_POSIX_ACLS_CAP|
2946 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2947 CIFS_UNIX_FCNTL_LOCKS_CAP|
2948 CIFS_UNIX_EXTATTR_CAP|
2949 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2951 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2953 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2957 case SMB_QUERY_POSIX_FS_INFO:
2960 vfs_statvfs_struct svfs;
2962 if (!lp_unix_extensions()) {
2963 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2967 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2971 SIVAL(pdata,0,svfs.OptimalTransferSize);
2972 SIVAL(pdata,4,svfs.BlockSize);
2973 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2974 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2975 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2976 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2977 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2978 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2979 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2981 } else if (rc == EOPNOTSUPP) {
2982 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2984 #endif /* EOPNOTSUPP */
2986 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2987 reply_doserror(req, ERRSRV, ERRerror);
2993 case SMB_QUERY_POSIX_WHOAMI:
2999 if (!lp_unix_extensions()) {
3000 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3004 if (max_data_bytes < 40) {
3005 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3009 /* We ARE guest if global_sid_Builtin_Guests is
3010 * in our list of SIDs.
3012 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3013 conn->server_info->ptok)) {
3014 flags |= SMB_WHOAMI_GUEST;
3017 /* We are NOT guest if global_sid_Authenticated_Users
3018 * is in our list of SIDs.
3020 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3021 conn->server_info->ptok)) {
3022 flags &= ~SMB_WHOAMI_GUEST;
3025 /* NOTE: 8 bytes for UID/GID, irrespective of native
3026 * platform size. This matches
3027 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3029 data_len = 4 /* flags */
3036 + 4 /* pad/reserved */
3037 + (conn->server_info->utok.ngroups * 8)
3039 + (conn->server_info->ptok->num_sids *
3043 SIVAL(pdata, 0, flags);
3044 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3046 (uint64_t)conn->server_info->utok.uid);
3047 SBIG_UINT(pdata, 16,
3048 (uint64_t)conn->server_info->utok.gid);
3051 if (data_len >= max_data_bytes) {
3052 /* Potential overflow, skip the GIDs and SIDs. */
3054 SIVAL(pdata, 24, 0); /* num_groups */
3055 SIVAL(pdata, 28, 0); /* num_sids */
3056 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3057 SIVAL(pdata, 36, 0); /* reserved */
3063 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3064 SIVAL(pdata, 28, conn->server_info->num_sids);
3066 /* We walk the SID list twice, but this call is fairly
3067 * infrequent, and I don't expect that it's performance
3068 * sensitive -- jpeach
3070 for (i = 0, sid_bytes = 0;
3071 i < conn->server_info->ptok->num_sids; ++i) {
3072 sid_bytes += ndr_size_dom_sid(
3073 &conn->server_info->ptok->user_sids[i],
3077 /* SID list byte count */
3078 SIVAL(pdata, 32, sid_bytes);
3080 /* 4 bytes pad/reserved - must be zero */
3081 SIVAL(pdata, 36, 0);
3085 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3086 SBIG_UINT(pdata, data_len,
3087 (uint64_t)conn->server_info->utok.groups[i]);
3093 i < conn->server_info->ptok->num_sids; ++i) {
3094 int sid_len = ndr_size_dom_sid(
3095 &conn->server_info->ptok->user_sids[i],
3098 sid_linearize(pdata + data_len, sid_len,
3099 &conn->server_info->ptok->user_sids[i]);
3100 data_len += sid_len;
3106 case SMB_MAC_QUERY_FS_INFO:
3108 * Thursby MAC extension... ONLY on NTFS filesystems
3109 * once we do streams then we don't need this
3111 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3113 SIVAL(pdata,84,0x100); /* Don't support mac... */
3118 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3123 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3126 DEBUG( 4, ( "%s info_level = %d\n",
3127 smb_fn_name(req->cmd), info_level) );
3132 /****************************************************************************
3133 Reply to a TRANS2_SETFSINFO (set filesystem info).
3134 ****************************************************************************/
3136 static void call_trans2setfsinfo(connection_struct *conn,
3137 struct smb_request *req,
3138 char **pparams, int total_params,
3139 char **ppdata, int total_data,
3140 unsigned int max_data_bytes)
3142 char *pdata = *ppdata;
3143 char *params = *pparams;
3146 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3149 if (total_params < 4) {
3150 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3156 info_level = SVAL(params,2);
3159 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3160 info_level != SMB_SET_CIFS_UNIX_INFO) {
3161 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3162 "info level (0x%x) on IPC$.\n",
3163 (unsigned int)info_level));
3164 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3169 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3170 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3171 DEBUG(0,("call_trans2setfsinfo: encryption required "
3172 "and info level 0x%x sent.\n",
3173 (unsigned int)info_level));
3174 exit_server_cleanly("encryption required "
3180 switch(info_level) {
3181 case SMB_SET_CIFS_UNIX_INFO:
3183 uint16 client_unix_major;
3184 uint16 client_unix_minor;
3185 uint32 client_unix_cap_low;
3186 uint32 client_unix_cap_high;
3188 if (!lp_unix_extensions()) {
3190 NT_STATUS_INVALID_LEVEL);
3194 /* There should be 12 bytes of capabilities set. */
3195 if (total_data < 8) {
3198 NT_STATUS_INVALID_PARAMETER);
3201 client_unix_major = SVAL(pdata,0);
3202 client_unix_minor = SVAL(pdata,2);
3203 client_unix_cap_low = IVAL(pdata,4);
3204 client_unix_cap_high = IVAL(pdata,8);
3205 /* Just print these values for now. */
3206 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3207 cap_low = 0x%x, cap_high = 0x%x\n",
3208 (unsigned int)client_unix_major,
3209 (unsigned int)client_unix_minor,
3210 (unsigned int)client_unix_cap_low,
3211 (unsigned int)client_unix_cap_high ));
3213 /* Here is where we must switch to posix pathname processing... */
3214 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3215 lp_set_posix_pathnames();
3216 mangle_change_to_posix();
3219 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3220 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3221 /* Client that knows how to do posix locks,
3222 * but not posix open/mkdir operations. Set a
3223 * default type for read/write checks. */
3225 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3231 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3234 size_t param_len = 0;
3235 size_t data_len = total_data;
3237 if (!lp_unix_extensions()) {
3240 NT_STATUS_INVALID_LEVEL);
3244 if (lp_smb_encrypt(SNUM(conn)) == false) {
3247 NT_STATUS_NOT_SUPPORTED);
3251 DEBUG( 4,("call_trans2setfsinfo: "
3252 "request transport encryption.\n"));
3254 status = srv_request_encryption_setup(conn,
3255 (unsigned char **)ppdata,
3257 (unsigned char **)pparams,
3260 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3261 !NT_STATUS_IS_OK(status)) {
3262 reply_nterror(req, status);
3266 send_trans2_replies(conn, req,
3273 if (NT_STATUS_IS_OK(status)) {
3274 /* Server-side transport
3275 * encryption is now *on*. */
3276 status = srv_encryption_start(conn);
3277 if (!NT_STATUS_IS_OK(status)) {
3278 exit_server_cleanly(
3279 "Failure in setting "
3280 "up encrypted transport");
3286 case SMB_FS_QUOTA_INFORMATION:
3288 files_struct *fsp = NULL;
3289 SMB_NTQUOTA_STRUCT quotas;
3291 ZERO_STRUCT(quotas);
3294 if ((conn->server_info->utok.uid != 0)
3295 ||!CAN_WRITE(conn)) {
3296 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3297 lp_servicename(SNUM(conn)),
3298 conn->server_info->unix_name));
3299 reply_doserror(req, ERRSRV, ERRaccess);
3303 /* note: normaly there're 48 bytes,
3304 * but we didn't use the last 6 bytes for now
3307 fsp = file_fsp(req, SVAL(params,0));
3309 if (!check_fsp_ntquota_handle(conn, req,
3311 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3313 req, NT_STATUS_INVALID_HANDLE);
3317 if (total_data < 42) {
3318 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3322 NT_STATUS_INVALID_PARAMETER);
3326 /* unknown_1 24 NULL bytes in pdata*/
3328 /* the soft quotas 8 bytes (uint64_t)*/
3329 quotas.softlim = (uint64_t)IVAL(pdata,24);
3330 #ifdef LARGE_SMB_OFF_T
3331 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3332 #else /* LARGE_SMB_OFF_T */
3333 if ((IVAL(pdata,28) != 0)&&
3334 ((quotas.softlim != 0xFFFFFFFF)||
3335 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3336 /* more than 32 bits? */
3339 NT_STATUS_INVALID_PARAMETER);
3342 #endif /* LARGE_SMB_OFF_T */
3344 /* the hard quotas 8 bytes (uint64_t)*/
3345 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3346 #ifdef LARGE_SMB_OFF_T
3347 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3348 #else /* LARGE_SMB_OFF_T */
3349 if ((IVAL(pdata,36) != 0)&&
3350 ((quotas.hardlim != 0xFFFFFFFF)||
3351 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3352 /* more than 32 bits? */
3355 NT_STATUS_INVALID_PARAMETER);
3358 #endif /* LARGE_SMB_OFF_T */
3360 /* quota_flags 2 bytes **/
3361 quotas.qflags = SVAL(pdata,40);
3363 /* unknown_2 6 NULL bytes follow*/
3365 /* now set the quotas */
3366 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3367 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3368 reply_doserror(req, ERRSRV, ERRerror);
3375 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3377 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3383 * sending this reply works fine,
3384 * but I'm not sure it's the same
3385 * like windows do...
3388 reply_outbuf(req, 10, 0);
3391 #if defined(HAVE_POSIX_ACLS)
3392 /****************************************************************************
3393 Utility function to count the number of entries in a POSIX acl.
3394 ****************************************************************************/
3396 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3398 unsigned int ace_count = 0;
3399 int entry_id = SMB_ACL_FIRST_ENTRY;
3400 SMB_ACL_ENTRY_T entry;
3402 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3404 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3405 entry_id = SMB_ACL_NEXT_ENTRY;
3412 /****************************************************************************
3413 Utility function to marshall a POSIX acl into wire format.
3414 ****************************************************************************/
3416 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3418 int entry_id = SMB_ACL_FIRST_ENTRY;
3419 SMB_ACL_ENTRY_T entry;
3421 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3422 SMB_ACL_TAG_T tagtype;
3423 SMB_ACL_PERMSET_T permset;
3424 unsigned char perms = 0;
3425 unsigned int own_grp;
3428 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3429 entry_id = SMB_ACL_NEXT_ENTRY;
3432 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3433 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3437 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3438 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3442 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3443 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3444 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3446 SCVAL(pdata,1,perms);
3449 case SMB_ACL_USER_OBJ:
3450 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3451 own_grp = (unsigned int)pst->st_uid;
3452 SIVAL(pdata,2,own_grp);
3457 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3459 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3462 own_grp = (unsigned int)*puid;
3463 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3464 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3465 SIVAL(pdata,2,own_grp);
3469 case SMB_ACL_GROUP_OBJ:
3470 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3471 own_grp = (unsigned int)pst->st_gid;
3472 SIVAL(pdata,2,own_grp);
3477 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3479 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3482 own_grp = (unsigned int)*pgid;
3483 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3484 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3485 SIVAL(pdata,2,own_grp);
3490 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3491 SIVAL(pdata,2,0xFFFFFFFF);
3492 SIVAL(pdata,6,0xFFFFFFFF);
3495 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3496 SIVAL(pdata,2,0xFFFFFFFF);
3497 SIVAL(pdata,6,0xFFFFFFFF);
3500 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3503 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3510 /****************************************************************************
3511 Store the FILE_UNIX_BASIC info.
3512 ****************************************************************************/
3514 static char *store_file_unix_basic(connection_struct *conn,
3517 const SMB_STRUCT_STAT *psbuf)
3519 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3520 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3522 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3525 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3528 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3529 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3530 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3533 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3537 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3541 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3544 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3548 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3552 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3555 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3559 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3566 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3567 * the chflags(2) (or equivalent) flags.
3569 * XXX: this really should be behind the VFS interface. To do this, we would
3570 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3571 * Each VFS module could then implement its own mapping as appropriate for the
3572 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3574 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3578 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3582 { UF_IMMUTABLE, EXT_IMMUTABLE },
3586 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3590 { UF_HIDDEN, EXT_HIDDEN },
3593 /* Do not remove. We need to guarantee that this array has at least one
3594 * entry to build on HP-UX.
3600 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3601 uint32 *smb_fflags, uint32 *smb_fmask)
3603 #ifdef HAVE_STAT_ST_FLAGS
3606 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3607 *smb_fmask |= info2_flags_map[i].smb_fflag;
3608 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3609 *smb_fflags |= info2_flags_map[i].smb_fflag;
3612 #endif /* HAVE_STAT_ST_FLAGS */
3615 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3616 const uint32 smb_fflags,
3617 const uint32 smb_fmask,
3620 #ifdef HAVE_STAT_ST_FLAGS
3621 uint32 max_fmask = 0;
3624 *stat_fflags = psbuf->st_flags;
3626 /* For each flags requested in smb_fmask, check the state of the
3627 * corresponding flag in smb_fflags and set or clear the matching
3631 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3632 max_fmask |= info2_flags_map[i].smb_fflag;
3633 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3634 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3635 *stat_fflags |= info2_flags_map[i].stat_fflag;
3637 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3642 /* If smb_fmask is asking to set any bits that are not supported by
3643 * our flag mappings, we should fail.
3645 if ((smb_fmask & max_fmask) != smb_fmask) {
3652 #endif /* HAVE_STAT_ST_FLAGS */
3656 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3657 * of file flags and birth (create) time.
3659 static char *store_file_unix_basic_info2(connection_struct *conn,
3662 const SMB_STRUCT_STAT *psbuf)
3664 uint32 file_flags = 0;
3665 uint32 flags_mask = 0;
3667 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3669 /* Create (birth) time 64 bit */
3670 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3673 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3674 SIVAL(pdata, 0, file_flags); /* flags */
3675 SIVAL(pdata, 4, flags_mask); /* mask */
3681 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3682 const struct stream_struct *streams,
3684 unsigned int max_data_bytes,
3685 unsigned int *data_size)
3688 unsigned int ofs = 0;
3690 for (i=0; i<num_streams; i++) {
3691 unsigned int next_offset;
3693 smb_ucs2_t *namebuf;
3695 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3696 streams[i].name, &namelen) ||
3699 return NT_STATUS_INVALID_PARAMETER;
3703 * name_buf is now null-terminated, we need to marshall as not
3709 if (ofs + 24 + namelen > max_data_bytes) {
3710 TALLOC_FREE(namebuf);
3711 return NT_STATUS_BUFFER_TOO_SMALL;
3714 SIVAL(data, ofs+4, namelen);
3715 SOFF_T(data, ofs+8, streams[i].size);
3716 SOFF_T(data, ofs+16, streams[i].alloc_size);
3717 memcpy(data+ofs+24, namebuf, namelen);
3718 TALLOC_FREE(namebuf);
3720 next_offset = ofs + 24 + namelen;
3722 if (i == num_streams-1) {
3723 SIVAL(data, ofs, 0);
3726 unsigned int align = ndr_align_size(next_offset, 8);
3728 if (next_offset + align > max_data_bytes) {
3729 return NT_STATUS_BUFFER_TOO_SMALL;
3732 memset(data+next_offset, 0, align);
3733 next_offset += align;
3735 SIVAL(data, ofs, next_offset - ofs);
3744 return NT_STATUS_OK;
3747 /****************************************************************************
3748 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3749 ****************************************************************************/
3751 static void call_trans2qpipeinfo(connection_struct *conn,
3752 struct smb_request *req,
3753 unsigned int tran_call,
3754 char **pparams, int total_params,
3755 char **ppdata, int total_data,
3756 unsigned int max_data_bytes)
3758 char *params = *pparams;
3759 char *pdata = *ppdata;
3760 unsigned int data_size = 0;
3761 unsigned int param_size = 2;
3766 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3770 if (total_params < 4) {
3771 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3775 fsp = file_fsp(req, SVAL(params,0));
3776 if (!fsp_is_np(fsp)) {
3777 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3781 info_level = SVAL(params,2);
3783 *pparams = (char *)SMB_REALLOC(*pparams,2);
3784 if (*pparams == NULL) {
3785 reply_nterror(req, NT_STATUS_NO_MEMORY);
3790 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3791 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3792 if (*ppdata == NULL ) {
3793 reply_nterror(req, NT_STATUS_NO_MEMORY);
3798 switch (info_level) {
3799 case SMB_FILE_STANDARD_INFORMATION:
3801 SOFF_T(pdata,0,4096LL);
3808 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3812 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3818 /****************************************************************************
3819 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3820 file name or file id).
3821 ****************************************************************************/
3823 static void call_trans2qfilepathinfo(connection_struct *conn,
3824 struct smb_request *req,
3825 unsigned int tran_call,
3826 char **pparams, int total_params,
3827 char **ppdata, int total_data,
3828 unsigned int max_data_bytes)
3830 char *params = *pparams;
3831 char *pdata = *ppdata;
3832 char *dstart, *dend;
3836 SMB_OFF_T file_size=0;
3837 uint64_t allocation_size=0;
3838 unsigned int data_size = 0;
3839 unsigned int param_size = 2;
3840 SMB_STRUCT_STAT sbuf;
3841 char *dos_fname = NULL;
3847 bool delete_pending = False;
3849 time_t create_time, mtime, atime;
3850 struct timespec create_time_ts, mtime_ts, atime_ts;
3851 struct timespec write_time_ts;
3852 files_struct *fsp = NULL;
3853 struct file_id fileid;
3854 struct ea_list *ea_list = NULL;
3855 char *lock_data = NULL;
3856 bool ms_dfs_link = false;
3857 TALLOC_CTX *ctx = talloc_tos();
3860 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3865 ZERO_STRUCT(write_time_ts);
3867 if (tran_call == TRANSACT2_QFILEINFO) {
3868 if (total_params < 4) {
3869 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3874 call_trans2qpipeinfo(conn, req, tran_call,
3875 pparams, total_params,
3881 fsp = file_fsp(req, SVAL(params,0));
3882 info_level = SVAL(params,2);
3884 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3886 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3887 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3891 /* Initial check for valid fsp ptr. */
3892 if (!check_fsp_open(conn, req, fsp)) {
3896 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3898 reply_nterror(req, NT_STATUS_NO_MEMORY);
3902 if(fsp->fake_file_handle) {
3904 * This is actually for the QUOTA_FAKE_FILE --metze
3907 /* We know this name is ok, it's already passed the checks. */
3909 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3911 * This is actually a QFILEINFO on a directory
3912 * handle (returned from an NT SMB). NT5.0 seems
3913 * to do this call. JRA.
3916 if (INFO_LEVEL_IS_UNIX(info_level)) {
3917 /* Always do lstat for UNIX calls. */
3918 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3919 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3920 reply_unixerror(req,ERRDOS,ERRbadpath);
3923 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3924 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3925 reply_unixerror(req, ERRDOS, ERRbadpath);
3929 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3930 get_file_infos(fileid, &delete_pending, &write_time_ts);
3933 * Original code - this is an open file.
3935 if (!check_fsp(conn, req, fsp)) {
3939 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3940 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3941 reply_unixerror(req, ERRDOS, ERRbadfid);
3944 pos = fsp->fh->position_information;
3945 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3946 get_file_infos(fileid, &delete_pending, &write_time_ts);
3950 NTSTATUS status = NT_STATUS_OK;
3953 if (total_params < 7) {
3954 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3958 info_level = SVAL(params,0);
3960 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3962 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3963 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3967 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3969 STR_TERMINATE, &status);
3970 if (!NT_STATUS_IS_OK(status)) {
3971 reply_nterror(req, status);
3975 status = resolve_dfspath(ctx,
3977 req->flags2 & FLAGS2_DFS_PATHNAMES,
3980 if (!NT_STATUS_IS_OK(status)) {
3981 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3982 reply_botherror(req,
3983 NT_STATUS_PATH_NOT_COVERED,
3984 ERRSRV, ERRbadpath);
3986 reply_nterror(req, status);
3990 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3991 if (!NT_STATUS_IS_OK(status)) {
3992 reply_nterror(req, status);
3995 status = check_name(conn, fname);
3996 if (!NT_STATUS_IS_OK(status)) {
3997 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3998 reply_nterror(req, status);
4002 if (INFO_LEVEL_IS_UNIX(info_level)) {
4003 /* Always do lstat for UNIX calls. */
4004 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4005 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4006 reply_unixerror(req, ERRDOS, ERRbadpath);
4010 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4011 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4014 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4015 reply_unixerror(req, ERRDOS, ERRbadpath);
4020 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4021 get_file_infos(fileid, &delete_pending, &write_time_ts);
4022 if (delete_pending) {
4023 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4028 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4029 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4033 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4034 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4036 p = strrchr_m(fname,'/');
4043 mode = dos_mode_msdfs(conn,fname,&sbuf);
4045 mode = dos_mode(conn,fname,&sbuf);
4048 mode = FILE_ATTRIBUTE_NORMAL;
4050 nlink = sbuf.st_nlink;
4052 if (nlink && (mode&aDIR)) {
4056 if ((nlink > 0) && delete_pending) {
4060 fullpathname = fname;
4062 file_size = get_file_size(sbuf);
4064 /* Pull out any data sent here before we realloc. */
4065 switch (info_level) {
4066 case SMB_INFO_QUERY_EAS_FROM_LIST:
4068 /* Pull any EA list from the data portion. */
4071 if (total_data < 4) {
4073 req, NT_STATUS_INVALID_PARAMETER);
4076 ea_size = IVAL(pdata,0);
4078 if (total_data > 0 && ea_size != total_data) {
4079 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4080 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4082 req, NT_STATUS_INVALID_PARAMETER);
4086 if (!lp_ea_support(SNUM(conn))) {
4087 reply_doserror(req, ERRDOS,
4088 ERReasnotsupported);
4092 /* Pull out the list of names. */
4093 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4096 req, NT_STATUS_INVALID_PARAMETER);
4102 case SMB_QUERY_POSIX_LOCK:
4104 if (fsp == NULL || fsp->fh->fd == -1) {
4105 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4109 if (total_data != POSIX_LOCK_DATA_SIZE) {
4111 req, NT_STATUS_INVALID_PARAMETER);
4115 /* Copy the lock range data. */
4116 lock_data = (char *)TALLOC_MEMDUP(
4117 ctx, pdata, total_data);
4119 reply_nterror(req, NT_STATUS_NO_MEMORY);
4127 *pparams = (char *)SMB_REALLOC(*pparams,2);
4128 if (*pparams == NULL) {
4129 reply_nterror(req, NT_STATUS_NO_MEMORY);
4134 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4135 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4136 if (*ppdata == NULL ) {
4137 reply_nterror(req, NT_STATUS_NO_MEMORY);
4142 dend = dstart + data_size - 1;
4144 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4145 mtime_ts = get_mtimespec(&sbuf);
4146 atime_ts = get_atimespec(&sbuf);
4148 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4151 /* Do we have this path open ? */
4153 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4154 fsp1 = file_find_di_first(fileid);
4155 if (fsp1 && fsp1->initial_allocation_size) {
4156 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4160 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4161 mtime_ts = write_time_ts;
4164 if (lp_dos_filetime_resolution(SNUM(conn))) {
4165 dos_filetime_timespec(&create_time_ts);
4166 dos_filetime_timespec(&mtime_ts);
4167 dos_filetime_timespec(&atime_ts);
4170 create_time = convert_timespec_to_time_t(create_time_ts);
4171 mtime = convert_timespec_to_time_t(mtime_ts);
4172 atime = convert_timespec_to_time_t(atime_ts);
4174 /* NT expects the name to be in an exact form of the *full*
4175 filename. See the trans2 torture test */
4176 if (ISDOT(base_name)) {
4177 dos_fname = talloc_strdup(ctx, "\\");
4179 reply_nterror(req, NT_STATUS_NO_MEMORY);
4183 dos_fname = talloc_asprintf(ctx,
4187 reply_nterror(req, NT_STATUS_NO_MEMORY);
4190 string_replace(dos_fname, '/', '\\');
4193 switch (info_level) {
4194 case SMB_INFO_STANDARD:
4195 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4197 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4198 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4199 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4200 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4201 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4202 SSVAL(pdata,l1_attrFile,mode);
4205 case SMB_INFO_QUERY_EA_SIZE:
4207 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4208 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4210 srv_put_dos_date2(pdata,0,create_time);
4211 srv_put_dos_date2(pdata,4,atime);
4212 srv_put_dos_date2(pdata,8,mtime); /* write time */
4213 SIVAL(pdata,12,(uint32)file_size);
4214 SIVAL(pdata,16,(uint32)allocation_size);
4215 SSVAL(pdata,20,mode);
4216 SIVAL(pdata,22,ea_size);
4220 case SMB_INFO_IS_NAME_VALID:
4221 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4222 if (tran_call == TRANSACT2_QFILEINFO) {
4223 /* os/2 needs this ? really ?*/
4224 reply_doserror(req, ERRDOS, ERRbadfunc);
4231 case SMB_INFO_QUERY_EAS_FROM_LIST:
4233 size_t total_ea_len = 0;
4234 struct ea_list *ea_file_list = NULL;
4236 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4238 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4239 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4241 if (!ea_list || (total_ea_len > data_size)) {
4243 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4247 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4251 case SMB_INFO_QUERY_ALL_EAS:
4253 /* We have data_size bytes to put EA's into. */
4254 size_t total_ea_len = 0;
4256 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4258 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4259 if (!ea_list || (total_ea_len > data_size)) {
4261 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4265 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4269 case SMB_FILE_BASIC_INFORMATION:
4270 case SMB_QUERY_FILE_BASIC_INFO:
4272 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4273 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4274 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4276 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4280 put_long_date_timespec(pdata,create_time_ts);
4281 put_long_date_timespec(pdata+8,atime_ts);
4282 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4283 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4284 SIVAL(pdata,32,mode);
4286 DEBUG(5,("SMB_QFBI - "));
4287 DEBUG(5,("create: %s ", ctime(&create_time)));
4288 DEBUG(5,("access: %s ", ctime(&atime)));
4289 DEBUG(5,("write: %s ", ctime(&mtime)));
4290 DEBUG(5,("change: %s ", ctime(&mtime)));
4291 DEBUG(5,("mode: %x\n", mode));
4294 case SMB_FILE_STANDARD_INFORMATION:
4295 case SMB_QUERY_FILE_STANDARD_INFO:
4297 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4299 SOFF_T(pdata,0,allocation_size);
4300 SOFF_T(pdata,8,file_size);
4301 SIVAL(pdata,16,nlink);
4302 SCVAL(pdata,20,delete_pending?1:0);
4303 SCVAL(pdata,21,(mode&aDIR)?1:0);
4304 SSVAL(pdata,22,0); /* Padding. */
4307 case SMB_FILE_EA_INFORMATION:
4308 case SMB_QUERY_FILE_EA_INFO:
4310 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4311 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4313 SIVAL(pdata,0,ea_size);
4317 /* Get the 8.3 name - used if NT SMB was negotiated. */
4318 case SMB_QUERY_FILE_ALT_NAME_INFO:
4319 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4321 char mangled_name[13];
4322 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4323 if (!name_to_8_3(base_name,mangled_name,
4324 True,conn->params)) {
4327 NT_STATUS_NO_MEMORY);
4329 len = srvstr_push(dstart, req->flags2,
4330 pdata+4, mangled_name,
4331 PTR_DIFF(dend, pdata+4),
4333 data_size = 4 + len;
4338 case SMB_QUERY_FILE_NAME_INFO:
4340 this must be *exactly* right for ACLs on mapped drives to work
4342 len = srvstr_push(dstart, req->flags2,
4344 PTR_DIFF(dend, pdata+4),
4346 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4347 data_size = 4 + len;
4351 case SMB_FILE_ALLOCATION_INFORMATION:
4352 case SMB_QUERY_FILE_ALLOCATION_INFO:
4353 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4355 SOFF_T(pdata,0,allocation_size);
4358 case SMB_FILE_END_OF_FILE_INFORMATION:
4359 case SMB_QUERY_FILE_END_OF_FILEINFO:
4360 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4362 SOFF_T(pdata,0,file_size);
4365 case SMB_QUERY_FILE_ALL_INFO:
4366 case SMB_FILE_ALL_INFORMATION:
4368 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4369 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4370 put_long_date_timespec(pdata,create_time_ts);
4371 put_long_date_timespec(pdata+8,atime_ts);
4372 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4373 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4374 SIVAL(pdata,32,mode);
4375 SIVAL(pdata,36,0); /* padding. */
4377 SOFF_T(pdata,0,allocation_size);
4378 SOFF_T(pdata,8,file_size);
4379 SIVAL(pdata,16,nlink);
4380 SCVAL(pdata,20,delete_pending);
4381 SCVAL(pdata,21,(mode&aDIR)?1:0);
4384 SIVAL(pdata,0,ea_size);
4385 pdata += 4; /* EA info */
4386 len = srvstr_push(dstart, req->flags2,
4388 PTR_DIFF(dend, pdata+4),
4392 data_size = PTR_DIFF(pdata,(*ppdata));
4395 case SMB_FILE_INTERNAL_INFORMATION:
4396 /* This should be an index number - looks like
4399 I think this causes us to fail the IFSKIT
4400 BasicFileInformationTest. -tpot */
4402 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4403 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4404 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4408 case SMB_FILE_ACCESS_INFORMATION:
4409 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4411 SIVAL(pdata,0,fsp->access_mask);
4413 /* GENERIC_EXECUTE mapping from Windows */
4414 SIVAL(pdata,0,0x12019F);
4419 case SMB_FILE_NAME_INFORMATION:
4420 /* Pathname with leading '\'. */
4423 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4424 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4425 SIVAL(pdata,0,byte_len);
4426 data_size = 4 + byte_len;
4430 case SMB_FILE_DISPOSITION_INFORMATION:
4431 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4433 SCVAL(pdata,0,delete_pending);
4436 case SMB_FILE_POSITION_INFORMATION:
4437 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4439 SOFF_T(pdata,0,pos);
4442 case SMB_FILE_MODE_INFORMATION:
4443 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4444 SIVAL(pdata,0,mode);
4448 case SMB_FILE_ALIGNMENT_INFORMATION:
4449 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4450 SIVAL(pdata,0,0); /* No alignment needed. */
4455 * NT4 server just returns "invalid query" to this - if we try
4456 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4459 /* The first statement above is false - verified using Thursby
4460 * client against NT4 -- gcolley.
4462 case SMB_QUERY_FILE_STREAM_INFO:
4463 case SMB_FILE_STREAM_INFORMATION: {
4464 unsigned int num_streams;
4465 struct stream_struct *streams;
4468 DEBUG(10,("call_trans2qfilepathinfo: "
4469 "SMB_FILE_STREAM_INFORMATION\n"));
4471 status = SMB_VFS_STREAMINFO(
4472 conn, fsp, fname, talloc_tos(),
4473 &num_streams, &streams);
4475 if (!NT_STATUS_IS_OK(status)) {
4476 DEBUG(10, ("could not get stream info: %s\n",
4477 nt_errstr(status)));
4478 reply_nterror(req, status);
4482 status = marshall_stream_info(num_streams, streams,
4483 pdata, max_data_bytes,
4486 if (!NT_STATUS_IS_OK(status)) {
4487 DEBUG(10, ("marshall_stream_info failed: %s\n",
4488 nt_errstr(status)));
4489 reply_nterror(req, status);
4493 TALLOC_FREE(streams);
4497 case SMB_QUERY_COMPRESSION_INFO:
4498 case SMB_FILE_COMPRESSION_INFORMATION:
4499 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4500 SOFF_T(pdata,0,file_size);
4501 SIVAL(pdata,8,0); /* ??? */
4502 SIVAL(pdata,12,0); /* ??? */
4506 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4507 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4508 put_long_date_timespec(pdata,create_time_ts);
4509 put_long_date_timespec(pdata+8,atime_ts);
4510 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4511 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4512 SOFF_T(pdata,32,allocation_size);
4513 SOFF_T(pdata,40,file_size);
4514 SIVAL(pdata,48,mode);
4515 SIVAL(pdata,52,0); /* ??? */
4519 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4520 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4521 SIVAL(pdata,0,mode);
4527 * CIFS UNIX Extensions.
4530 case SMB_QUERY_FILE_UNIX_BASIC:
4532 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4533 data_size = PTR_DIFF(pdata,(*ppdata));
4537 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4539 for (i=0; i<100; i++)
4540 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4546 case SMB_QUERY_FILE_UNIX_INFO2:
4548 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4549 data_size = PTR_DIFF(pdata,(*ppdata));
4553 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4555 for (i=0; i<100; i++)
4556 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4562 case SMB_QUERY_FILE_UNIX_LINK:
4564 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4567 reply_nterror(req, NT_STATUS_NO_MEMORY);
4571 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4573 if(!S_ISLNK(sbuf.st_mode)) {
4574 reply_unixerror(req, ERRSRV,
4579 reply_unixerror(req, ERRDOS, ERRbadlink);
4582 len = SMB_VFS_READLINK(conn,fullpathname,
4585 reply_unixerror(req, ERRDOS,
4590 len = srvstr_push(dstart, req->flags2,
4592 PTR_DIFF(dend, pdata),
4595 data_size = PTR_DIFF(pdata,(*ppdata));
4600 #if defined(HAVE_POSIX_ACLS)
4601 case SMB_QUERY_POSIX_ACL:
4603 SMB_ACL_T file_acl = NULL;
4604 SMB_ACL_T def_acl = NULL;
4605 uint16 num_file_acls = 0;
4606 uint16 num_def_acls = 0;
4608 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4609 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4611 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4614 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4615 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4619 NT_STATUS_NOT_IMPLEMENTED);
4623 if (S_ISDIR(sbuf.st_mode)) {
4624 if (fsp && fsp->is_directory) {
4625 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4627 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4629 def_acl = free_empty_sys_acl(conn, def_acl);
4632 num_file_acls = count_acl_entries(conn, file_acl);
4633 num_def_acls = count_acl_entries(conn, def_acl);
4635 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4636 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4638 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4639 SMB_POSIX_ACL_HEADER_SIZE) ));
4641 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4644 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4648 NT_STATUS_BUFFER_TOO_SMALL);
4652 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4653 SSVAL(pdata,2,num_file_acls);
4654 SSVAL(pdata,4,num_def_acls);
4655 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4657 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4660 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4663 req, NT_STATUS_INTERNAL_ERROR);
4666 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4668 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4671 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4675 NT_STATUS_INTERNAL_ERROR);
4680 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4683 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4685 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4691 case SMB_QUERY_POSIX_LOCK:
4693 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4697 enum brl_type lock_type;
4699 if (total_data != POSIX_LOCK_DATA_SIZE) {
4701 req, NT_STATUS_INVALID_PARAMETER);
4705 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4706 case POSIX_LOCK_TYPE_READ:
4707 lock_type = READ_LOCK;
4709 case POSIX_LOCK_TYPE_WRITE:
4710 lock_type = WRITE_LOCK;
4712 case POSIX_LOCK_TYPE_UNLOCK:
4714 /* There's no point in asking for an unlock... */
4717 NT_STATUS_INVALID_PARAMETER);
4721 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4722 #if defined(HAVE_LONGLONG)
4723 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4724 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4725 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4726 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4727 #else /* HAVE_LONGLONG */
4728 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4729 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4730 #endif /* HAVE_LONGLONG */
4732 status = query_lock(fsp,
4739 if (ERROR_WAS_LOCK_DENIED(status)) {
4740 /* Here we need to report who has it locked... */
4741 data_size = POSIX_LOCK_DATA_SIZE;
4743 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4744 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4745 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4746 #if defined(HAVE_LONGLONG)
4747 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4748 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4749 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4750 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4751 #else /* HAVE_LONGLONG */
4752 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4753 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4754 #endif /* HAVE_LONGLONG */
4756 } else if (NT_STATUS_IS_OK(status)) {
4757 /* For success we just return a copy of what we sent
4758 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4759 data_size = POSIX_LOCK_DATA_SIZE;
4760 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4761 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4763 reply_nterror(req, status);
4770 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4774 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4780 /****************************************************************************
4781 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4783 ****************************************************************************/
4785 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4786 connection_struct *conn,
4787 const char *oldname_in,
4788 const char *newname_in)
4790 SMB_STRUCT_STAT sbuf1, sbuf2;
4791 char *last_component_oldname = NULL;
4792 char *last_component_newname = NULL;
4793 char *oldname = NULL;
4794 char *newname = NULL;
4795 NTSTATUS status = NT_STATUS_OK;
4800 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4801 &last_component_oldname, &sbuf1);
4802 if (!NT_STATUS_IS_OK(status)) {
4806 status = check_name(conn, oldname);
4807 if (!NT_STATUS_IS_OK(status)) {
4811 /* source must already exist. */
4812 if (!VALID_STAT(sbuf1)) {
4813 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4816 status = unix_convert(ctx, conn, newname_in, False, &newname,
4817 &last_component_newname, &sbuf2);
4818 if (!NT_STATUS_IS_OK(status)) {
4822 status = check_name(conn, newname);
4823 if (!NT_STATUS_IS_OK(status)) {
4827 /* Disallow if newname already exists. */
4828 if (VALID_STAT(sbuf2)) {
4829 return NT_STATUS_OBJECT_NAME_COLLISION;
4832 /* No links from a directory. */
4833 if (S_ISDIR(sbuf1.st_mode)) {
4834 return NT_STATUS_FILE_IS_A_DIRECTORY;
4837 /* Ensure this is within the share. */
4838 status = check_reduced_name(conn, oldname);
4839 if (!NT_STATUS_IS_OK(status)) {
4843 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4845 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4846 status = map_nt_error_from_unix(errno);
4847 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4848 nt_errstr(status), newname, oldname));
4854 /****************************************************************************
4855 Deal with setting the time from any of the setfilepathinfo functions.
4856 ****************************************************************************/
4858 NTSTATUS smb_set_file_time(connection_struct *conn,
4861 const SMB_STRUCT_STAT *psbuf,
4862 struct timespec ts[2],
4863 bool setting_write_time)
4866 FILE_NOTIFY_CHANGE_LAST_ACCESS
4867 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4869 if (!VALID_STAT(*psbuf)) {
4870 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4873 /* get some defaults (no modifications) if any info is zero or -1. */
4874 if (null_timespec(ts[0])) {
4875 ts[0] = get_atimespec(psbuf);
4876 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4879 if (null_timespec(ts[1])) {
4880 ts[1] = get_mtimespec(psbuf);
4881 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4884 if (!setting_write_time) {
4885 /* ts[1] comes from change time, not write time. */
4886 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4889 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4890 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4893 * Try and set the times of this file if
4894 * they are different from the current values.
4898 struct timespec mts = get_mtimespec(psbuf);
4899 struct timespec ats = get_atimespec(psbuf);
4900 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4901 return NT_STATUS_OK;
4905 if (setting_write_time) {
4907 * This was a setfileinfo on an open file.
4908 * NT does this a lot. We also need to
4909 * set the time here, as it can be read by
4910 * FindFirst/FindNext and with the patch for bug #2045
4911 * in smbd/fileio.c it ensures that this timestamp is
4912 * kept sticky even after a write. We save the request
4913 * away and will set it on file close and after a write. JRA.
4916 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4917 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4920 set_sticky_write_time_fsp(fsp, ts[1]);
4922 set_sticky_write_time_path(conn, fname,
4923 vfs_file_id_from_sbuf(conn, psbuf),
4928 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4930 if(file_ntimes(conn, fname, ts)!=0) {
4931 return map_nt_error_from_unix(errno);
4933 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4935 return NT_STATUS_OK;
4938 /****************************************************************************
4939 Deal with setting the dosmode from any of the setfilepathinfo functions.
4940 ****************************************************************************/
4942 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4944 SMB_STRUCT_STAT *psbuf,
4947 if (!VALID_STAT(*psbuf)) {
4948 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4952 if (S_ISDIR(psbuf->st_mode)) {
4959 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
4961 /* check the mode isn't different, before changing it */
4962 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
4964 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
4965 fname, (unsigned int)dosmode ));
4967 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
4968 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
4969 fname, strerror(errno)));
4970 return map_nt_error_from_unix(errno);
4973 return NT_STATUS_OK;
4976 /****************************************************************************
4977 Deal with setting the size from any of the setfilepathinfo functions.
4978 ****************************************************************************/
4980 static NTSTATUS smb_set_file_size(connection_struct *conn,
4981 struct smb_request *req,
4984 SMB_STRUCT_STAT *psbuf,
4987 NTSTATUS status = NT_STATUS_OK;
4988 files_struct *new_fsp = NULL;
4990 if (!VALID_STAT(*psbuf)) {
4991 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4994 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
4996 if (size == get_file_size(*psbuf)) {
4997 return NT_STATUS_OK;
5000 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5001 fname, (double)size ));
5003 if (fsp && fsp->fh->fd != -1) {
5004 /* Handle based call. */
5005 if (vfs_set_filelen(fsp, size) == -1) {
5006 return map_nt_error_from_unix(errno);
5008 trigger_write_time_update_immediate(fsp);
5009 return NT_STATUS_OK;
5012 status = open_file_ntcreate(conn, req, fname, psbuf,
5013 FILE_WRITE_ATTRIBUTES,
5014 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5017 FILE_ATTRIBUTE_NORMAL,
5018 FORCE_OPLOCK_BREAK_TO_NONE,
5021 if (!NT_STATUS_IS_OK(status)) {
5022 /* NB. We check for open_was_deferred in the caller. */
5026 if (vfs_set_filelen(new_fsp, size) == -1) {
5027 status = map_nt_error_from_unix(errno);
5028 close_file(req, new_fsp,NORMAL_CLOSE);
5032 trigger_write_time_update_immediate(new_fsp);
5033 close_file(req, new_fsp,NORMAL_CLOSE);
5034 return NT_STATUS_OK;
5037 /****************************************************************************
5038 Deal with SMB_INFO_SET_EA.
5039 ****************************************************************************/
5041 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5047 struct ea_list *ea_list = NULL;
5048 TALLOC_CTX *ctx = NULL;
5049 NTSTATUS status = NT_STATUS_OK;
5051 if (total_data < 10) {
5053 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5054 length. They seem to have no effect. Bug #3212. JRA */
5056 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5057 /* We're done. We only get EA info in this call. */
5058 return NT_STATUS_OK;
5061 return NT_STATUS_INVALID_PARAMETER;
5064 if (IVAL(pdata,0) > total_data) {
5065 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5066 IVAL(pdata,0), (unsigned int)total_data));
5067 return NT_STATUS_INVALID_PARAMETER;
5071 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5073 return NT_STATUS_INVALID_PARAMETER;
5075 status = set_ea(conn, fsp, fname, ea_list);
5080 /****************************************************************************
5081 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5082 ****************************************************************************/
5084 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5089 SMB_STRUCT_STAT *psbuf)
5091 NTSTATUS status = NT_STATUS_OK;
5092 bool delete_on_close;
5095 if (total_data < 1) {
5096 return NT_STATUS_INVALID_PARAMETER;
5100 return NT_STATUS_INVALID_HANDLE;
5103 delete_on_close = (CVAL(pdata,0) ? True : False);
5104 dosmode = dos_mode(conn, fname, psbuf);
5106 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5107 "delete_on_close = %u\n",
5109 (unsigned int)dosmode,
5110 (unsigned int)delete_on_close ));
5112 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5114 if (!NT_STATUS_IS_OK(status)) {
5118 /* The set is across all open files on this dev/inode pair. */
5119 if (!set_delete_on_close(fsp, delete_on_close,
5120 &conn->server_info->utok)) {
5121 return NT_STATUS_ACCESS_DENIED;
5123 return NT_STATUS_OK;
5126 /****************************************************************************
5127 Deal with SMB_FILE_POSITION_INFORMATION.
5128 ****************************************************************************/
5130 static NTSTATUS smb_file_position_information(connection_struct *conn,
5135 uint64_t position_information;
5137 if (total_data < 8) {
5138 return NT_STATUS_INVALID_PARAMETER;
5142 /* Ignore on pathname based set. */
5143 return NT_STATUS_OK;
5146 position_information = (uint64_t)IVAL(pdata,0);
5147 #ifdef LARGE_SMB_OFF_T
5148 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5149 #else /* LARGE_SMB_OFF_T */
5150 if (IVAL(pdata,4) != 0) {
5151 /* more than 32 bits? */
5152 return NT_STATUS_INVALID_PARAMETER;
5154 #endif /* LARGE_SMB_OFF_T */
5156 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5157 fsp->fsp_name, (double)position_information ));
5158 fsp->fh->position_information = position_information;
5159 return NT_STATUS_OK;
5162 /****************************************************************************
5163 Deal with SMB_FILE_MODE_INFORMATION.
5164 ****************************************************************************/
5166 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5172 if (total_data < 4) {
5173 return NT_STATUS_INVALID_PARAMETER;
5175 mode = IVAL(pdata,0);
5176 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5177 return NT_STATUS_INVALID_PARAMETER;
5179 return NT_STATUS_OK;
5182 /****************************************************************************
5183 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5184 ****************************************************************************/
5186 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5187 struct smb_request *req,
5192 char *link_target = NULL;
5193 const char *newname = fname;
5194 NTSTATUS status = NT_STATUS_OK;
5195 TALLOC_CTX *ctx = talloc_tos();
5197 /* Set a symbolic link. */
5198 /* Don't allow this if follow links is false. */
5200 if (total_data == 0) {
5201 return NT_STATUS_INVALID_PARAMETER;
5204 if (!lp_symlinks(SNUM(conn))) {
5205 return NT_STATUS_ACCESS_DENIED;
5208 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5209 total_data, STR_TERMINATE);
5212 return NT_STATUS_INVALID_PARAMETER;
5215 /* !widelinks forces the target path to be within the share. */
5216 /* This means we can interpret the target as a pathname. */
5217 if (!lp_widelinks(SNUM(conn))) {
5218 char *rel_name = NULL;
5219 char *last_dirp = NULL;
5221 if (*link_target == '/') {
5222 /* No absolute paths allowed. */
5223 return NT_STATUS_ACCESS_DENIED;
5225 rel_name = talloc_strdup(ctx,newname);
5227 return NT_STATUS_NO_MEMORY;
5229 last_dirp = strrchr_m(rel_name, '/');
5231 last_dirp[1] = '\0';
5233 rel_name = talloc_strdup(ctx,"./");
5235 return NT_STATUS_NO_MEMORY;
5238 rel_name = talloc_asprintf_append(rel_name,
5242 return NT_STATUS_NO_MEMORY;
5245 status = check_name(conn, rel_name);
5246 if (!NT_STATUS_IS_OK(status)) {
5251 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5252 newname, link_target ));
5254 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5255 return map_nt_error_from_unix(errno);
5258 return NT_STATUS_OK;
5261 /****************************************************************************
5262 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5263 ****************************************************************************/
5265 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5266 struct smb_request *req,
5267 const char *pdata, int total_data,
5270 char *oldname = NULL;
5271 TALLOC_CTX *ctx = talloc_tos();
5272 NTSTATUS status = NT_STATUS_OK;
5274 /* Set a hard link. */
5275 if (total_data == 0) {
5276 return NT_STATUS_INVALID_PARAMETER;
5279 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5280 total_data, STR_TERMINATE, &status);
5281 if (!NT_STATUS_IS_OK(status)) {
5285 status = resolve_dfspath(ctx, conn,
5286 req->flags2 & FLAGS2_DFS_PATHNAMES,
5289 if (!NT_STATUS_IS_OK(status)) {
5293 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5296 return hardlink_internals(ctx, conn, oldname, fname);
5299 /****************************************************************************
5300 Deal with SMB_FILE_RENAME_INFORMATION.
5301 ****************************************************************************/
5303 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5304 struct smb_request *req,
5313 char *newname = NULL;
5314 char *base_name = NULL;
5315 bool dest_has_wcard = False;
5316 NTSTATUS status = NT_STATUS_OK;
5318 TALLOC_CTX *ctx = talloc_tos();
5320 if (total_data < 13) {
5321 return NT_STATUS_INVALID_PARAMETER;
5324 overwrite = (CVAL(pdata,0) ? True : False);
5325 root_fid = IVAL(pdata,4);
5326 len = IVAL(pdata,8);
5328 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5329 return NT_STATUS_INVALID_PARAMETER;
5332 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5335 if (!NT_STATUS_IS_OK(status)) {
5339 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5342 status = resolve_dfspath_wcard(ctx, conn,
5343 req->flags2 & FLAGS2_DFS_PATHNAMES,
5347 if (!NT_STATUS_IS_OK(status)) {
5351 /* Check the new name has no '/' characters. */
5352 if (strchr_m(newname, '/')) {
5353 return NT_STATUS_NOT_SUPPORTED;
5356 if (fsp && fsp->base_fsp) {
5357 if (newname[0] != ':') {
5358 return NT_STATUS_NOT_SUPPORTED;
5360 base_name = talloc_asprintf(ctx, "%s%s",
5361 fsp->base_fsp->fsp_name,
5364 return NT_STATUS_NO_MEMORY;
5367 if (is_ntfs_stream_name(newname)) {
5368 return NT_STATUS_NOT_SUPPORTED;
5371 /* Create the base directory. */
5372 base_name = talloc_strdup(ctx, fname);
5374 return NT_STATUS_NO_MEMORY;
5376 p = strrchr_m(base_name, '/');
5380 base_name = talloc_strdup(ctx, "./");
5382 return NT_STATUS_NO_MEMORY;
5385 /* Append the new name. */
5386 base_name = talloc_asprintf_append(base_name,
5390 return NT_STATUS_NO_MEMORY;
5395 SMB_STRUCT_STAT sbuf;
5396 char *newname_last_component = NULL;
5400 status = unix_convert(ctx, conn, newname, False,
5402 &newname_last_component,
5405 /* If an error we expect this to be
5406 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5408 if (!NT_STATUS_IS_OK(status)
5409 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5414 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5415 fsp->fnum, fsp->fsp_name, base_name ));
5416 status = rename_internals_fsp(conn, fsp, base_name,
5417 newname_last_component, 0,
5420 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5421 fname, base_name ));
5422 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5423 overwrite, False, dest_has_wcard,
5424 FILE_WRITE_ATTRIBUTES);
5430 /****************************************************************************
5431 Deal with SMB_SET_POSIX_ACL.
5432 ****************************************************************************/
5434 #if defined(HAVE_POSIX_ACLS)
5435 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5440 SMB_STRUCT_STAT *psbuf)
5442 uint16 posix_acl_version;
5443 uint16 num_file_acls;
5444 uint16 num_def_acls;
5445 bool valid_file_acls = True;
5446 bool valid_def_acls = True;
5448 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5449 return NT_STATUS_INVALID_PARAMETER;
5451 posix_acl_version = SVAL(pdata,0);
5452 num_file_acls = SVAL(pdata,2);
5453 num_def_acls = SVAL(pdata,4);
5455 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5456 valid_file_acls = False;
5460 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5461 valid_def_acls = False;
5465 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5466 return NT_STATUS_INVALID_PARAMETER;
5469 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5470 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5471 return NT_STATUS_INVALID_PARAMETER;
5474 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5475 fname ? fname : fsp->fsp_name,
5476 (unsigned int)num_file_acls,
5477 (unsigned int)num_def_acls));
5479 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5480 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5481 return map_nt_error_from_unix(errno);
5484 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5485 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5486 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5487 return map_nt_error_from_unix(errno);
5489 return NT_STATUS_OK;
5493 /****************************************************************************
5494 Deal with SMB_SET_POSIX_LOCK.
5495 ****************************************************************************/
5497 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5498 struct smb_request *req,
5506 bool blocking_lock = False;
5507 enum brl_type lock_type;
5509 NTSTATUS status = NT_STATUS_OK;
5511 if (fsp == NULL || fsp->fh->fd == -1) {
5512 return NT_STATUS_INVALID_HANDLE;
5515 if (total_data != POSIX_LOCK_DATA_SIZE) {
5516 return NT_STATUS_INVALID_PARAMETER;
5519 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5520 case POSIX_LOCK_TYPE_READ:
5521 lock_type = READ_LOCK;
5523 case POSIX_LOCK_TYPE_WRITE:
5524 /* Return the right POSIX-mappable error code for files opened read-only. */
5525 if (!fsp->can_write) {
5526 return NT_STATUS_INVALID_HANDLE;
5528 lock_type = WRITE_LOCK;
5530 case POSIX_LOCK_TYPE_UNLOCK:
5531 lock_type = UNLOCK_LOCK;
5534 return NT_STATUS_INVALID_PARAMETER;
5537 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5538 blocking_lock = False;
5539 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5540 blocking_lock = True;
5542 return NT_STATUS_INVALID_PARAMETER;
5545 if (!lp_blocking_locks(SNUM(conn))) {
5546 blocking_lock = False;
5549 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5550 #if defined(HAVE_LONGLONG)
5551 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5552 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5553 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5554 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5555 #else /* HAVE_LONGLONG */
5556 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5557 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5558 #endif /* HAVE_LONGLONG */
5560 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5561 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5563 (unsigned int)lock_type,
5564 (unsigned int)lock_pid,
5568 if (lock_type == UNLOCK_LOCK) {
5569 status = do_unlock(smbd_messaging_context(),
5576 uint32 block_smbpid;
5578 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5589 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5591 * A blocking lock was requested. Package up
5592 * this smb into a queued request and push it
5593 * onto the blocking lock queue.
5595 if(push_blocking_lock_request(br_lck,
5598 -1, /* infinite timeout. */
5606 TALLOC_FREE(br_lck);
5610 TALLOC_FREE(br_lck);
5616 /****************************************************************************
5617 Deal with SMB_INFO_STANDARD.
5618 ****************************************************************************/
5620 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5625 const SMB_STRUCT_STAT *psbuf)
5627 struct timespec ts[2];
5629 if (total_data < 12) {
5630 return NT_STATUS_INVALID_PARAMETER;
5634 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5636 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5638 DEBUG(10,("smb_set_info_standard: file %s\n",
5639 fname ? fname : fsp->fsp_name ));
5641 return smb_set_file_time(conn,
5649 /****************************************************************************
5650 Deal with SMB_SET_FILE_BASIC_INFO.
5651 ****************************************************************************/
5653 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5658 SMB_STRUCT_STAT *psbuf)
5660 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5661 struct timespec write_time;
5662 struct timespec changed_time;
5664 struct timespec ts[2];
5665 NTSTATUS status = NT_STATUS_OK;
5666 bool setting_write_time = true;
5668 if (total_data < 36) {
5669 return NT_STATUS_INVALID_PARAMETER;
5672 /* Set the attributes */
5673 dosmode = IVAL(pdata,32);
5674 status = smb_set_file_dosmode(conn,
5678 if (!NT_STATUS_IS_OK(status)) {
5682 /* Ignore create time at offset pdata. */
5685 ts[0] = interpret_long_date(pdata+8);
5687 write_time = interpret_long_date(pdata+16);
5688 changed_time = interpret_long_date(pdata+24);
5691 ts[1] = timespec_min(&write_time, &changed_time);
5693 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5697 /* Prefer a defined time to an undefined one. */
5698 if (null_timespec(ts[1])) {
5699 if (null_timespec(write_time)) {
5700 ts[1] = changed_time;
5701 setting_write_time = false;
5707 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5708 fname ? fname : fsp->fsp_name ));
5710 return smb_set_file_time(conn,
5715 setting_write_time);
5718 /****************************************************************************
5719 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5720 ****************************************************************************/
5722 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5723 struct smb_request *req,
5728 SMB_STRUCT_STAT *psbuf)
5730 uint64_t allocation_size = 0;
5731 NTSTATUS status = NT_STATUS_OK;
5732 files_struct *new_fsp = NULL;
5734 if (!VALID_STAT(*psbuf)) {
5735 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5738 if (total_data < 8) {
5739 return NT_STATUS_INVALID_PARAMETER;
5742 allocation_size = (uint64_t)IVAL(pdata,0);
5743 #ifdef LARGE_SMB_OFF_T
5744 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5745 #else /* LARGE_SMB_OFF_T */
5746 if (IVAL(pdata,4) != 0) {
5747 /* more than 32 bits? */
5748 return NT_STATUS_INVALID_PARAMETER;
5750 #endif /* LARGE_SMB_OFF_T */
5752 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5753 fname, (double)allocation_size ));
5755 if (allocation_size) {
5756 allocation_size = smb_roundup(conn, allocation_size);
5759 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5760 fname, (double)allocation_size ));
5762 if (fsp && fsp->fh->fd != -1) {
5763 /* Open file handle. */
5764 /* Only change if needed. */
5765 if (allocation_size != get_file_size(*psbuf)) {
5766 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5767 return map_nt_error_from_unix(errno);
5770 /* But always update the time. */
5772 * This is equivalent to a write. Ensure it's seen immediately
5773 * if there are no pending writes.
5775 trigger_write_time_update_immediate(fsp);
5776 return NT_STATUS_OK;
5779 /* Pathname or stat or directory file. */
5781 status = open_file_ntcreate(conn, req, fname, psbuf,
5783 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5786 FILE_ATTRIBUTE_NORMAL,
5787 FORCE_OPLOCK_BREAK_TO_NONE,
5790 if (!NT_STATUS_IS_OK(status)) {
5791 /* NB. We check for open_was_deferred in the caller. */
5795 /* Only change if needed. */
5796 if (allocation_size != get_file_size(*psbuf)) {
5797 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5798 status = map_nt_error_from_unix(errno);
5799 close_file(req, new_fsp, NORMAL_CLOSE);
5804 /* Changing the allocation size should set the last mod time. */
5806 * This is equivalent to a write. Ensure it's seen immediately
5807 * if there are no pending writes.
5809 trigger_write_time_update_immediate(new_fsp);
5811 close_file(req, new_fsp, NORMAL_CLOSE);
5812 return NT_STATUS_OK;
5815 /****************************************************************************
5816 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5817 ****************************************************************************/
5819 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5820 struct smb_request *req,
5825 SMB_STRUCT_STAT *psbuf)
5829 if (total_data < 8) {
5830 return NT_STATUS_INVALID_PARAMETER;
5833 size = IVAL(pdata,0);
5834 #ifdef LARGE_SMB_OFF_T
5835 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5836 #else /* LARGE_SMB_OFF_T */
5837 if (IVAL(pdata,4) != 0) {
5838 /* more than 32 bits? */
5839 return NT_STATUS_INVALID_PARAMETER;
5841 #endif /* LARGE_SMB_OFF_T */
5842 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5843 "file %s to %.0f\n", fname, (double)size ));
5845 return smb_set_file_size(conn, req,
5852 /****************************************************************************
5853 Allow a UNIX info mknod.
5854 ****************************************************************************/
5856 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5860 SMB_STRUCT_STAT *psbuf)
5862 uint32 file_type = IVAL(pdata,56);
5863 #if defined(HAVE_MAKEDEV)
5864 uint32 dev_major = IVAL(pdata,60);
5865 uint32 dev_minor = IVAL(pdata,68);
5867 SMB_DEV_T dev = (SMB_DEV_T)0;
5868 uint32 raw_unixmode = IVAL(pdata,84);
5872 if (total_data < 100) {
5873 return NT_STATUS_INVALID_PARAMETER;
5876 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5877 if (!NT_STATUS_IS_OK(status)) {
5881 #if defined(HAVE_MAKEDEV)
5882 dev = makedev(dev_major, dev_minor);
5885 switch (file_type) {
5886 #if defined(S_IFIFO)
5887 case UNIX_TYPE_FIFO:
5888 unixmode |= S_IFIFO;
5891 #if defined(S_IFSOCK)
5892 case UNIX_TYPE_SOCKET:
5893 unixmode |= S_IFSOCK;
5896 #if defined(S_IFCHR)
5897 case UNIX_TYPE_CHARDEV:
5898 unixmode |= S_IFCHR;
5901 #if defined(S_IFBLK)
5902 case UNIX_TYPE_BLKDEV:
5903 unixmode |= S_IFBLK;
5907 return NT_STATUS_INVALID_PARAMETER;
5910 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5911 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5913 /* Ok - do the mknod. */
5914 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5915 return map_nt_error_from_unix(errno);
5918 /* If any of the other "set" calls fail we
5919 * don't want to end up with a half-constructed mknod.
5922 if (lp_inherit_perms(SNUM(conn))) {
5923 inherit_access_posix_acl(
5924 conn, parent_dirname(fname),
5928 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5929 status = map_nt_error_from_unix(errno);
5930 SMB_VFS_UNLINK(conn,fname);
5933 return NT_STATUS_OK;
5936 /****************************************************************************
5937 Deal with SMB_SET_FILE_UNIX_BASIC.
5938 ****************************************************************************/
5940 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5941 struct smb_request *req,
5946 SMB_STRUCT_STAT *psbuf)
5948 struct timespec ts[2];
5949 uint32 raw_unixmode;
5952 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5953 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5954 NTSTATUS status = NT_STATUS_OK;
5955 bool delete_on_fail = False;
5956 enum perm_type ptype;
5958 if (total_data < 100) {
5959 return NT_STATUS_INVALID_PARAMETER;
5962 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5963 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5964 size=IVAL(pdata,0); /* first 8 Bytes are size */
5965 #ifdef LARGE_SMB_OFF_T
5966 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5967 #else /* LARGE_SMB_OFF_T */
5968 if (IVAL(pdata,4) != 0) {
5969 /* more than 32 bits? */
5970 return NT_STATUS_INVALID_PARAMETER;
5972 #endif /* LARGE_SMB_OFF_T */
5975 ts[0] = interpret_long_date(pdata+24); /* access_time */
5976 ts[1] = interpret_long_date(pdata+32); /* modification_time */
5977 set_owner = (uid_t)IVAL(pdata,40);
5978 set_grp = (gid_t)IVAL(pdata,48);
5979 raw_unixmode = IVAL(pdata,84);
5981 if (VALID_STAT(*psbuf)) {
5982 if (S_ISDIR(psbuf->st_mode)) {
5983 ptype = PERM_EXISTING_DIR;
5985 ptype = PERM_EXISTING_FILE;
5988 ptype = PERM_NEW_FILE;
5991 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
5992 if (!NT_STATUS_IS_OK(status)) {
5996 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
5997 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5998 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6000 if (!VALID_STAT(*psbuf)) {
6002 * The only valid use of this is to create character and block
6003 * devices, and named pipes. This is deprecated (IMHO) and
6004 * a new info level should be used for mknod. JRA.
6007 status = smb_unix_mknod(conn,
6012 if (!NT_STATUS_IS_OK(status)) {
6016 /* Ensure we don't try and change anything else. */
6017 raw_unixmode = SMB_MODE_NO_CHANGE;
6018 size = get_file_size(*psbuf);
6019 ts[0] = get_atimespec(psbuf);
6020 ts[1] = get_mtimespec(psbuf);
6022 * We continue here as we might want to change the
6025 delete_on_fail = True;
6029 /* Horrible backwards compatibility hack as an old server bug
6030 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6034 size = get_file_size(*psbuf);
6039 * Deal with the UNIX specific mode set.
6042 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6043 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6044 (unsigned int)unixmode, fname ));
6045 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6046 return map_nt_error_from_unix(errno);
6051 * Deal with the UNIX specific uid set.
6054 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6057 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6058 (unsigned int)set_owner, fname ));
6060 if (S_ISLNK(psbuf->st_mode)) {
6061 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6063 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6067 status = map_nt_error_from_unix(errno);
6068 if (delete_on_fail) {
6069 SMB_VFS_UNLINK(conn,fname);
6076 * Deal with the UNIX specific gid set.
6079 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6080 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6081 (unsigned int)set_owner, fname ));
6082 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6083 status = map_nt_error_from_unix(errno);
6084 if (delete_on_fail) {
6085 SMB_VFS_UNLINK(conn,fname);
6091 /* Deal with any size changes. */
6093 status = smb_set_file_size(conn, req,
6098 if (!NT_STATUS_IS_OK(status)) {
6102 /* Deal with any time changes. */
6104 return smb_set_file_time(conn,
6112 /****************************************************************************
6113 Deal with SMB_SET_FILE_UNIX_INFO2.
6114 ****************************************************************************/
6116 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6117 struct smb_request *req,
6122 SMB_STRUCT_STAT *psbuf)
6128 if (total_data < 116) {
6129 return NT_STATUS_INVALID_PARAMETER;
6132 /* Start by setting all the fields that are common between UNIX_BASIC
6135 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6137 if (!NT_STATUS_IS_OK(status)) {
6141 smb_fflags = IVAL(pdata, 108);
6142 smb_fmask = IVAL(pdata, 112);
6144 /* NB: We should only attempt to alter the file flags if the client
6145 * sends a non-zero mask.
6147 if (smb_fmask != 0) {
6148 int stat_fflags = 0;
6150 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6152 /* Client asked to alter a flag we don't understand. */
6153 return NT_STATUS_INVALID_PARAMETER;
6156 if (fsp && fsp->fh->fd != -1) {
6157 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6158 return NT_STATUS_NOT_SUPPORTED;
6160 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6161 return map_nt_error_from_unix(errno);
6166 /* XXX: need to add support for changing the create_time here. You
6167 * can do this for paths on Darwin with setattrlist(2). The right way
6168 * to hook this up is probably by extending the VFS utimes interface.
6171 return NT_STATUS_OK;
6174 /****************************************************************************
6175 Create a directory with POSIX semantics.
6176 ****************************************************************************/
6178 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6179 struct smb_request *req,
6183 SMB_STRUCT_STAT *psbuf,
6184 int *pdata_return_size)
6186 NTSTATUS status = NT_STATUS_OK;
6187 uint32 raw_unixmode = 0;
6188 uint32 mod_unixmode = 0;
6189 mode_t unixmode = (mode_t)0;
6190 files_struct *fsp = NULL;
6191 uint16 info_level_return = 0;
6193 char *pdata = *ppdata;
6195 if (total_data < 18) {
6196 return NT_STATUS_INVALID_PARAMETER;
6199 raw_unixmode = IVAL(pdata,8);
6200 /* Next 4 bytes are not yet defined. */
6202 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6203 if (!NT_STATUS_IS_OK(status)) {
6207 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6209 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6210 fname, (unsigned int)unixmode ));
6212 status = open_directory(conn, req,
6215 FILE_READ_ATTRIBUTES, /* Just a stat open */
6216 FILE_SHARE_NONE, /* Ignored for stat opens */
6223 if (NT_STATUS_IS_OK(status)) {
6224 close_file(req, fsp, NORMAL_CLOSE);
6227 info_level_return = SVAL(pdata,16);
6229 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6230 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6231 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6232 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6234 *pdata_return_size = 12;
6237 /* Realloc the data size */
6238 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6239 if (*ppdata == NULL) {
6240 *pdata_return_size = 0;
6241 return NT_STATUS_NO_MEMORY;
6245 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6246 SSVAL(pdata,2,0); /* No fnum. */
6247 SIVAL(pdata,4,info); /* Was directory created. */
6249 switch (info_level_return) {
6250 case SMB_QUERY_FILE_UNIX_BASIC:
6251 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6252 SSVAL(pdata,10,0); /* Padding. */
6253 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6255 case SMB_QUERY_FILE_UNIX_INFO2:
6256 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6257 SSVAL(pdata,10,0); /* Padding. */
6258 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6261 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6262 SSVAL(pdata,10,0); /* Padding. */
6269 /****************************************************************************
6270 Open/Create a file with POSIX semantics.
6271 ****************************************************************************/
6273 static NTSTATUS smb_posix_open(connection_struct *conn,
6274 struct smb_request *req,
6278 SMB_STRUCT_STAT *psbuf,
6279 int *pdata_return_size)
6281 bool extended_oplock_granted = False;
6282 char *pdata = *ppdata;
6284 uint32 wire_open_mode = 0;
6285 uint32 raw_unixmode = 0;
6286 uint32 mod_unixmode = 0;
6287 uint32 create_disp = 0;
6288 uint32 access_mask = 0;
6289 uint32 create_options = 0;
6290 NTSTATUS status = NT_STATUS_OK;
6291 mode_t unixmode = (mode_t)0;
6292 files_struct *fsp = NULL;
6293 int oplock_request = 0;
6295 uint16 info_level_return = 0;
6297 if (total_data < 18) {
6298 return NT_STATUS_INVALID_PARAMETER;
6301 flags = IVAL(pdata,0);
6302 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6303 if (oplock_request) {
6304 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6307 wire_open_mode = IVAL(pdata,4);
6309 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6310 return smb_posix_mkdir(conn, req,
6318 switch (wire_open_mode & SMB_ACCMODE) {
6320 access_mask = FILE_READ_DATA;
6323 access_mask = FILE_WRITE_DATA;
6326 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6329 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6330 (unsigned int)wire_open_mode ));
6331 return NT_STATUS_INVALID_PARAMETER;
6334 wire_open_mode &= ~SMB_ACCMODE;
6336 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6337 create_disp = FILE_CREATE;
6338 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6339 create_disp = FILE_OVERWRITE_IF;
6340 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6341 create_disp = FILE_OPEN_IF;
6343 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6344 (unsigned int)wire_open_mode ));
6345 return NT_STATUS_INVALID_PARAMETER;
6348 raw_unixmode = IVAL(pdata,8);
6349 /* Next 4 bytes are not yet defined. */
6351 status = unix_perms_from_wire(conn,
6354 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6357 if (!NT_STATUS_IS_OK(status)) {
6361 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6363 if (wire_open_mode & SMB_O_SYNC) {
6364 create_options |= FILE_WRITE_THROUGH;
6366 if (wire_open_mode & SMB_O_APPEND) {
6367 access_mask |= FILE_APPEND_DATA;
6369 if (wire_open_mode & SMB_O_DIRECT) {
6370 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6373 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6375 (unsigned int)wire_open_mode,
6376 (unsigned int)unixmode ));
6378 status = open_file_ntcreate(conn, req,
6382 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6384 0, /* no create options yet. */
6390 if (!NT_STATUS_IS_OK(status)) {
6394 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6395 extended_oplock_granted = True;
6398 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6399 extended_oplock_granted = True;
6402 info_level_return = SVAL(pdata,16);
6404 /* Allocate the correct return size. */
6406 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6407 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6408 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6409 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6411 *pdata_return_size = 12;
6414 /* Realloc the data size */
6415 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6416 if (*ppdata == NULL) {
6417 close_file(req, fsp, ERROR_CLOSE);
6418 *pdata_return_size = 0;
6419 return NT_STATUS_NO_MEMORY;
6423 if (extended_oplock_granted) {
6424 if (flags & REQUEST_BATCH_OPLOCK) {
6425 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6427 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6429 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6430 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6432 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6435 SSVAL(pdata,2,fsp->fnum);
6436 SIVAL(pdata,4,info); /* Was file created etc. */
6438 switch (info_level_return) {
6439 case SMB_QUERY_FILE_UNIX_BASIC:
6440 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6441 SSVAL(pdata,10,0); /* padding. */
6442 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6444 case SMB_QUERY_FILE_UNIX_INFO2:
6445 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6446 SSVAL(pdata,10,0); /* padding. */
6447 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6450 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6451 SSVAL(pdata,10,0); /* padding. */
6454 return NT_STATUS_OK;
6457 /****************************************************************************
6458 Delete a file with POSIX semantics.
6459 ****************************************************************************/
6461 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6462 struct smb_request *req,
6466 SMB_STRUCT_STAT *psbuf)
6468 NTSTATUS status = NT_STATUS_OK;
6469 files_struct *fsp = NULL;
6474 struct share_mode_lock *lck = NULL;
6476 if (total_data < 2) {
6477 return NT_STATUS_INVALID_PARAMETER;
6480 flags = SVAL(pdata,0);
6482 if (!VALID_STAT(*psbuf)) {
6483 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6486 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6487 !VALID_STAT_OF_DIR(*psbuf)) {
6488 return NT_STATUS_NOT_A_DIRECTORY;
6491 DEBUG(10,("smb_posix_unlink: %s %s\n",
6492 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6495 if (VALID_STAT_OF_DIR(*psbuf)) {
6496 status = open_directory(conn, req,
6500 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6503 FILE_FLAG_POSIX_SEMANTICS|0777,
6508 status = open_file_ntcreate(conn, req,
6512 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6515 FILE_FLAG_POSIX_SEMANTICS|0777,
6516 0, /* No oplock, but break existing ones. */
6521 if (!NT_STATUS_IS_OK(status)) {
6526 * Don't lie to client. If we can't really delete due to
6527 * non-POSIX opens return SHARING_VIOLATION.
6530 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6533 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6534 "lock for file %s\n", fsp->fsp_name));
6535 close_file(req, fsp, NORMAL_CLOSE);
6536 return NT_STATUS_INVALID_PARAMETER;
6540 * See if others still have the file open. If this is the case, then
6541 * don't delete. If all opens are POSIX delete we can set the delete
6542 * on close disposition.
6544 for (i=0; i<lck->num_share_modes; i++) {
6545 struct share_mode_entry *e = &lck->share_modes[i];
6546 if (is_valid_share_mode_entry(e)) {
6547 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6550 /* Fail with sharing violation. */
6551 close_file(req, fsp, NORMAL_CLOSE);
6553 return NT_STATUS_SHARING_VIOLATION;
6558 * Set the delete on close.
6560 status = smb_set_file_disposition_info(conn,
6567 if (!NT_STATUS_IS_OK(status)) {
6568 close_file(req, fsp, NORMAL_CLOSE);
6573 return close_file(req, fsp, NORMAL_CLOSE);
6576 /****************************************************************************
6577 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6578 ****************************************************************************/
6580 static void call_trans2setfilepathinfo(connection_struct *conn,
6581 struct smb_request *req,
6582 unsigned int tran_call,
6583 char **pparams, int total_params,
6584 char **ppdata, int total_data,
6585 unsigned int max_data_bytes)
6587 char *params = *pparams;
6588 char *pdata = *ppdata;
6590 SMB_STRUCT_STAT sbuf;
6592 files_struct *fsp = NULL;
6593 NTSTATUS status = NT_STATUS_OK;
6594 int data_return_size = 0;
6595 TALLOC_CTX *ctx = talloc_tos();
6598 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6604 if (tran_call == TRANSACT2_SETFILEINFO) {
6605 if (total_params < 4) {
6606 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6610 fsp = file_fsp(req, SVAL(params,0));
6611 /* Basic check for non-null fsp. */
6612 if (!check_fsp_open(conn, req, fsp)) {
6615 info_level = SVAL(params,2);
6617 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6619 reply_nterror(req, NT_STATUS_NO_MEMORY);
6623 if(fsp->is_directory || fsp->fh->fd == -1) {
6625 * This is actually a SETFILEINFO on a directory
6626 * handle (returned from an NT SMB). NT5.0 seems
6627 * to do this call. JRA.
6629 if (INFO_LEVEL_IS_UNIX(info_level)) {
6630 /* Always do lstat for UNIX calls. */
6631 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6632 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6633 reply_unixerror(req,ERRDOS,ERRbadpath);
6637 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6638 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6639 reply_unixerror(req,ERRDOS,ERRbadpath);
6643 } else if (fsp->print_file) {
6645 * Doing a DELETE_ON_CLOSE should cancel a print job.
6647 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6648 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6650 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6653 send_trans2_replies(conn, req, params, 2,
6658 reply_unixerror(req, ERRDOS, ERRbadpath);
6663 * Original code - this is an open file.
6665 if (!check_fsp(conn, req, fsp)) {
6669 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6670 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6671 reply_unixerror(req, ERRDOS, ERRbadfid);
6677 if (total_params < 7) {
6678 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6682 info_level = SVAL(params,0);
6683 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6684 total_params - 6, STR_TERMINATE,
6686 if (!NT_STATUS_IS_OK(status)) {
6687 reply_nterror(req, status);
6691 status = resolve_dfspath(ctx, conn,
6692 req->flags2 & FLAGS2_DFS_PATHNAMES,
6695 if (!NT_STATUS_IS_OK(status)) {
6696 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6697 reply_botherror(req,
6698 NT_STATUS_PATH_NOT_COVERED,
6699 ERRSRV, ERRbadpath);
6702 reply_nterror(req, status);
6706 status = unix_convert(ctx, conn, fname, False,
6707 &fname, NULL, &sbuf);
6708 if (!NT_STATUS_IS_OK(status)) {
6709 reply_nterror(req, status);
6713 status = check_name(conn, fname);
6714 if (!NT_STATUS_IS_OK(status)) {
6715 reply_nterror(req, status);
6719 if (INFO_LEVEL_IS_UNIX(info_level)) {
6721 * For CIFS UNIX extensions the target name may not exist.
6724 /* Always do lstat for UNIX calls. */
6725 SMB_VFS_LSTAT(conn,fname,&sbuf);
6727 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6728 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6729 reply_unixerror(req, ERRDOS, ERRbadpath);
6734 if (!CAN_WRITE(conn)) {
6735 reply_doserror(req, ERRSRV, ERRaccess);
6739 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6740 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6744 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6745 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6747 /* Realloc the parameter size */
6748 *pparams = (char *)SMB_REALLOC(*pparams,2);
6749 if (*pparams == NULL) {
6750 reply_nterror(req, NT_STATUS_NO_MEMORY);
6757 switch (info_level) {
6759 case SMB_INFO_STANDARD:
6761 status = smb_set_info_standard(conn,
6770 case SMB_INFO_SET_EA:
6772 status = smb_info_set_ea(conn,
6780 case SMB_SET_FILE_BASIC_INFO:
6781 case SMB_FILE_BASIC_INFORMATION:
6783 status = smb_set_file_basic_info(conn,
6792 case SMB_FILE_ALLOCATION_INFORMATION:
6793 case SMB_SET_FILE_ALLOCATION_INFO:
6795 status = smb_set_file_allocation_info(conn, req,
6804 case SMB_FILE_END_OF_FILE_INFORMATION:
6805 case SMB_SET_FILE_END_OF_FILE_INFO:
6807 status = smb_set_file_end_of_file_info(conn, req,
6816 case SMB_FILE_DISPOSITION_INFORMATION:
6817 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6820 /* JRA - We used to just ignore this on a path ?
6821 * Shouldn't this be invalid level on a pathname
6824 if (tran_call != TRANSACT2_SETFILEINFO) {
6825 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6828 status = smb_set_file_disposition_info(conn,
6837 case SMB_FILE_POSITION_INFORMATION:
6839 status = smb_file_position_information(conn,
6846 /* From tridge Samba4 :
6847 * MODE_INFORMATION in setfileinfo (I have no
6848 * idea what "mode information" on a file is - it takes a value of 0,
6849 * 2, 4 or 6. What could it be?).
6852 case SMB_FILE_MODE_INFORMATION:
6854 status = smb_file_mode_information(conn,
6861 * CIFS UNIX extensions.
6864 case SMB_SET_FILE_UNIX_BASIC:
6866 status = smb_set_file_unix_basic(conn, req,
6875 case SMB_SET_FILE_UNIX_INFO2:
6877 status = smb_set_file_unix_info2(conn, req,
6886 case SMB_SET_FILE_UNIX_LINK:
6888 if (tran_call != TRANSACT2_SETPATHINFO) {
6889 /* We must have a pathname for this. */
6890 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6893 status = smb_set_file_unix_link(conn, req, pdata,
6898 case SMB_SET_FILE_UNIX_HLINK:
6900 if (tran_call != TRANSACT2_SETPATHINFO) {
6901 /* We must have a pathname for this. */
6902 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6905 status = smb_set_file_unix_hlink(conn, req,
6911 case SMB_FILE_RENAME_INFORMATION:
6913 status = smb_file_rename_information(conn, req,
6919 #if defined(HAVE_POSIX_ACLS)
6920 case SMB_SET_POSIX_ACL:
6922 status = smb_set_posix_acl(conn,
6932 case SMB_SET_POSIX_LOCK:
6934 if (tran_call != TRANSACT2_SETFILEINFO) {
6935 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6938 status = smb_set_posix_lock(conn, req,
6939 pdata, total_data, fsp);
6943 case SMB_POSIX_PATH_OPEN:
6945 if (tran_call != TRANSACT2_SETPATHINFO) {
6946 /* We must have a pathname for this. */
6947 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6951 status = smb_posix_open(conn, req,
6960 case SMB_POSIX_PATH_UNLINK:
6962 if (tran_call != TRANSACT2_SETPATHINFO) {
6963 /* We must have a pathname for this. */
6964 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6968 status = smb_posix_unlink(conn, req,
6977 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6982 if (!NT_STATUS_IS_OK(status)) {
6983 if (open_was_deferred(req->mid)) {
6984 /* We have re-scheduled this call. */
6987 if (blocking_lock_was_deferred(req->mid)) {
6988 /* We have re-scheduled this call. */
6991 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6992 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
6993 ERRSRV, ERRbadpath);
6996 if (info_level == SMB_POSIX_PATH_OPEN) {
6997 reply_openerror(req, status);
7001 reply_nterror(req, status);
7006 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7012 /****************************************************************************
7013 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7014 ****************************************************************************/
7016 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7017 char **pparams, int total_params,
7018 char **ppdata, int total_data,
7019 unsigned int max_data_bytes)
7021 char *params = *pparams;
7022 char *pdata = *ppdata;
7023 char *directory = NULL;
7024 SMB_STRUCT_STAT sbuf;
7025 NTSTATUS status = NT_STATUS_OK;
7026 struct ea_list *ea_list = NULL;
7027 TALLOC_CTX *ctx = talloc_tos();
7029 if (!CAN_WRITE(conn)) {
7030 reply_doserror(req, ERRSRV, ERRaccess);
7034 if (total_params < 5) {
7035 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7039 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7040 total_params - 4, STR_TERMINATE,
7042 if (!NT_STATUS_IS_OK(status)) {
7043 reply_nterror(req, status);
7047 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7049 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7050 if (!NT_STATUS_IS_OK(status)) {
7051 reply_nterror(req, status);
7055 status = check_name(conn, directory);
7056 if (!NT_STATUS_IS_OK(status)) {
7057 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7058 reply_nterror(req, status);
7062 /* Any data in this call is an EA list. */
7063 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7064 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7069 * OS/2 workplace shell seems to send SET_EA requests of "null"
7070 * length (4 bytes containing IVAL 4).
7071 * They seem to have no effect. Bug #3212. JRA.
7074 if (total_data != 4) {
7075 if (total_data < 10) {
7076 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7080 if (IVAL(pdata,0) > total_data) {
7081 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7082 IVAL(pdata,0), (unsigned int)total_data));
7083 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7087 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7094 /* If total_data == 4 Windows doesn't care what values
7095 * are placed in that field, it just ignores them.
7096 * The System i QNTC IBM SMB client puts bad values here,
7097 * so ignore them. */
7099 status = create_directory(conn, req, directory);
7101 if (!NT_STATUS_IS_OK(status)) {
7102 reply_nterror(req, status);
7106 /* Try and set any given EA. */
7108 status = set_ea(conn, NULL, directory, ea_list);
7109 if (!NT_STATUS_IS_OK(status)) {
7110 reply_nterror(req, status);
7115 /* Realloc the parameter and data sizes */
7116 *pparams = (char *)SMB_REALLOC(*pparams,2);
7117 if(*pparams == NULL) {
7118 reply_nterror(req, NT_STATUS_NO_MEMORY);
7125 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7130 /****************************************************************************
7131 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7132 We don't actually do this - we just send a null response.
7133 ****************************************************************************/
7135 static void call_trans2findnotifyfirst(connection_struct *conn,
7136 struct smb_request *req,
7137 char **pparams, int total_params,
7138 char **ppdata, int total_data,
7139 unsigned int max_data_bytes)
7141 static uint16 fnf_handle = 257;
7142 char *params = *pparams;
7145 if (total_params < 6) {
7146 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7150 info_level = SVAL(params,4);
7151 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7153 switch (info_level) {
7158 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7162 /* Realloc the parameter and data sizes */
7163 *pparams = (char *)SMB_REALLOC(*pparams,6);
7164 if (*pparams == NULL) {
7165 reply_nterror(req, NT_STATUS_NO_MEMORY);
7170 SSVAL(params,0,fnf_handle);
7171 SSVAL(params,2,0); /* No changes */
7172 SSVAL(params,4,0); /* No EA errors */
7179 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7184 /****************************************************************************
7185 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7186 changes). Currently this does nothing.
7187 ****************************************************************************/
7189 static void call_trans2findnotifynext(connection_struct *conn,
7190 struct smb_request *req,
7191 char **pparams, int total_params,
7192 char **ppdata, int total_data,
7193 unsigned int max_data_bytes)
7195 char *params = *pparams;
7197 DEBUG(3,("call_trans2findnotifynext\n"));
7199 /* Realloc the parameter and data sizes */
7200 *pparams = (char *)SMB_REALLOC(*pparams,4);
7201 if (*pparams == NULL) {
7202 reply_nterror(req, NT_STATUS_NO_MEMORY);
7207 SSVAL(params,0,0); /* No changes */
7208 SSVAL(params,2,0); /* No EA errors */
7210 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7215 /****************************************************************************
7216 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7217 ****************************************************************************/
7219 static void call_trans2getdfsreferral(connection_struct *conn,
7220 struct smb_request *req,
7221 char **pparams, int total_params,
7222 char **ppdata, int total_data,
7223 unsigned int max_data_bytes)
7225 char *params = *pparams;
7226 char *pathname = NULL;
7228 int max_referral_level;
7229 NTSTATUS status = NT_STATUS_OK;
7230 TALLOC_CTX *ctx = talloc_tos();
7232 DEBUG(10,("call_trans2getdfsreferral\n"));
7234 if (total_params < 3) {
7235 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7239 max_referral_level = SVAL(params,0);
7241 if(!lp_host_msdfs()) {
7242 reply_doserror(req, ERRDOS, ERRbadfunc);
7246 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7247 total_params - 2, STR_TERMINATE);
7249 reply_nterror(req, NT_STATUS_NOT_FOUND);
7252 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7253 ppdata,&status)) < 0) {
7254 reply_nterror(req, status);
7258 SSVAL(req->inbuf, smb_flg2,
7259 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7260 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7265 #define LMCAT_SPL 0x53
7266 #define LMFUNC_GETJOBID 0x60
7268 /****************************************************************************
7269 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7270 ****************************************************************************/
7272 static void call_trans2ioctl(connection_struct *conn,
7273 struct smb_request *req,
7274 char **pparams, int total_params,
7275 char **ppdata, int total_data,
7276 unsigned int max_data_bytes)
7278 char *pdata = *ppdata;
7279 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7281 /* check for an invalid fid before proceeding */
7284 reply_doserror(req, ERRDOS, ERRbadfid);
7288 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7289 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7290 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7291 if (*ppdata == NULL) {
7292 reply_nterror(req, NT_STATUS_NO_MEMORY);
7297 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7298 CAN ACCEPT THIS IN UNICODE. JRA. */
7300 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7301 srvstr_push(pdata, req->flags2, pdata + 2,
7302 global_myname(), 15,
7303 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7304 srvstr_push(pdata, req->flags2, pdata+18,
7305 lp_servicename(SNUM(conn)), 13,
7306 STR_ASCII|STR_TERMINATE); /* Service name */
7307 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7312 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7313 reply_doserror(req, ERRSRV, ERRerror);
7316 /****************************************************************************
7317 Reply to a SMBfindclose (stop trans2 directory search).
7318 ****************************************************************************/
7320 void reply_findclose(struct smb_request *req)
7324 START_PROFILE(SMBfindclose);
7327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7328 END_PROFILE(SMBfindclose);
7332 dptr_num = SVALS(req->vwv+0, 0);
7334 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7336 dptr_close(&dptr_num);
7338 reply_outbuf(req, 0, 0);
7340 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7342 END_PROFILE(SMBfindclose);
7346 /****************************************************************************
7347 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7348 ****************************************************************************/
7350 void reply_findnclose(struct smb_request *req)
7354 START_PROFILE(SMBfindnclose);
7357 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7358 END_PROFILE(SMBfindnclose);
7362 dptr_num = SVAL(req->vwv+0, 0);
7364 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7366 /* We never give out valid handles for a
7367 findnotifyfirst - so any dptr_num is ok here.
7370 reply_outbuf(req, 0, 0);
7372 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7374 END_PROFILE(SMBfindnclose);
7378 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7379 struct trans_state *state)
7381 if (Protocol >= PROTOCOL_NT1) {
7382 req->flags2 |= 0x40; /* IS_LONG_NAME */
7383 SSVAL(req->inbuf,smb_flg2,req->flags2);
7386 if (conn->encrypt_level == Required && !req->encrypted) {
7387 if (state->call != TRANSACT2_QFSINFO &&
7388 state->call != TRANSACT2_SETFSINFO) {
7389 DEBUG(0,("handle_trans2: encryption required "
7391 (unsigned int)state->call));
7392 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7397 /* Now we must call the relevant TRANS2 function */
7398 switch(state->call) {
7399 case TRANSACT2_OPEN:
7401 START_PROFILE(Trans2_open);
7402 call_trans2open(conn, req,
7403 &state->param, state->total_param,
7404 &state->data, state->total_data,
7405 state->max_data_return);
7406 END_PROFILE(Trans2_open);
7410 case TRANSACT2_FINDFIRST:
7412 START_PROFILE(Trans2_findfirst);
7413 call_trans2findfirst(conn, req,
7414 &state->param, state->total_param,
7415 &state->data, state->total_data,
7416 state->max_data_return);
7417 END_PROFILE(Trans2_findfirst);
7421 case TRANSACT2_FINDNEXT:
7423 START_PROFILE(Trans2_findnext);
7424 call_trans2findnext(conn, req,
7425 &state->param, state->total_param,
7426 &state->data, state->total_data,
7427 state->max_data_return);
7428 END_PROFILE(Trans2_findnext);
7432 case TRANSACT2_QFSINFO:
7434 START_PROFILE(Trans2_qfsinfo);
7435 call_trans2qfsinfo(conn, req,
7436 &state->param, state->total_param,
7437 &state->data, state->total_data,
7438 state->max_data_return);
7439 END_PROFILE(Trans2_qfsinfo);
7443 case TRANSACT2_SETFSINFO:
7445 START_PROFILE(Trans2_setfsinfo);
7446 call_trans2setfsinfo(conn, req,
7447 &state->param, state->total_param,
7448 &state->data, state->total_data,
7449 state->max_data_return);
7450 END_PROFILE(Trans2_setfsinfo);
7454 case TRANSACT2_QPATHINFO:
7455 case TRANSACT2_QFILEINFO:
7457 START_PROFILE(Trans2_qpathinfo);
7458 call_trans2qfilepathinfo(conn, req, state->call,
7459 &state->param, state->total_param,
7460 &state->data, state->total_data,
7461 state->max_data_return);
7462 END_PROFILE(Trans2_qpathinfo);
7466 case TRANSACT2_SETPATHINFO:
7467 case TRANSACT2_SETFILEINFO:
7469 START_PROFILE(Trans2_setpathinfo);
7470 call_trans2setfilepathinfo(conn, req, state->call,
7471 &state->param, state->total_param,
7472 &state->data, state->total_data,
7473 state->max_data_return);
7474 END_PROFILE(Trans2_setpathinfo);
7478 case TRANSACT2_FINDNOTIFYFIRST:
7480 START_PROFILE(Trans2_findnotifyfirst);
7481 call_trans2findnotifyfirst(conn, req,
7482 &state->param, state->total_param,
7483 &state->data, state->total_data,
7484 state->max_data_return);
7485 END_PROFILE(Trans2_findnotifyfirst);
7489 case TRANSACT2_FINDNOTIFYNEXT:
7491 START_PROFILE(Trans2_findnotifynext);
7492 call_trans2findnotifynext(conn, req,
7493 &state->param, state->total_param,
7494 &state->data, state->total_data,
7495 state->max_data_return);
7496 END_PROFILE(Trans2_findnotifynext);
7500 case TRANSACT2_MKDIR:
7502 START_PROFILE(Trans2_mkdir);
7503 call_trans2mkdir(conn, req,
7504 &state->param, state->total_param,
7505 &state->data, state->total_data,
7506 state->max_data_return);
7507 END_PROFILE(Trans2_mkdir);
7511 case TRANSACT2_GET_DFS_REFERRAL:
7513 START_PROFILE(Trans2_get_dfs_referral);
7514 call_trans2getdfsreferral(conn, req,
7515 &state->param, state->total_param,
7516 &state->data, state->total_data,
7517 state->max_data_return);
7518 END_PROFILE(Trans2_get_dfs_referral);
7522 case TRANSACT2_IOCTL:
7524 START_PROFILE(Trans2_ioctl);
7525 call_trans2ioctl(conn, req,
7526 &state->param, state->total_param,
7527 &state->data, state->total_data,
7528 state->max_data_return);
7529 END_PROFILE(Trans2_ioctl);
7534 /* Error in request */
7535 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7536 reply_doserror(req, ERRSRV,ERRerror);
7540 /****************************************************************************
7541 Reply to a SMBtrans2.
7542 ****************************************************************************/
7544 void reply_trans2(struct smb_request *req)
7546 connection_struct *conn = req->conn;
7551 unsigned int tran_call;
7552 struct trans_state *state;
7555 START_PROFILE(SMBtrans2);
7557 if (req->wct < 14) {
7558 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7559 END_PROFILE(SMBtrans2);
7563 dsoff = SVAL(req->vwv+12, 0);
7564 dscnt = SVAL(req->vwv+11, 0);
7565 psoff = SVAL(req->vwv+10, 0);
7566 pscnt = SVAL(req->vwv+9, 0);
7567 tran_call = SVAL(req->vwv+14, 0);
7569 result = allow_new_trans(conn->pending_trans, req->mid);
7570 if (!NT_STATUS_IS_OK(result)) {
7571 DEBUG(2, ("Got invalid trans2 request: %s\n",
7572 nt_errstr(result)));
7573 reply_nterror(req, result);
7574 END_PROFILE(SMBtrans2);
7579 switch (tran_call) {
7580 /* List the allowed trans2 calls on IPC$ */
7581 case TRANSACT2_OPEN:
7582 case TRANSACT2_GET_DFS_REFERRAL:
7583 case TRANSACT2_QFILEINFO:
7584 case TRANSACT2_QFSINFO:
7585 case TRANSACT2_SETFSINFO:
7588 reply_doserror(req, ERRSRV, ERRaccess);
7589 END_PROFILE(SMBtrans2);
7594 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7595 DEBUG(0, ("talloc failed\n"));
7596 reply_nterror(req, NT_STATUS_NO_MEMORY);
7597 END_PROFILE(SMBtrans2);
7601 state->cmd = SMBtrans2;
7603 state->mid = req->mid;
7604 state->vuid = req->vuid;
7605 state->setup_count = SVAL(req->vwv+13, 0);
7606 state->setup = NULL;
7607 state->total_param = SVAL(req->vwv+0, 0);
7608 state->param = NULL;
7609 state->total_data = SVAL(req->vwv+1, 0);
7611 state->max_param_return = SVAL(req->vwv+2, 0);
7612 state->max_data_return = SVAL(req->vwv+3, 0);
7613 state->max_setup_return = SVAL(req->vwv+4, 0);
7614 state->close_on_completion = BITSETW(req->vwv+5, 0);
7615 state->one_way = BITSETW(req->vwv+5, 1);
7617 state->call = tran_call;
7619 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7620 is so as a sanity check */
7621 if (state->setup_count != 1) {
7623 * Need to have rc=0 for ioctl to get job id for OS/2.
7624 * Network printing will fail if function is not successful.
7625 * Similar function in reply.c will be used if protocol
7626 * is LANMAN1.0 instead of LM1.2X002.
7627 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7628 * outbuf doesn't have to be set(only job id is used).
7630 if ( (state->setup_count == 4)
7631 && (tran_call == TRANSACT2_IOCTL)
7632 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7633 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7634 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7636 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7637 DEBUG(2,("Transaction is %d\n",tran_call));
7639 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7640 END_PROFILE(SMBtrans2);
7645 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7648 if (state->total_data) {
7650 if (trans_oob(state->total_data, 0, dscnt)
7651 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7655 /* Can't use talloc here, the core routines do realloc on the
7656 * params and data. */
7657 state->data = (char *)SMB_MALLOC(state->total_data);
7658 if (state->data == NULL) {
7659 DEBUG(0,("reply_trans2: data malloc fail for %u "
7660 "bytes !\n", (unsigned int)state->total_data));
7662 reply_nterror(req, NT_STATUS_NO_MEMORY);
7663 END_PROFILE(SMBtrans2);
7667 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7670 if (state->total_param) {
7672 if (trans_oob(state->total_param, 0, pscnt)
7673 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7677 /* Can't use talloc here, the core routines do realloc on the
7678 * params and data. */
7679 state->param = (char *)SMB_MALLOC(state->total_param);
7680 if (state->param == NULL) {
7681 DEBUG(0,("reply_trans: param malloc fail for %u "
7682 "bytes !\n", (unsigned int)state->total_param));
7683 SAFE_FREE(state->data);
7685 reply_nterror(req, NT_STATUS_NO_MEMORY);
7686 END_PROFILE(SMBtrans2);
7690 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7693 state->received_data = dscnt;
7694 state->received_param = pscnt;
7696 if ((state->received_param == state->total_param) &&
7697 (state->received_data == state->total_data)) {
7699 handle_trans2(conn, req, state);
7701 SAFE_FREE(state->data);
7702 SAFE_FREE(state->param);
7704 END_PROFILE(SMBtrans2);
7708 DLIST_ADD(conn->pending_trans, state);
7710 /* We need to send an interim response then receive the rest
7711 of the parameter/data bytes */
7712 reply_outbuf(req, 0, 0);
7713 show_msg((char *)req->outbuf);
7714 END_PROFILE(SMBtrans2);
7719 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7720 SAFE_FREE(state->data);
7721 SAFE_FREE(state->param);
7723 END_PROFILE(SMBtrans2);
7724 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7728 /****************************************************************************
7729 Reply to a SMBtranss2
7730 ****************************************************************************/
7732 void reply_transs2(struct smb_request *req)
7734 connection_struct *conn = req->conn;
7735 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7736 struct trans_state *state;
7738 START_PROFILE(SMBtranss2);
7740 show_msg((char *)req->inbuf);
7743 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7744 END_PROFILE(SMBtranss2);
7748 for (state = conn->pending_trans; state != NULL;
7749 state = state->next) {
7750 if (state->mid == req->mid) {
7755 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7756 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7757 END_PROFILE(SMBtranss2);
7761 /* Revise state->total_param and state->total_data in case they have
7762 changed downwards */
7764 if (SVAL(req->vwv+0, 0) < state->total_param)
7765 state->total_param = SVAL(req->vwv+0, 0);
7766 if (SVAL(req->vwv+1, 0) < state->total_data)
7767 state->total_data = SVAL(req->vwv+1, 0);
7769 pcnt = SVAL(req->vwv+2, 0);
7770 poff = SVAL(req->vwv+3, 0);
7771 pdisp = SVAL(req->vwv+4, 0);
7773 dcnt = SVAL(req->vwv+5, 0);
7774 doff = SVAL(req->vwv+6, 0);
7775 ddisp = SVAL(req->vwv+7, 0);
7777 state->received_param += pcnt;
7778 state->received_data += dcnt;
7780 if ((state->received_data > state->total_data) ||
7781 (state->received_param > state->total_param))
7785 if (trans_oob(state->total_param, pdisp, pcnt)
7786 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7789 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7793 if (trans_oob(state->total_data, ddisp, dcnt)
7794 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7797 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7800 if ((state->received_param < state->total_param) ||
7801 (state->received_data < state->total_data)) {
7802 END_PROFILE(SMBtranss2);
7806 handle_trans2(conn, req, state);
7808 DLIST_REMOVE(conn->pending_trans, state);
7809 SAFE_FREE(state->data);
7810 SAFE_FREE(state->param);
7813 END_PROFILE(SMBtranss2);
7818 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7819 DLIST_REMOVE(conn->pending_trans, state);
7820 SAFE_FREE(state->data);
7821 SAFE_FREE(state->param);
7823 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7824 END_PROFILE(SMBtranss2);