2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 extern enum protocol_types Protocol;
30 extern uint32 global_client_caps;
32 #define get_file_size(sbuf) ((sbuf).st_size)
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
62 /********************************************************************
63 Given a stat buffer return the allocated size on disk, taking into
65 ********************************************************************/
67 uint64_t get_allocation_size(connection_struct *conn, files_struct *fsp, const SMB_STRUCT_STAT *sbuf)
71 if(S_ISDIR(sbuf->st_mode)) {
75 #if defined(HAVE_STAT_ST_BLOCKS) && defined(STAT_ST_BLOCKSIZE)
76 ret = (uint64_t)STAT_ST_BLOCKSIZE * (uint64_t)sbuf->st_blocks;
78 ret = (uint64_t)get_file_size(*sbuf);
81 if (fsp && fsp->initial_allocation_size)
82 ret = MAX(ret,fsp->initial_allocation_size);
84 return smb_roundup(conn, ret);
87 /****************************************************************************
88 Utility functions for dealing with extended attributes.
89 ****************************************************************************/
91 /****************************************************************************
92 Refuse to allow clients to overwrite our private xattrs.
93 ****************************************************************************/
95 static bool samba_private_attr_name(const char *unix_ea_name)
97 static const char *prohibited_ea_names[] = {
98 SAMBA_POSIX_INHERITANCE_EA_NAME,
99 SAMBA_XATTR_DOS_ATTRIB,
105 for (i = 0; prohibited_ea_names[i]; i++) {
106 if (strequal( prohibited_ea_names[i], unix_ea_name))
109 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
110 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
116 /****************************************************************************
117 Get one EA value. Fill in a struct ea_struct.
118 ****************************************************************************/
120 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
121 files_struct *fsp, const char *fname,
122 const char *ea_name, struct ea_struct *pea)
124 /* Get the value of this xattr. Max size is 64k. */
125 size_t attr_size = 256;
131 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
133 return NT_STATUS_NO_MEMORY;
136 if (fsp && fsp->fh->fd != -1) {
137 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
139 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
142 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
148 return map_nt_error_from_unix(errno);
151 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
152 dump_data(10, (uint8 *)val, sizeret);
155 if (strnequal(ea_name, "user.", 5)) {
156 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
158 pea->name = talloc_strdup(mem_ctx, ea_name);
160 if (pea->name == NULL) {
162 return NT_STATUS_NO_MEMORY;
164 pea->value.data = (unsigned char *)val;
165 pea->value.length = (size_t)sizeret;
169 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
170 files_struct *fsp, const char *fname,
171 char ***pnames, size_t *pnum_names)
173 /* Get a list of all xattrs. Max namesize is 64k. */
174 size_t ea_namelist_size = 1024;
175 char *ea_namelist = NULL;
180 ssize_t sizeret = -1;
182 if (!lp_ea_support(SNUM(conn))) {
189 * TALLOC the result early to get the talloc hierarchy right.
192 names = TALLOC_ARRAY(mem_ctx, char *, 1);
194 DEBUG(0, ("talloc failed\n"));
195 return NT_STATUS_NO_MEMORY;
198 while (ea_namelist_size <= 65536) {
200 ea_namelist = TALLOC_REALLOC_ARRAY(
201 names, ea_namelist, char, ea_namelist_size);
202 if (ea_namelist == NULL) {
203 DEBUG(0, ("talloc failed\n"));
205 return NT_STATUS_NO_MEMORY;
208 if (fsp && fsp->fh->fd != -1) {
209 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
212 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
216 if ((sizeret == -1) && (errno == ERANGE)) {
217 ea_namelist_size *= 2;
226 return map_nt_error_from_unix(errno);
229 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
230 (unsigned int)sizeret));
240 * Ensure the result is 0-terminated
243 if (ea_namelist[sizeret-1] != '\0') {
245 return NT_STATUS_INTERNAL_ERROR;
253 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
257 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
259 DEBUG(0, ("talloc failed\n"));
261 return NT_STATUS_NO_MEMORY;
267 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
268 names[num_names++] = p;
272 *pnum_names = num_names;
276 /****************************************************************************
277 Return a linked list of the total EA's. Plus the total size
278 ****************************************************************************/
280 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
281 const char *fname, size_t *pea_total_len)
283 /* Get a list of all xattrs. Max namesize is 64k. */
286 struct ea_list *ea_list_head = NULL;
291 if (!lp_ea_support(SNUM(conn))) {
295 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
298 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
302 for (i=0; i<num_names; i++) {
303 struct ea_list *listp;
306 if (strnequal(names[i], "system.", 7)
307 || samba_private_attr_name(names[i]))
310 listp = TALLOC_P(mem_ctx, struct ea_list);
315 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
321 push_ascii_fstring(dos_ea_name, listp->ea.name);
324 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
326 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
327 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
328 (unsigned int)listp->ea.value.length));
330 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
334 /* Add on 4 for total length. */
335 if (*pea_total_len) {
339 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
340 (unsigned int)*pea_total_len));
345 /****************************************************************************
346 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
348 ****************************************************************************/
350 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
351 connection_struct *conn, struct ea_list *ea_list)
353 unsigned int ret_data_size = 4;
356 SMB_ASSERT(total_data_size >= 4);
358 if (!lp_ea_support(SNUM(conn))) {
363 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
366 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
367 dos_namelen = strlen(dos_ea_name);
368 if (dos_namelen > 255 || dos_namelen == 0) {
371 if (ea_list->ea.value.length > 65535) {
374 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
378 /* We know we have room. */
379 SCVAL(p,0,ea_list->ea.flags);
380 SCVAL(p,1,dos_namelen);
381 SSVAL(p,2,ea_list->ea.value.length);
382 fstrcpy(p+4, dos_ea_name);
383 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
385 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
386 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
389 ret_data_size = PTR_DIFF(p, pdata);
390 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
391 SIVAL(pdata,0,ret_data_size);
392 return ret_data_size;
395 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
397 size_t total_ea_len = 0;
398 TALLOC_CTX *mem_ctx = NULL;
400 if (!lp_ea_support(SNUM(conn))) {
403 mem_ctx = talloc_tos();
404 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
408 /****************************************************************************
409 Ensure the EA name is case insensitive by matching any existing EA name.
410 ****************************************************************************/
412 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
415 TALLOC_CTX *mem_ctx = talloc_tos();
416 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
418 for (; ea_list; ea_list = ea_list->next) {
419 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
420 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
421 &unix_ea_name[5], ea_list->ea.name));
422 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
428 /****************************************************************************
429 Set or delete an extended attribute.
430 ****************************************************************************/
432 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
434 if (!lp_ea_support(SNUM(conn))) {
435 return NT_STATUS_EAS_NOT_SUPPORTED;
438 for (;ea_list; ea_list = ea_list->next) {
440 fstring unix_ea_name;
442 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
443 fstrcat(unix_ea_name, ea_list->ea.name);
445 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
447 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
449 if (samba_private_attr_name(unix_ea_name)) {
450 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
451 return NT_STATUS_ACCESS_DENIED;
454 if (ea_list->ea.value.length == 0) {
455 /* Remove the attribute. */
456 if (fsp && (fsp->fh->fd != -1)) {
457 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
458 unix_ea_name, fsp->fsp_name));
459 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
461 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
462 unix_ea_name, fname));
463 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
466 /* Removing a non existent attribute always succeeds. */
467 if (ret == -1 && errno == ENOATTR) {
468 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
474 if (fsp && (fsp->fh->fd != -1)) {
475 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
476 unix_ea_name, fsp->fsp_name));
477 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
478 ea_list->ea.value.data, ea_list->ea.value.length, 0);
480 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
481 unix_ea_name, fname));
482 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
483 ea_list->ea.value.data, ea_list->ea.value.length, 0);
489 if (errno == ENOTSUP) {
490 return NT_STATUS_EAS_NOT_SUPPORTED;
493 return map_nt_error_from_unix(errno);
499 /****************************************************************************
500 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
501 ****************************************************************************/
503 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
505 struct ea_list *ea_list_head = NULL;
506 size_t converted_size, offset = 0;
508 while (offset + 2 < data_size) {
509 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
510 unsigned int namelen = CVAL(pdata,offset);
512 offset++; /* Go past the namelen byte. */
514 /* integer wrap paranioa. */
515 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
516 (offset > data_size) || (namelen > data_size) ||
517 (offset + namelen >= data_size)) {
520 /* Ensure the name is null terminated. */
521 if (pdata[offset + namelen] != '\0') {
524 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
526 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
527 "failed: %s", strerror(errno)));
533 offset += (namelen + 1); /* Go past the name + terminating zero. */
534 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
535 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
541 /****************************************************************************
542 Read one EA list entry from the buffer.
543 ****************************************************************************/
545 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
547 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
549 unsigned int namelen;
550 size_t converted_size;
560 eal->ea.flags = CVAL(pdata,0);
561 namelen = CVAL(pdata,1);
562 val_len = SVAL(pdata,2);
564 if (4 + namelen + 1 + val_len > data_size) {
568 /* Ensure the name is null terminated. */
569 if (pdata[namelen + 4] != '\0') {
572 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
573 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
580 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
581 if (!eal->ea.value.data) {
585 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
587 /* Ensure we're null terminated just in case we print the value. */
588 eal->ea.value.data[val_len] = '\0';
589 /* But don't count the null. */
590 eal->ea.value.length--;
593 *pbytes_used = 4 + namelen + 1 + val_len;
596 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
597 dump_data(10, eal->ea.value.data, eal->ea.value.length);
602 /****************************************************************************
603 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
604 ****************************************************************************/
606 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
608 struct ea_list *ea_list_head = NULL;
610 size_t bytes_used = 0;
612 while (offset < data_size) {
613 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
619 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
620 offset += bytes_used;
626 /****************************************************************************
627 Count the total EA size needed.
628 ****************************************************************************/
630 static size_t ea_list_size(struct ea_list *ealist)
633 struct ea_list *listp;
636 for (listp = ealist; listp; listp = listp->next) {
637 push_ascii_fstring(dos_ea_name, listp->ea.name);
638 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
640 /* Add on 4 for total length. */
648 /****************************************************************************
649 Return a union of EA's from a file list and a list of names.
650 The TALLOC context for the two lists *MUST* be identical as we steal
651 memory from one list to add to another. JRA.
652 ****************************************************************************/
654 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
656 struct ea_list *nlistp, *flistp;
658 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
659 for (flistp = file_list; flistp; flistp = flistp->next) {
660 if (strequal(nlistp->ea.name, flistp->ea.name)) {
666 /* Copy the data from this entry. */
667 nlistp->ea.flags = flistp->ea.flags;
668 nlistp->ea.value = flistp->ea.value;
671 nlistp->ea.flags = 0;
672 ZERO_STRUCT(nlistp->ea.value);
676 *total_ea_len = ea_list_size(name_list);
680 /****************************************************************************
681 Send the required number of replies back.
682 We assume all fields other than the data fields are
683 set correctly for the type of call.
684 HACK ! Always assumes smb_setup field is zero.
685 ****************************************************************************/
687 void send_trans2_replies(connection_struct *conn,
688 struct smb_request *req,
695 /* As we are using a protocol > LANMAN1 then the max_send
696 variable must have been set in the sessetupX call.
697 This takes precedence over the max_xmit field in the
698 global struct. These different max_xmit variables should
699 be merged as this is now too confusing */
701 int data_to_send = datasize;
702 int params_to_send = paramsize;
704 const char *pp = params;
705 const char *pd = pdata;
706 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
707 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
708 int data_alignment_offset = 0;
709 bool overflow = False;
711 /* Modify the data_to_send and datasize and set the error if
712 we're trying to send more than max_data_bytes. We still send
713 the part of the packet(s) that fit. Strange, but needed
716 if (max_data_bytes > 0 && datasize > max_data_bytes) {
717 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
718 max_data_bytes, datasize ));
719 datasize = data_to_send = max_data_bytes;
723 /* If there genuinely are no parameters or data to send just send the empty packet */
725 if(params_to_send == 0 && data_to_send == 0) {
726 reply_outbuf(req, 10, 0);
727 show_msg((char *)req->outbuf);
731 /* When sending params and data ensure that both are nicely aligned */
732 /* Only do this alignment when there is also data to send - else
733 can cause NT redirector problems. */
735 if (((params_to_send % 4) != 0) && (data_to_send != 0))
736 data_alignment_offset = 4 - (params_to_send % 4);
738 /* Space is bufsize minus Netbios over TCP header minus SMB header */
739 /* The alignment_offset is to align the param bytes on an even byte
740 boundary. NT 4.0 Beta needs this to work correctly. */
742 useable_space = max_send - (smb_size
745 + data_alignment_offset);
747 if (useable_space < 0) {
748 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
749 "= %d!!!", useable_space));
750 exit_server_cleanly("send_trans2_replies: Not enough space");
753 while (params_to_send || data_to_send) {
754 /* Calculate whether we will totally or partially fill this packet */
756 total_sent_thistime = params_to_send + data_to_send;
758 /* We can never send more than useable_space */
760 * Note that 'useable_space' does not include the alignment offsets,
761 * but we must include the alignment offsets in the calculation of
762 * the length of the data we send over the wire, as the alignment offsets
763 * are sent here. Fix from Marc_Jacobsen@hp.com.
766 total_sent_thistime = MIN(total_sent_thistime, useable_space);
768 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
769 + data_alignment_offset);
772 * We might have SMBtrans2s in req which was transferred to
773 * the outbuf, fix that.
775 SCVAL(req->outbuf, smb_com, SMBtrans2);
777 /* Set total params and data to be sent */
778 SSVAL(req->outbuf,smb_tprcnt,paramsize);
779 SSVAL(req->outbuf,smb_tdrcnt,datasize);
781 /* Calculate how many parameters and data we can fit into
782 * this packet. Parameters get precedence
785 params_sent_thistime = MIN(params_to_send,useable_space);
786 data_sent_thistime = useable_space - params_sent_thistime;
787 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
789 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
791 /* smb_proff is the offset from the start of the SMB header to the
792 parameter bytes, however the first 4 bytes of outbuf are
793 the Netbios over TCP header. Thus use smb_base() to subtract
794 them from the calculation */
796 SSVAL(req->outbuf,smb_proff,
797 ((smb_buf(req->outbuf)+alignment_offset)
798 - smb_base(req->outbuf)));
800 if(params_sent_thistime == 0)
801 SSVAL(req->outbuf,smb_prdisp,0);
803 /* Absolute displacement of param bytes sent in this packet */
804 SSVAL(req->outbuf,smb_prdisp,pp - params);
806 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
807 if(data_sent_thistime == 0) {
808 SSVAL(req->outbuf,smb_droff,0);
809 SSVAL(req->outbuf,smb_drdisp, 0);
811 /* The offset of the data bytes is the offset of the
812 parameter bytes plus the number of parameters being sent this time */
813 SSVAL(req->outbuf, smb_droff,
814 ((smb_buf(req->outbuf)+alignment_offset)
815 - smb_base(req->outbuf))
816 + params_sent_thistime + data_alignment_offset);
817 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
820 /* Initialize the padding for alignment */
822 if (alignment_offset != 0) {
823 memset(smb_buf(req->outbuf), 0, alignment_offset);
826 /* Copy the param bytes into the packet */
828 if(params_sent_thistime) {
829 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
830 params_sent_thistime);
833 /* Copy in the data bytes */
834 if(data_sent_thistime) {
835 if (data_alignment_offset != 0) {
836 memset((smb_buf(req->outbuf)+alignment_offset+
837 params_sent_thistime), 0,
838 data_alignment_offset);
840 memcpy(smb_buf(req->outbuf)+alignment_offset
841 +params_sent_thistime+data_alignment_offset,
842 pd,data_sent_thistime);
845 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
846 params_sent_thistime, data_sent_thistime, useable_space));
847 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
848 params_to_send, data_to_send, paramsize, datasize));
851 error_packet_set((char *)req->outbuf,
852 ERRDOS,ERRbufferoverflow,
853 STATUS_BUFFER_OVERFLOW,
857 /* Send the packet */
858 show_msg((char *)req->outbuf);
859 if (!srv_send_smb(smbd_server_fd(),
861 IS_CONN_ENCRYPTED(conn)))
862 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
864 TALLOC_FREE(req->outbuf);
866 pp += params_sent_thistime;
867 pd += data_sent_thistime;
869 params_to_send -= params_sent_thistime;
870 data_to_send -= data_sent_thistime;
873 if(params_to_send < 0 || data_to_send < 0) {
874 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
875 params_to_send, data_to_send));
883 /****************************************************************************
884 Reply to a TRANSACT2_OPEN.
885 ****************************************************************************/
887 static void call_trans2open(connection_struct *conn,
888 struct smb_request *req,
889 char **pparams, int total_params,
890 char **ppdata, int total_data,
891 unsigned int max_data_bytes)
893 char *params = *pparams;
894 char *pdata = *ppdata;
899 bool return_additional_info;
910 SMB_STRUCT_STAT sbuf;
913 struct ea_list *ea_list = NULL;
918 uint32 create_disposition;
919 uint32 create_options = 0;
920 TALLOC_CTX *ctx = talloc_tos();
923 * Ensure we have enough parameters to perform the operation.
926 if (total_params < 29) {
927 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
931 flags = SVAL(params, 0);
932 deny_mode = SVAL(params, 2);
933 open_attr = SVAL(params,6);
934 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
935 if (oplock_request) {
936 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
940 return_additional_info = BITSETW(params,0);
941 open_sattr = SVAL(params, 4);
942 open_time = make_unix_date3(params+8);
944 open_ofun = SVAL(params,12);
945 open_size = IVAL(params,14);
949 reply_doserror(req, ERRSRV, ERRaccess);
953 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
954 total_params - 28, STR_TERMINATE,
956 if (!NT_STATUS_IS_OK(status)) {
957 reply_nterror(req, status);
961 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
962 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
963 (unsigned int)open_ofun, open_size));
965 if (open_ofun == 0) {
966 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
970 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
975 reply_doserror(req, ERRDOS, ERRbadaccess);
979 /* Any data in this call is an EA list. */
980 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
981 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
985 if (total_data != 4) {
986 if (total_data < 10) {
987 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
991 if (IVAL(pdata,0) > total_data) {
992 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
993 IVAL(pdata,0), (unsigned int)total_data));
994 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
998 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1001 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1004 } else if (IVAL(pdata,0) != 4) {
1005 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1009 status = SMB_VFS_CREATE_FILE(
1012 0, /* root_dir_fid */
1014 true, /* is_dos_path */
1015 access_mask, /* access_mask */
1016 share_mode, /* share_access */
1017 create_disposition, /* create_disposition*/
1018 create_options, /* create_options */
1019 open_attr, /* file_attributes */
1020 oplock_request, /* oplock_request */
1021 open_size, /* allocation_size */
1023 ea_list, /* ea_list */
1025 &smb_action, /* pinfo */
1028 if (!NT_STATUS_IS_OK(status)) {
1029 if (open_was_deferred(req->mid)) {
1030 /* We have re-scheduled this call. */
1033 reply_openerror(req, status);
1037 size = get_file_size(sbuf);
1038 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1039 mtime = sbuf.st_mtime;
1040 inode = sbuf.st_ino;
1042 close_file(req, fsp, ERROR_CLOSE);
1043 reply_doserror(req, ERRDOS,ERRnoaccess);
1047 /* Realloc the size of parameters and data we will return */
1048 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1049 if(*pparams == NULL ) {
1050 reply_nterror(req, NT_STATUS_NO_MEMORY);
1055 SSVAL(params,0,fsp->fnum);
1056 SSVAL(params,2,fattr);
1057 srv_put_dos_date2(params,4, mtime);
1058 SIVAL(params,8, (uint32)size);
1059 SSVAL(params,12,deny_mode);
1060 SSVAL(params,14,0); /* open_type - file or directory. */
1061 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1063 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1064 smb_action |= EXTENDED_OPLOCK_GRANTED;
1067 SSVAL(params,18,smb_action);
1070 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1072 SIVAL(params,20,inode);
1073 SSVAL(params,24,0); /* Padding. */
1075 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1076 SIVAL(params, 26, ea_size);
1078 SIVAL(params, 26, 0);
1081 /* Send the required number of replies */
1082 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1085 /*********************************************************
1086 Routine to check if a given string matches exactly.
1087 as a special case a mask of "." does NOT match. That
1088 is required for correct wildcard semantics
1089 Case can be significant or not.
1090 **********************************************************/
1092 static bool exact_match(connection_struct *conn,
1096 if (mask[0] == '.' && mask[1] == 0)
1098 if (conn->case_sensitive)
1099 return strcmp(str,mask)==0;
1100 if (StrCaseCmp(str,mask) != 0) {
1103 if (dptr_has_wild(conn->dirptr)) {
1109 /****************************************************************************
1110 Return the filetype for UNIX extensions.
1111 ****************************************************************************/
1113 static uint32 unix_filetype(mode_t mode)
1116 return UNIX_TYPE_FILE;
1117 else if(S_ISDIR(mode))
1118 return UNIX_TYPE_DIR;
1120 else if(S_ISLNK(mode))
1121 return UNIX_TYPE_SYMLINK;
1124 else if(S_ISCHR(mode))
1125 return UNIX_TYPE_CHARDEV;
1128 else if(S_ISBLK(mode))
1129 return UNIX_TYPE_BLKDEV;
1132 else if(S_ISFIFO(mode))
1133 return UNIX_TYPE_FIFO;
1136 else if(S_ISSOCK(mode))
1137 return UNIX_TYPE_SOCKET;
1140 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1141 return UNIX_TYPE_UNKNOWN;
1144 /****************************************************************************
1145 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1146 ****************************************************************************/
1148 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1150 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1151 SMB_STRUCT_STAT *psbuf,
1153 enum perm_type ptype,
1158 if (perms == SMB_MODE_NO_CHANGE) {
1159 if (!VALID_STAT(*psbuf)) {
1160 return NT_STATUS_INVALID_PARAMETER;
1162 *ret_perms = psbuf->st_mode;
1163 return NT_STATUS_OK;
1167 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1168 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1169 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1170 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1171 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1172 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1173 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1174 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1175 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1177 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1180 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1183 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1188 /* Apply mode mask */
1189 ret &= lp_create_mask(SNUM(conn));
1190 /* Add in force bits */
1191 ret |= lp_force_create_mode(SNUM(conn));
1194 ret &= lp_dir_mask(SNUM(conn));
1195 /* Add in force bits */
1196 ret |= lp_force_dir_mode(SNUM(conn));
1198 case PERM_EXISTING_FILE:
1199 /* Apply mode mask */
1200 ret &= lp_security_mask(SNUM(conn));
1201 /* Add in force bits */
1202 ret |= lp_force_security_mode(SNUM(conn));
1204 case PERM_EXISTING_DIR:
1205 /* Apply mode mask */
1206 ret &= lp_dir_security_mask(SNUM(conn));
1207 /* Add in force bits */
1208 ret |= lp_force_dir_security_mode(SNUM(conn));
1213 return NT_STATUS_OK;
1216 /****************************************************************************
1217 Needed to show the msdfs symlinks as directories. Modifies psbuf
1218 to be a directory if it's a msdfs link.
1219 ****************************************************************************/
1221 static bool check_msdfs_link(connection_struct *conn,
1222 const char *pathname,
1223 SMB_STRUCT_STAT *psbuf)
1225 int saved_errno = errno;
1226 if(lp_host_msdfs() &&
1227 lp_msdfs_root(SNUM(conn)) &&
1228 is_msdfs_link(conn, pathname, psbuf)) {
1230 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1233 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1234 errno = saved_errno;
1237 errno = saved_errno;
1242 /****************************************************************************
1243 Get a level dependent lanman2 dir entry.
1244 ****************************************************************************/
1246 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1247 connection_struct *conn,
1249 const char *path_mask,
1252 int requires_resume_key,
1258 int space_remaining,
1260 bool *got_exact_match,
1261 int *last_entry_off,
1262 struct ea_list *name_list)
1266 SMB_STRUCT_STAT sbuf;
1267 const char *mask = NULL;
1268 char *pathreal = NULL;
1269 const char *fname = NULL;
1270 char *p, *q, *pdata = *ppdata;
1274 SMB_OFF_T file_size = 0;
1275 uint64_t allocation_size = 0;
1277 struct timespec mdate_ts, adate_ts, create_date_ts;
1278 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1280 char *last_entry_ptr;
1282 uint32 nt_extmode; /* Used for NT connections instead of mode */
1283 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1284 bool check_mangled_names = lp_manglednames(conn->params);
1285 char mangled_name[13]; /* mangled 8.3 name. */
1287 *out_of_space = False;
1288 *got_exact_match = False;
1290 ZERO_STRUCT(mdate_ts);
1291 ZERO_STRUCT(adate_ts);
1292 ZERO_STRUCT(create_date_ts);
1294 if (!conn->dirptr) {
1298 p = strrchr_m(path_mask,'/');
1301 mask = talloc_strdup(ctx,"*.*");
1311 bool ms_dfs_link = False;
1313 /* Needed if we run out of space */
1314 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1315 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1318 * Due to bugs in NT client redirectors we are not using
1319 * resume keys any more - set them to zero.
1320 * Check out the related comments in findfirst/findnext.
1326 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1327 (long)conn->dirptr,curr_dirpos));
1334 * fname may get mangled, dname is never mangled.
1335 * Whenever we're accessing the filesystem we use
1336 * pathreal which is composed from dname.
1342 /* Mangle fname if it's an illegal name. */
1343 if (mangle_must_mangle(dname,conn->params)) {
1344 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1345 continue; /* Error - couldn't mangle. */
1347 fname = mangled_name;
1350 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1351 got_match = mask_match(fname, mask, conn->case_sensitive);
1354 if(!got_match && check_mangled_names &&
1355 !mangle_is_8_3(fname, False, conn->params)) {
1357 * It turns out that NT matches wildcards against
1358 * both long *and* short names. This may explain some
1359 * of the wildcard wierdness from old DOS clients
1360 * that some people have been seeing.... JRA.
1362 /* Force the mangling into 8.3. */
1363 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1364 continue; /* Error - couldn't mangle. */
1367 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1368 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1373 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1375 if (dont_descend && !isdots) {
1381 pathreal = talloc_asprintf(ctx,
1386 pathreal = talloc_asprintf(ctx,
1396 if (INFO_LEVEL_IS_UNIX(info_level)) {
1397 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1398 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1399 pathreal,strerror(errno)));
1400 TALLOC_FREE(pathreal);
1403 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1404 /* Needed to show the msdfs symlinks as
1407 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1409 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1410 pathreal,strerror(errno)));
1411 TALLOC_FREE(pathreal);
1417 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1419 mode = dos_mode(conn,pathreal,&sbuf);
1422 if (!dir_check_ftype(conn,mode,dirtype)) {
1423 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1424 TALLOC_FREE(pathreal);
1428 if (!(mode & aDIR)) {
1429 file_size = get_file_size(sbuf);
1431 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1433 mdate_ts = get_mtimespec(&sbuf);
1434 adate_ts = get_atimespec(&sbuf);
1435 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1437 if (ask_sharemode) {
1438 struct timespec write_time_ts;
1439 struct file_id fileid;
1441 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1442 get_file_infos(fileid, NULL, &write_time_ts);
1443 if (!null_timespec(write_time_ts)) {
1444 mdate_ts = write_time_ts;
1448 if (lp_dos_filetime_resolution(SNUM(conn))) {
1449 dos_filetime_timespec(&create_date_ts);
1450 dos_filetime_timespec(&mdate_ts);
1451 dos_filetime_timespec(&adate_ts);
1454 create_date = convert_timespec_to_time_t(create_date_ts);
1455 mdate = convert_timespec_to_time_t(mdate_ts);
1456 adate = convert_timespec_to_time_t(adate_ts);
1458 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1462 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1469 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1471 switch (info_level) {
1472 case SMB_FIND_INFO_STANDARD:
1473 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1474 if(requires_resume_key) {
1478 srv_put_dos_date2(p,0,create_date);
1479 srv_put_dos_date2(p,4,adate);
1480 srv_put_dos_date2(p,8,mdate);
1481 SIVAL(p,12,(uint32)file_size);
1482 SIVAL(p,16,(uint32)allocation_size);
1486 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1487 p += ucs2_align(base_data, p, 0);
1489 len = srvstr_push(base_data, flags2, p,
1490 fname, PTR_DIFF(end_data, p),
1492 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1494 SCVAL(nameptr, -1, len - 2);
1496 SCVAL(nameptr, -1, 0);
1500 SCVAL(nameptr, -1, len - 1);
1502 SCVAL(nameptr, -1, 0);
1508 case SMB_FIND_EA_SIZE:
1509 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1510 if(requires_resume_key) {
1514 srv_put_dos_date2(p,0,create_date);
1515 srv_put_dos_date2(p,4,adate);
1516 srv_put_dos_date2(p,8,mdate);
1517 SIVAL(p,12,(uint32)file_size);
1518 SIVAL(p,16,(uint32)allocation_size);
1521 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1522 SIVAL(p,22,ea_size); /* Extended attributes */
1526 len = srvstr_push(base_data, flags2,
1527 p, fname, PTR_DIFF(end_data, p),
1528 STR_TERMINATE | STR_NOALIGN);
1529 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1542 SCVAL(nameptr,0,len);
1544 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1547 case SMB_FIND_EA_LIST:
1549 struct ea_list *file_list = NULL;
1552 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1556 if(requires_resume_key) {
1560 srv_put_dos_date2(p,0,create_date);
1561 srv_put_dos_date2(p,4,adate);
1562 srv_put_dos_date2(p,8,mdate);
1563 SIVAL(p,12,(uint32)file_size);
1564 SIVAL(p,16,(uint32)allocation_size);
1566 p += 22; /* p now points to the EA area. */
1568 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1569 name_list = ea_list_union(name_list, file_list, &ea_len);
1571 /* We need to determine if this entry will fit in the space available. */
1572 /* Max string size is 255 bytes. */
1573 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1574 /* Move the dirptr back to prev_dirpos */
1575 dptr_SeekDir(conn->dirptr, prev_dirpos);
1576 *out_of_space = True;
1577 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1578 return False; /* Not finished - just out of space */
1581 /* Push the ea_data followed by the name. */
1582 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1584 len = srvstr_push(base_data, flags2,
1585 p + 1, fname, PTR_DIFF(end_data, p+1),
1586 STR_TERMINATE | STR_NOALIGN);
1587 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1600 SCVAL(nameptr,0,len);
1602 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1606 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1607 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1608 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1610 SIVAL(p,0,reskey); p += 4;
1611 put_long_date_timespec(p,create_date_ts); p += 8;
1612 put_long_date_timespec(p,adate_ts); p += 8;
1613 put_long_date_timespec(p,mdate_ts); p += 8;
1614 put_long_date_timespec(p,mdate_ts); p += 8;
1615 SOFF_T(p,0,file_size); p += 8;
1616 SOFF_T(p,0,allocation_size); p += 8;
1617 SIVAL(p,0,nt_extmode); p += 4;
1618 q = p; p += 4; /* q is placeholder for name length. */
1620 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1621 SIVAL(p,0,ea_size); /* Extended attributes */
1624 /* Clear the short name buffer. This is
1625 * IMPORTANT as not doing so will trigger
1626 * a Win2k client bug. JRA.
1628 if (!was_8_3 && check_mangled_names) {
1629 if (!name_to_8_3(fname,mangled_name,True,
1631 /* Error - mangle failed ! */
1632 memset(mangled_name,'\0',12);
1634 mangled_name[12] = 0;
1635 len = srvstr_push(base_data, flags2,
1636 p+2, mangled_name, 24,
1637 STR_UPPER|STR_UNICODE);
1639 memset(p + 2 + len,'\0',24 - len);
1646 len = srvstr_push(base_data, flags2, p,
1647 fname, PTR_DIFF(end_data, p),
1648 STR_TERMINATE_ASCII);
1651 SIVAL(p,0,0); /* Ensure any padding is null. */
1652 len = PTR_DIFF(p, pdata);
1653 len = (len + 3) & ~3;
1658 case SMB_FIND_FILE_DIRECTORY_INFO:
1659 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1661 SIVAL(p,0,reskey); p += 4;
1662 put_long_date_timespec(p,create_date_ts); p += 8;
1663 put_long_date_timespec(p,adate_ts); p += 8;
1664 put_long_date_timespec(p,mdate_ts); p += 8;
1665 put_long_date_timespec(p,mdate_ts); p += 8;
1666 SOFF_T(p,0,file_size); p += 8;
1667 SOFF_T(p,0,allocation_size); p += 8;
1668 SIVAL(p,0,nt_extmode); p += 4;
1669 len = srvstr_push(base_data, flags2,
1670 p + 4, fname, PTR_DIFF(end_data, p+4),
1671 STR_TERMINATE_ASCII);
1674 SIVAL(p,0,0); /* Ensure any padding is null. */
1675 len = PTR_DIFF(p, pdata);
1676 len = (len + 3) & ~3;
1681 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1682 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1684 SIVAL(p,0,reskey); p += 4;
1685 put_long_date_timespec(p,create_date_ts); p += 8;
1686 put_long_date_timespec(p,adate_ts); p += 8;
1687 put_long_date_timespec(p,mdate_ts); p += 8;
1688 put_long_date_timespec(p,mdate_ts); p += 8;
1689 SOFF_T(p,0,file_size); p += 8;
1690 SOFF_T(p,0,allocation_size); p += 8;
1691 SIVAL(p,0,nt_extmode); p += 4;
1692 q = p; p += 4; /* q is placeholder for name length. */
1694 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1695 SIVAL(p,0,ea_size); /* Extended attributes */
1698 len = srvstr_push(base_data, flags2, p,
1699 fname, PTR_DIFF(end_data, p),
1700 STR_TERMINATE_ASCII);
1704 SIVAL(p,0,0); /* Ensure any padding is null. */
1705 len = PTR_DIFF(p, pdata);
1706 len = (len + 3) & ~3;
1711 case SMB_FIND_FILE_NAMES_INFO:
1712 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1714 SIVAL(p,0,reskey); p += 4;
1716 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1717 acl on a dir (tridge) */
1718 len = srvstr_push(base_data, flags2, p,
1719 fname, PTR_DIFF(end_data, p),
1720 STR_TERMINATE_ASCII);
1723 SIVAL(p,0,0); /* Ensure any padding is null. */
1724 len = PTR_DIFF(p, pdata);
1725 len = (len + 3) & ~3;
1730 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1731 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1733 SIVAL(p,0,reskey); p += 4;
1734 put_long_date_timespec(p,create_date_ts); p += 8;
1735 put_long_date_timespec(p,adate_ts); p += 8;
1736 put_long_date_timespec(p,mdate_ts); p += 8;
1737 put_long_date_timespec(p,mdate_ts); p += 8;
1738 SOFF_T(p,0,file_size); p += 8;
1739 SOFF_T(p,0,allocation_size); p += 8;
1740 SIVAL(p,0,nt_extmode); p += 4;
1741 q = p; p += 4; /* q is placeholder for name length. */
1743 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1744 SIVAL(p,0,ea_size); /* Extended attributes */
1747 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1748 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1749 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1750 len = srvstr_push(base_data, flags2, p,
1751 fname, PTR_DIFF(end_data, p),
1752 STR_TERMINATE_ASCII);
1755 SIVAL(p,0,0); /* Ensure any padding is null. */
1756 len = PTR_DIFF(p, pdata);
1757 len = (len + 3) & ~3;
1762 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1763 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1764 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1766 SIVAL(p,0,reskey); p += 4;
1767 put_long_date_timespec(p,create_date_ts); p += 8;
1768 put_long_date_timespec(p,adate_ts); p += 8;
1769 put_long_date_timespec(p,mdate_ts); p += 8;
1770 put_long_date_timespec(p,mdate_ts); p += 8;
1771 SOFF_T(p,0,file_size); p += 8;
1772 SOFF_T(p,0,allocation_size); p += 8;
1773 SIVAL(p,0,nt_extmode); p += 4;
1774 q = p; p += 4; /* q is placeholder for name length */
1776 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1777 SIVAL(p,0,ea_size); /* Extended attributes */
1780 /* Clear the short name buffer. This is
1781 * IMPORTANT as not doing so will trigger
1782 * a Win2k client bug. JRA.
1784 if (!was_8_3 && check_mangled_names) {
1785 if (!name_to_8_3(fname,mangled_name,True,
1787 /* Error - mangle failed ! */
1788 memset(mangled_name,'\0',12);
1790 mangled_name[12] = 0;
1791 len = srvstr_push(base_data, flags2,
1792 p+2, mangled_name, 24,
1793 STR_UPPER|STR_UNICODE);
1796 memset(p + 2 + len,'\0',24 - len);
1803 SSVAL(p,0,0); p += 2; /* Reserved ? */
1804 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1805 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1806 len = srvstr_push(base_data, flags2, p,
1807 fname, PTR_DIFF(end_data, p),
1808 STR_TERMINATE_ASCII);
1811 SIVAL(p,0,0); /* Ensure any padding is null. */
1812 len = PTR_DIFF(p, pdata);
1813 len = (len + 3) & ~3;
1818 /* CIFS UNIX Extension. */
1820 case SMB_FIND_FILE_UNIX:
1821 case SMB_FIND_FILE_UNIX_INFO2:
1823 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1825 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1827 if (info_level == SMB_FIND_FILE_UNIX) {
1828 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1829 p = store_file_unix_basic(conn, p,
1831 len = srvstr_push(base_data, flags2, p,
1832 fname, PTR_DIFF(end_data, p),
1835 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1836 p = store_file_unix_basic_info2(conn, p,
1840 len = srvstr_push(base_data, flags2, p, fname,
1841 PTR_DIFF(end_data, p), 0);
1842 SIVAL(nameptr, 0, len);
1846 SIVAL(p,0,0); /* Ensure any padding is null. */
1848 len = PTR_DIFF(p, pdata);
1849 len = (len + 3) & ~3;
1850 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1852 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1861 if (PTR_DIFF(p,pdata) > space_remaining) {
1862 /* Move the dirptr back to prev_dirpos */
1863 dptr_SeekDir(conn->dirptr, prev_dirpos);
1864 *out_of_space = True;
1865 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1866 return False; /* Not finished - just out of space */
1869 /* Setup the last entry pointer, as an offset from base_data */
1870 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1871 /* Advance the data pointer to the next slot */
1877 /****************************************************************************
1878 Reply to a TRANS2_FINDFIRST.
1879 ****************************************************************************/
1881 static void call_trans2findfirst(connection_struct *conn,
1882 struct smb_request *req,
1883 char **pparams, int total_params,
1884 char **ppdata, int total_data,
1885 unsigned int max_data_bytes)
1887 /* We must be careful here that we don't return more than the
1888 allowed number of data bytes. If this means returning fewer than
1889 maxentries then so be it. We assume that the redirector has
1890 enough room for the fixed number of parameter bytes it has
1892 char *params = *pparams;
1893 char *pdata = *ppdata;
1897 uint16 findfirst_flags;
1898 bool close_after_first;
1900 bool requires_resume_key;
1902 char *directory = NULL;
1905 int last_entry_off=0;
1909 bool finished = False;
1910 bool dont_descend = False;
1911 bool out_of_space = False;
1912 int space_remaining;
1913 bool mask_contains_wcard = False;
1914 SMB_STRUCT_STAT sbuf;
1915 struct ea_list *ea_list = NULL;
1916 NTSTATUS ntstatus = NT_STATUS_OK;
1917 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1918 TALLOC_CTX *ctx = talloc_tos();
1920 if (total_params < 13) {
1921 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1925 dirtype = SVAL(params,0);
1926 maxentries = SVAL(params,2);
1927 findfirst_flags = SVAL(params,4);
1928 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1929 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1930 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1931 info_level = SVAL(params,6);
1933 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1934 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1935 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1936 info_level, max_data_bytes));
1939 /* W2K3 seems to treat zero as 1. */
1943 switch (info_level) {
1944 case SMB_FIND_INFO_STANDARD:
1945 case SMB_FIND_EA_SIZE:
1946 case SMB_FIND_EA_LIST:
1947 case SMB_FIND_FILE_DIRECTORY_INFO:
1948 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1949 case SMB_FIND_FILE_NAMES_INFO:
1950 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1951 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1952 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1954 case SMB_FIND_FILE_UNIX:
1955 case SMB_FIND_FILE_UNIX_INFO2:
1956 /* Always use filesystem for UNIX mtime query. */
1957 ask_sharemode = false;
1958 if (!lp_unix_extensions()) {
1959 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1964 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1968 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1969 params+12, total_params - 12,
1970 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1971 if (!NT_STATUS_IS_OK(ntstatus)) {
1972 reply_nterror(req, ntstatus);
1976 ntstatus = resolve_dfspath_wcard(ctx, conn,
1977 req->flags2 & FLAGS2_DFS_PATHNAMES,
1980 &mask_contains_wcard);
1981 if (!NT_STATUS_IS_OK(ntstatus)) {
1982 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1983 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1984 ERRSRV, ERRbadpath);
1987 reply_nterror(req, ntstatus);
1991 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1992 if (!NT_STATUS_IS_OK(ntstatus)) {
1993 reply_nterror(req, ntstatus);
1997 ntstatus = check_name(conn, directory);
1998 if (!NT_STATUS_IS_OK(ntstatus)) {
1999 reply_nterror(req, ntstatus);
2003 p = strrchr_m(directory,'/');
2005 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2006 if((directory[0] == '.') && (directory[1] == '\0')) {
2007 mask = talloc_strdup(ctx,"*");
2009 reply_nterror(req, NT_STATUS_NO_MEMORY);
2012 mask_contains_wcard = True;
2014 directory = talloc_strdup(talloc_tos(), "./");
2016 reply_nterror(req, NT_STATUS_NO_MEMORY);
2023 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2025 if (info_level == SMB_FIND_EA_LIST) {
2028 if (total_data < 4) {
2029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2033 ea_size = IVAL(pdata,0);
2034 if (ea_size != total_data) {
2035 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2036 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2037 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2041 if (!lp_ea_support(SNUM(conn))) {
2042 reply_doserror(req, ERRDOS, ERReasnotsupported);
2046 /* Pull out the list of names. */
2047 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2049 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2054 *ppdata = (char *)SMB_REALLOC(
2055 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2056 if(*ppdata == NULL ) {
2057 reply_nterror(req, NT_STATUS_NO_MEMORY);
2061 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2063 /* Realloc the params space */
2064 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2065 if (*pparams == NULL) {
2066 reply_nterror(req, NT_STATUS_NO_MEMORY);
2071 /* Save the wildcard match and attribs we are using on this directory -
2072 needed as lanman2 assumes these are being saved between calls */
2074 ntstatus = dptr_create(conn,
2080 mask_contains_wcard,
2084 if (!NT_STATUS_IS_OK(ntstatus)) {
2085 reply_nterror(req, ntstatus);
2089 dptr_num = dptr_dnum(conn->dirptr);
2090 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2092 /* We don't need to check for VOL here as this is returned by
2093 a different TRANS2 call. */
2095 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2096 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2097 dont_descend = True;
2100 space_remaining = max_data_bytes;
2101 out_of_space = False;
2103 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2104 bool got_exact_match = False;
2106 /* this is a heuristic to avoid seeking the dirptr except when
2107 absolutely necessary. It allows for a filename of about 40 chars */
2108 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2109 out_of_space = True;
2112 finished = !get_lanman2_dir_entry(ctx,
2115 mask,dirtype,info_level,
2116 requires_resume_key,dont_descend,
2119 space_remaining, &out_of_space,
2121 &last_entry_off, ea_list);
2124 if (finished && out_of_space)
2127 if (!finished && !out_of_space)
2131 * As an optimisation if we know we aren't looking
2132 * for a wildcard name (ie. the name matches the wildcard exactly)
2133 * then we can finish on any (first) match.
2134 * This speeds up large directory searches. JRA.
2140 /* Ensure space_remaining never goes -ve. */
2141 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2142 space_remaining = 0;
2143 out_of_space = true;
2145 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2149 /* Check if we can close the dirptr */
2150 if(close_after_first || (finished && close_if_end)) {
2151 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2152 dptr_close(&dptr_num);
2156 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2157 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2158 * the protocol level is less than NT1. Tested with smbclient. JRA.
2159 * This should fix the OS/2 client bug #2335.
2162 if(numentries == 0) {
2163 dptr_close(&dptr_num);
2164 if (Protocol < PROTOCOL_NT1) {
2165 reply_doserror(req, ERRDOS, ERRnofiles);
2168 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2169 ERRDOS, ERRbadfile);
2174 /* At this point pdata points to numentries directory entries. */
2176 /* Set up the return parameter block */
2177 SSVAL(params,0,dptr_num);
2178 SSVAL(params,2,numentries);
2179 SSVAL(params,4,finished);
2180 SSVAL(params,6,0); /* Never an EA error */
2181 SSVAL(params,8,last_entry_off);
2183 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2186 if ((! *directory) && dptr_path(dptr_num)) {
2187 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2189 reply_nterror(req, NT_STATUS_NO_MEMORY);
2193 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2194 smb_fn_name(req->cmd),
2195 mask, directory, dirtype, numentries ) );
2198 * Force a name mangle here to ensure that the
2199 * mask as an 8.3 name is top of the mangled cache.
2200 * The reasons for this are subtle. Don't remove
2201 * this code unless you know what you are doing
2202 * (see PR#13758). JRA.
2205 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2206 char mangled_name[13];
2207 name_to_8_3(mask, mangled_name, True, conn->params);
2213 /****************************************************************************
2214 Reply to a TRANS2_FINDNEXT.
2215 ****************************************************************************/
2217 static void call_trans2findnext(connection_struct *conn,
2218 struct smb_request *req,
2219 char **pparams, int total_params,
2220 char **ppdata, int total_data,
2221 unsigned int max_data_bytes)
2223 /* We must be careful here that we don't return more than the
2224 allowed number of data bytes. If this means returning fewer than
2225 maxentries then so be it. We assume that the redirector has
2226 enough room for the fixed number of parameter bytes it has
2228 char *params = *pparams;
2229 char *pdata = *ppdata;
2235 uint16 findnext_flags;
2236 bool close_after_request;
2238 bool requires_resume_key;
2240 bool mask_contains_wcard = False;
2241 char *resume_name = NULL;
2242 const char *mask = NULL;
2243 const char *directory = NULL;
2247 int i, last_entry_off=0;
2248 bool finished = False;
2249 bool dont_descend = False;
2250 bool out_of_space = False;
2251 int space_remaining;
2252 struct ea_list *ea_list = NULL;
2253 NTSTATUS ntstatus = NT_STATUS_OK;
2254 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2255 TALLOC_CTX *ctx = talloc_tos();
2257 if (total_params < 13) {
2258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2262 dptr_num = SVAL(params,0);
2263 maxentries = SVAL(params,2);
2264 info_level = SVAL(params,4);
2265 resume_key = IVAL(params,6);
2266 findnext_flags = SVAL(params,10);
2267 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2268 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2269 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2270 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2272 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2274 total_params - 12, STR_TERMINATE, &ntstatus,
2275 &mask_contains_wcard);
2276 if (!NT_STATUS_IS_OK(ntstatus)) {
2277 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2278 complain (it thinks we're asking for the directory above the shared
2279 path or an invalid name). Catch this as the resume name is only compared, never used in
2280 a file access. JRA. */
2281 srvstr_pull_talloc(ctx, params, req->flags2,
2282 &resume_name, params+12,
2286 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2287 reply_nterror(req, ntstatus);
2292 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2293 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2294 resume_key = %d resume name = %s continue=%d level = %d\n",
2295 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2296 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2299 /* W2K3 seems to treat zero as 1. */
2303 switch (info_level) {
2304 case SMB_FIND_INFO_STANDARD:
2305 case SMB_FIND_EA_SIZE:
2306 case SMB_FIND_EA_LIST:
2307 case SMB_FIND_FILE_DIRECTORY_INFO:
2308 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2309 case SMB_FIND_FILE_NAMES_INFO:
2310 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2311 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2312 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2314 case SMB_FIND_FILE_UNIX:
2315 case SMB_FIND_FILE_UNIX_INFO2:
2316 /* Always use filesystem for UNIX mtime query. */
2317 ask_sharemode = false;
2318 if (!lp_unix_extensions()) {
2319 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2324 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2328 if (info_level == SMB_FIND_EA_LIST) {
2331 if (total_data < 4) {
2332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2336 ea_size = IVAL(pdata,0);
2337 if (ea_size != total_data) {
2338 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2339 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2340 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2344 if (!lp_ea_support(SNUM(conn))) {
2345 reply_doserror(req, ERRDOS, ERReasnotsupported);
2349 /* Pull out the list of names. */
2350 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2352 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2357 *ppdata = (char *)SMB_REALLOC(
2358 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2359 if(*ppdata == NULL) {
2360 reply_nterror(req, NT_STATUS_NO_MEMORY);
2365 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2367 /* Realloc the params space */
2368 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2369 if(*pparams == NULL ) {
2370 reply_nterror(req, NT_STATUS_NO_MEMORY);
2376 /* Check that the dptr is valid */
2377 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2378 reply_doserror(req, ERRDOS, ERRnofiles);
2382 string_set(&conn->dirpath,dptr_path(dptr_num));
2384 /* Get the wildcard mask from the dptr */
2385 if((p = dptr_wcard(dptr_num))== NULL) {
2386 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2387 reply_doserror(req, ERRDOS, ERRnofiles);
2392 directory = conn->dirpath;
2394 /* Get the attr mask from the dptr */
2395 dirtype = dptr_attr(dptr_num);
2397 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2398 dptr_num, mask, dirtype,
2400 dptr_TellDir(conn->dirptr)));
2402 /* We don't need to check for VOL here as this is returned by
2403 a different TRANS2 call. */
2405 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2406 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2407 dont_descend = True;
2410 space_remaining = max_data_bytes;
2411 out_of_space = False;
2414 * Seek to the correct position. We no longer use the resume key but
2415 * depend on the last file name instead.
2418 if(*resume_name && !continue_bit) {
2421 long current_pos = 0;
2423 * Remember, name_to_8_3 is called by
2424 * get_lanman2_dir_entry(), so the resume name
2425 * could be mangled. Ensure we check the unmangled name.
2428 if (mangle_is_mangled(resume_name, conn->params)) {
2429 char *new_resume_name = NULL;
2430 mangle_lookup_name_from_8_3(ctx,
2434 if (new_resume_name) {
2435 resume_name = new_resume_name;
2440 * Fix for NT redirector problem triggered by resume key indexes
2441 * changing between directory scans. We now return a resume key of 0
2442 * and instead look for the filename to continue from (also given
2443 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2444 * findfirst/findnext (as is usual) then the directory pointer
2445 * should already be at the correct place.
2448 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2449 } /* end if resume_name && !continue_bit */
2451 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2452 bool got_exact_match = False;
2454 /* this is a heuristic to avoid seeking the dirptr except when
2455 absolutely necessary. It allows for a filename of about 40 chars */
2456 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2457 out_of_space = True;
2460 finished = !get_lanman2_dir_entry(ctx,
2463 mask,dirtype,info_level,
2464 requires_resume_key,dont_descend,
2467 space_remaining, &out_of_space,
2469 &last_entry_off, ea_list);
2472 if (finished && out_of_space)
2475 if (!finished && !out_of_space)
2479 * As an optimisation if we know we aren't looking
2480 * for a wildcard name (ie. the name matches the wildcard exactly)
2481 * then we can finish on any (first) match.
2482 * This speeds up large directory searches. JRA.
2488 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2491 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2492 smb_fn_name(req->cmd),
2493 mask, directory, dirtype, numentries ) );
2495 /* Check if we can close the dirptr */
2496 if(close_after_request || (finished && close_if_end)) {
2497 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2498 dptr_close(&dptr_num); /* This frees up the saved mask */
2501 /* Set up the return parameter block */
2502 SSVAL(params,0,numentries);
2503 SSVAL(params,2,finished);
2504 SSVAL(params,4,0); /* Never an EA error */
2505 SSVAL(params,6,last_entry_off);
2507 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2513 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2515 E_md4hash(lp_servicename(SNUM(conn)),objid);
2519 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2521 SMB_ASSERT(extended_info != NULL);
2523 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2524 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2525 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2526 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2527 #ifdef SAMBA_VERSION_REVISION
2528 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2530 extended_info->samba_subversion = 0;
2531 #ifdef SAMBA_VERSION_RC_RELEASE
2532 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2534 #ifdef SAMBA_VERSION_PRE_RELEASE
2535 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2538 #ifdef SAMBA_VERSION_VENDOR_PATCH
2539 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2541 extended_info->samba_gitcommitdate = 0;
2542 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2543 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2546 memset(extended_info->samba_version_string, 0,
2547 sizeof(extended_info->samba_version_string));
2549 snprintf (extended_info->samba_version_string,
2550 sizeof(extended_info->samba_version_string),
2551 "%s", samba_version_string());
2554 /****************************************************************************
2555 Reply to a TRANS2_QFSINFO (query filesystem info).
2556 ****************************************************************************/
2558 static void call_trans2qfsinfo(connection_struct *conn,
2559 struct smb_request *req,
2560 char **pparams, int total_params,
2561 char **ppdata, int total_data,
2562 unsigned int max_data_bytes)
2564 char *pdata, *end_data;
2565 char *params = *pparams;
2569 const char *vname = volume_label(SNUM(conn));
2570 int snum = SNUM(conn);
2571 char *fstype = lp_fstype(SNUM(conn));
2572 uint32 additional_flags = 0;
2574 if (total_params < 2) {
2575 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2579 info_level = SVAL(params,0);
2582 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2583 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2584 "info level (0x%x) on IPC$.\n",
2585 (unsigned int)info_level));
2586 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2591 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2592 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2593 DEBUG(0,("call_trans2qfsinfo: encryption required "
2594 "and info level 0x%x sent.\n",
2595 (unsigned int)info_level));
2596 exit_server_cleanly("encryption required "
2602 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2604 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2605 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2606 reply_doserror(req, ERRSRV, ERRinvdevice);
2610 *ppdata = (char *)SMB_REALLOC(
2611 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2612 if (*ppdata == NULL ) {
2613 reply_nterror(req, NT_STATUS_NO_MEMORY);
2618 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2619 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2621 switch (info_level) {
2622 case SMB_INFO_ALLOCATION:
2624 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2626 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2627 reply_unixerror(req, ERRHRD, ERRgeneral);
2631 block_size = lp_block_size(snum);
2632 if (bsize < block_size) {
2633 uint64_t factor = block_size/bsize;
2638 if (bsize > block_size) {
2639 uint64_t factor = bsize/block_size;
2644 bytes_per_sector = 512;
2645 sectors_per_unit = bsize/bytes_per_sector;
2647 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2648 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2649 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2651 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2652 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2653 SIVAL(pdata,l1_cUnit,dsize);
2654 SIVAL(pdata,l1_cUnitAvail,dfree);
2655 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2659 case SMB_INFO_VOLUME:
2660 /* Return volume name */
2662 * Add volume serial number - hash of a combination of
2663 * the called hostname and the service name.
2665 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2667 * Win2k3 and previous mess this up by sending a name length
2668 * one byte short. I believe only older clients (OS/2 Win9x) use
2669 * this call so try fixing this by adding a terminating null to
2670 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2674 pdata+l2_vol_szVolLabel, vname,
2675 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2676 STR_NOALIGN|STR_TERMINATE);
2677 SCVAL(pdata,l2_vol_cch,len);
2678 data_len = l2_vol_szVolLabel + len;
2679 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2680 (unsigned)st.st_ctime, len, vname));
2683 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2684 case SMB_FS_ATTRIBUTE_INFORMATION:
2686 additional_flags = 0;
2687 #if defined(HAVE_SYS_QUOTAS)
2688 additional_flags |= FILE_VOLUME_QUOTAS;
2691 if(lp_nt_acl_support(SNUM(conn))) {
2692 additional_flags |= FILE_PERSISTENT_ACLS;
2695 /* Capabilities are filled in at connection time through STATVFS call */
2696 additional_flags |= conn->fs_capabilities;
2698 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2699 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2700 additional_flags); /* FS ATTRIBUTES */
2702 SIVAL(pdata,4,255); /* Max filename component length */
2703 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2704 and will think we can't do long filenames */
2705 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2706 PTR_DIFF(end_data, pdata+12),
2709 data_len = 12 + len;
2712 case SMB_QUERY_FS_LABEL_INFO:
2713 case SMB_FS_LABEL_INFORMATION:
2714 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2715 PTR_DIFF(end_data, pdata+4), 0);
2720 case SMB_QUERY_FS_VOLUME_INFO:
2721 case SMB_FS_VOLUME_INFORMATION:
2724 * Add volume serial number - hash of a combination of
2725 * the called hostname and the service name.
2727 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2728 (str_checksum(get_local_machine_name())<<16));
2730 /* Max label len is 32 characters. */
2731 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2732 PTR_DIFF(end_data, pdata+18),
2734 SIVAL(pdata,12,len);
2737 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2738 (int)strlen(vname),vname, lp_servicename(snum)));
2741 case SMB_QUERY_FS_SIZE_INFO:
2742 case SMB_FS_SIZE_INFORMATION:
2744 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2746 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2747 reply_unixerror(req, ERRHRD, ERRgeneral);
2750 block_size = lp_block_size(snum);
2751 if (bsize < block_size) {
2752 uint64_t factor = block_size/bsize;
2757 if (bsize > block_size) {
2758 uint64_t factor = bsize/block_size;
2763 bytes_per_sector = 512;
2764 sectors_per_unit = bsize/bytes_per_sector;
2765 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2766 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2767 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2768 SBIG_UINT(pdata,0,dsize);
2769 SBIG_UINT(pdata,8,dfree);
2770 SIVAL(pdata,16,sectors_per_unit);
2771 SIVAL(pdata,20,bytes_per_sector);
2775 case SMB_FS_FULL_SIZE_INFORMATION:
2777 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2779 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2780 reply_unixerror(req, ERRHRD, ERRgeneral);
2783 block_size = lp_block_size(snum);
2784 if (bsize < block_size) {
2785 uint64_t factor = block_size/bsize;
2790 if (bsize > block_size) {
2791 uint64_t factor = bsize/block_size;
2796 bytes_per_sector = 512;
2797 sectors_per_unit = bsize/bytes_per_sector;
2798 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2799 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2800 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2801 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2802 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2803 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2804 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2805 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2809 case SMB_QUERY_FS_DEVICE_INFO:
2810 case SMB_FS_DEVICE_INFORMATION:
2812 SIVAL(pdata,0,0); /* dev type */
2813 SIVAL(pdata,4,0); /* characteristics */
2816 #ifdef HAVE_SYS_QUOTAS
2817 case SMB_FS_QUOTA_INFORMATION:
2819 * what we have to send --metze:
2821 * Unknown1: 24 NULL bytes
2822 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2823 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2824 * Quota Flags: 2 byte :
2825 * Unknown3: 6 NULL bytes
2829 * details for Quota Flags:
2831 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2832 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2833 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2834 * 0x0001 Enable Quotas: enable quota for this fs
2838 /* we need to fake up a fsp here,
2839 * because its not send in this call
2842 SMB_NTQUOTA_STRUCT quotas;
2845 ZERO_STRUCT(quotas);
2851 if (conn->server_info->utok.uid != 0) {
2852 DEBUG(0,("set_user_quota: access_denied "
2853 "service [%s] user [%s]\n",
2854 lp_servicename(SNUM(conn)),
2855 conn->server_info->unix_name));
2856 reply_doserror(req, ERRDOS, ERRnoaccess);
2860 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2861 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2862 reply_doserror(req, ERRSRV, ERRerror);
2868 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2870 /* Unknown1 24 NULL bytes*/
2871 SBIG_UINT(pdata,0,(uint64_t)0);
2872 SBIG_UINT(pdata,8,(uint64_t)0);
2873 SBIG_UINT(pdata,16,(uint64_t)0);
2875 /* Default Soft Quota 8 bytes */
2876 SBIG_UINT(pdata,24,quotas.softlim);
2878 /* Default Hard Quota 8 bytes */
2879 SBIG_UINT(pdata,32,quotas.hardlim);
2881 /* Quota flag 2 bytes */
2882 SSVAL(pdata,40,quotas.qflags);
2884 /* Unknown3 6 NULL bytes */
2890 #endif /* HAVE_SYS_QUOTAS */
2891 case SMB_FS_OBJECTID_INFORMATION:
2893 unsigned char objid[16];
2894 struct smb_extended_info extended_info;
2895 memcpy(pdata,create_volume_objectid(conn, objid),16);
2896 samba_extended_info_version (&extended_info);
2897 SIVAL(pdata,16,extended_info.samba_magic);
2898 SIVAL(pdata,20,extended_info.samba_version);
2899 SIVAL(pdata,24,extended_info.samba_subversion);
2900 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2901 memcpy(pdata+36,extended_info.samba_version_string,28);
2907 * Query the version and capabilities of the CIFS UNIX extensions
2911 case SMB_QUERY_CIFS_UNIX_INFO:
2913 bool large_write = lp_min_receive_file_size() &&
2914 !srv_is_signing_active();
2915 bool large_read = !srv_is_signing_active();
2916 int encrypt_caps = 0;
2918 if (!lp_unix_extensions()) {
2919 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2923 switch (conn->encrypt_level) {
2929 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2932 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2933 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2934 large_write = false;
2940 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2941 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2943 /* We have POSIX ACLs, pathname, encryption,
2944 * large read/write, and locking capability. */
2946 SBIG_UINT(pdata,4,((uint64_t)(
2947 CIFS_UNIX_POSIX_ACLS_CAP|
2948 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2949 CIFS_UNIX_FCNTL_LOCKS_CAP|
2950 CIFS_UNIX_EXTATTR_CAP|
2951 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2953 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2955 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2959 case SMB_QUERY_POSIX_FS_INFO:
2962 vfs_statvfs_struct svfs;
2964 if (!lp_unix_extensions()) {
2965 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2969 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2973 SIVAL(pdata,0,svfs.OptimalTransferSize);
2974 SIVAL(pdata,4,svfs.BlockSize);
2975 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2976 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2977 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2978 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2979 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2980 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2981 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2983 } else if (rc == EOPNOTSUPP) {
2984 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2986 #endif /* EOPNOTSUPP */
2988 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2989 reply_doserror(req, ERRSRV, ERRerror);
2995 case SMB_QUERY_POSIX_WHOAMI:
3001 if (!lp_unix_extensions()) {
3002 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3006 if (max_data_bytes < 40) {
3007 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3011 /* We ARE guest if global_sid_Builtin_Guests is
3012 * in our list of SIDs.
3014 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3015 conn->server_info->ptok)) {
3016 flags |= SMB_WHOAMI_GUEST;
3019 /* We are NOT guest if global_sid_Authenticated_Users
3020 * is in our list of SIDs.
3022 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3023 conn->server_info->ptok)) {
3024 flags &= ~SMB_WHOAMI_GUEST;
3027 /* NOTE: 8 bytes for UID/GID, irrespective of native
3028 * platform size. This matches
3029 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3031 data_len = 4 /* flags */
3038 + 4 /* pad/reserved */
3039 + (conn->server_info->utok.ngroups * 8)
3041 + (conn->server_info->ptok->num_sids *
3045 SIVAL(pdata, 0, flags);
3046 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3048 (uint64_t)conn->server_info->utok.uid);
3049 SBIG_UINT(pdata, 16,
3050 (uint64_t)conn->server_info->utok.gid);
3053 if (data_len >= max_data_bytes) {
3054 /* Potential overflow, skip the GIDs and SIDs. */
3056 SIVAL(pdata, 24, 0); /* num_groups */
3057 SIVAL(pdata, 28, 0); /* num_sids */
3058 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3059 SIVAL(pdata, 36, 0); /* reserved */
3065 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3066 SIVAL(pdata, 28, conn->server_info->num_sids);
3068 /* We walk the SID list twice, but this call is fairly
3069 * infrequent, and I don't expect that it's performance
3070 * sensitive -- jpeach
3072 for (i = 0, sid_bytes = 0;
3073 i < conn->server_info->ptok->num_sids; ++i) {
3074 sid_bytes += ndr_size_dom_sid(
3075 &conn->server_info->ptok->user_sids[i],
3079 /* SID list byte count */
3080 SIVAL(pdata, 32, sid_bytes);
3082 /* 4 bytes pad/reserved - must be zero */
3083 SIVAL(pdata, 36, 0);
3087 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3088 SBIG_UINT(pdata, data_len,
3089 (uint64_t)conn->server_info->utok.groups[i]);
3095 i < conn->server_info->ptok->num_sids; ++i) {
3096 int sid_len = ndr_size_dom_sid(
3097 &conn->server_info->ptok->user_sids[i],
3100 sid_linearize(pdata + data_len, sid_len,
3101 &conn->server_info->ptok->user_sids[i]);
3102 data_len += sid_len;
3108 case SMB_MAC_QUERY_FS_INFO:
3110 * Thursby MAC extension... ONLY on NTFS filesystems
3111 * once we do streams then we don't need this
3113 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3115 SIVAL(pdata,84,0x100); /* Don't support mac... */
3120 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3125 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3128 DEBUG( 4, ( "%s info_level = %d\n",
3129 smb_fn_name(req->cmd), info_level) );
3134 /****************************************************************************
3135 Reply to a TRANS2_SETFSINFO (set filesystem info).
3136 ****************************************************************************/
3138 static void call_trans2setfsinfo(connection_struct *conn,
3139 struct smb_request *req,
3140 char **pparams, int total_params,
3141 char **ppdata, int total_data,
3142 unsigned int max_data_bytes)
3144 char *pdata = *ppdata;
3145 char *params = *pparams;
3148 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3151 if (total_params < 4) {
3152 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3154 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3158 info_level = SVAL(params,2);
3161 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3162 info_level != SMB_SET_CIFS_UNIX_INFO) {
3163 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3164 "info level (0x%x) on IPC$.\n",
3165 (unsigned int)info_level));
3166 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3171 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3172 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3173 DEBUG(0,("call_trans2setfsinfo: encryption required "
3174 "and info level 0x%x sent.\n",
3175 (unsigned int)info_level));
3176 exit_server_cleanly("encryption required "
3182 switch(info_level) {
3183 case SMB_SET_CIFS_UNIX_INFO:
3185 uint16 client_unix_major;
3186 uint16 client_unix_minor;
3187 uint32 client_unix_cap_low;
3188 uint32 client_unix_cap_high;
3190 if (!lp_unix_extensions()) {
3192 NT_STATUS_INVALID_LEVEL);
3196 /* There should be 12 bytes of capabilities set. */
3197 if (total_data < 8) {
3200 NT_STATUS_INVALID_PARAMETER);
3203 client_unix_major = SVAL(pdata,0);
3204 client_unix_minor = SVAL(pdata,2);
3205 client_unix_cap_low = IVAL(pdata,4);
3206 client_unix_cap_high = IVAL(pdata,8);
3207 /* Just print these values for now. */
3208 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3209 cap_low = 0x%x, cap_high = 0x%x\n",
3210 (unsigned int)client_unix_major,
3211 (unsigned int)client_unix_minor,
3212 (unsigned int)client_unix_cap_low,
3213 (unsigned int)client_unix_cap_high ));
3215 /* Here is where we must switch to posix pathname processing... */
3216 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3217 lp_set_posix_pathnames();
3218 mangle_change_to_posix();
3221 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3222 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3223 /* Client that knows how to do posix locks,
3224 * but not posix open/mkdir operations. Set a
3225 * default type for read/write checks. */
3227 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3233 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3236 size_t param_len = 0;
3237 size_t data_len = total_data;
3239 if (!lp_unix_extensions()) {
3242 NT_STATUS_INVALID_LEVEL);
3246 if (lp_smb_encrypt(SNUM(conn)) == false) {
3249 NT_STATUS_NOT_SUPPORTED);
3253 DEBUG( 4,("call_trans2setfsinfo: "
3254 "request transport encryption.\n"));
3256 status = srv_request_encryption_setup(conn,
3257 (unsigned char **)ppdata,
3259 (unsigned char **)pparams,
3262 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3263 !NT_STATUS_IS_OK(status)) {
3264 reply_nterror(req, status);
3268 send_trans2_replies(conn, req,
3275 if (NT_STATUS_IS_OK(status)) {
3276 /* Server-side transport
3277 * encryption is now *on*. */
3278 status = srv_encryption_start(conn);
3279 if (!NT_STATUS_IS_OK(status)) {
3280 exit_server_cleanly(
3281 "Failure in setting "
3282 "up encrypted transport");
3288 case SMB_FS_QUOTA_INFORMATION:
3290 files_struct *fsp = NULL;
3291 SMB_NTQUOTA_STRUCT quotas;
3293 ZERO_STRUCT(quotas);
3296 if ((conn->server_info->utok.uid != 0)
3297 ||!CAN_WRITE(conn)) {
3298 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3299 lp_servicename(SNUM(conn)),
3300 conn->server_info->unix_name));
3301 reply_doserror(req, ERRSRV, ERRaccess);
3305 /* note: normaly there're 48 bytes,
3306 * but we didn't use the last 6 bytes for now
3309 fsp = file_fsp(req, SVAL(params,0));
3311 if (!check_fsp_ntquota_handle(conn, req,
3313 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3315 req, NT_STATUS_INVALID_HANDLE);
3319 if (total_data < 42) {
3320 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3324 NT_STATUS_INVALID_PARAMETER);
3328 /* unknown_1 24 NULL bytes in pdata*/
3330 /* the soft quotas 8 bytes (uint64_t)*/
3331 quotas.softlim = (uint64_t)IVAL(pdata,24);
3332 #ifdef LARGE_SMB_OFF_T
3333 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3334 #else /* LARGE_SMB_OFF_T */
3335 if ((IVAL(pdata,28) != 0)&&
3336 ((quotas.softlim != 0xFFFFFFFF)||
3337 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3338 /* more than 32 bits? */
3341 NT_STATUS_INVALID_PARAMETER);
3344 #endif /* LARGE_SMB_OFF_T */
3346 /* the hard quotas 8 bytes (uint64_t)*/
3347 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3348 #ifdef LARGE_SMB_OFF_T
3349 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3350 #else /* LARGE_SMB_OFF_T */
3351 if ((IVAL(pdata,36) != 0)&&
3352 ((quotas.hardlim != 0xFFFFFFFF)||
3353 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3354 /* more than 32 bits? */
3357 NT_STATUS_INVALID_PARAMETER);
3360 #endif /* LARGE_SMB_OFF_T */
3362 /* quota_flags 2 bytes **/
3363 quotas.qflags = SVAL(pdata,40);
3365 /* unknown_2 6 NULL bytes follow*/
3367 /* now set the quotas */
3368 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3369 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3370 reply_doserror(req, ERRSRV, ERRerror);
3377 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3379 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3385 * sending this reply works fine,
3386 * but I'm not sure it's the same
3387 * like windows do...
3390 reply_outbuf(req, 10, 0);
3393 #if defined(HAVE_POSIX_ACLS)
3394 /****************************************************************************
3395 Utility function to count the number of entries in a POSIX acl.
3396 ****************************************************************************/
3398 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3400 unsigned int ace_count = 0;
3401 int entry_id = SMB_ACL_FIRST_ENTRY;
3402 SMB_ACL_ENTRY_T entry;
3404 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3406 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3407 entry_id = SMB_ACL_NEXT_ENTRY;
3414 /****************************************************************************
3415 Utility function to marshall a POSIX acl into wire format.
3416 ****************************************************************************/
3418 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3420 int entry_id = SMB_ACL_FIRST_ENTRY;
3421 SMB_ACL_ENTRY_T entry;
3423 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3424 SMB_ACL_TAG_T tagtype;
3425 SMB_ACL_PERMSET_T permset;
3426 unsigned char perms = 0;
3427 unsigned int own_grp;
3430 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3431 entry_id = SMB_ACL_NEXT_ENTRY;
3434 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3435 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3439 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3440 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3444 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3445 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3446 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3448 SCVAL(pdata,1,perms);
3451 case SMB_ACL_USER_OBJ:
3452 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3453 own_grp = (unsigned int)pst->st_uid;
3454 SIVAL(pdata,2,own_grp);
3459 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3461 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3464 own_grp = (unsigned int)*puid;
3465 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3466 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3467 SIVAL(pdata,2,own_grp);
3471 case SMB_ACL_GROUP_OBJ:
3472 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3473 own_grp = (unsigned int)pst->st_gid;
3474 SIVAL(pdata,2,own_grp);
3479 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3481 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3484 own_grp = (unsigned int)*pgid;
3485 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3486 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3487 SIVAL(pdata,2,own_grp);
3492 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3493 SIVAL(pdata,2,0xFFFFFFFF);
3494 SIVAL(pdata,6,0xFFFFFFFF);
3497 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3498 SIVAL(pdata,2,0xFFFFFFFF);
3499 SIVAL(pdata,6,0xFFFFFFFF);
3502 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3505 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3512 /****************************************************************************
3513 Store the FILE_UNIX_BASIC info.
3514 ****************************************************************************/
3516 static char *store_file_unix_basic(connection_struct *conn,
3519 const SMB_STRUCT_STAT *psbuf)
3521 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3522 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3524 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3527 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3530 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3531 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3532 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3535 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3539 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3543 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3546 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3550 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3554 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3557 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3561 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3568 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3569 * the chflags(2) (or equivalent) flags.
3571 * XXX: this really should be behind the VFS interface. To do this, we would
3572 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3573 * Each VFS module could then implement its own mapping as appropriate for the
3574 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3576 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3580 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3584 { UF_IMMUTABLE, EXT_IMMUTABLE },
3588 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3592 { UF_HIDDEN, EXT_HIDDEN },
3595 /* Do not remove. We need to guarantee that this array has at least one
3596 * entry to build on HP-UX.
3602 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3603 uint32 *smb_fflags, uint32 *smb_fmask)
3605 #ifdef HAVE_STAT_ST_FLAGS
3608 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3609 *smb_fmask |= info2_flags_map[i].smb_fflag;
3610 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3611 *smb_fflags |= info2_flags_map[i].smb_fflag;
3614 #endif /* HAVE_STAT_ST_FLAGS */
3617 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3618 const uint32 smb_fflags,
3619 const uint32 smb_fmask,
3622 #ifdef HAVE_STAT_ST_FLAGS
3623 uint32 max_fmask = 0;
3626 *stat_fflags = psbuf->st_flags;
3628 /* For each flags requested in smb_fmask, check the state of the
3629 * corresponding flag in smb_fflags and set or clear the matching
3633 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3634 max_fmask |= info2_flags_map[i].smb_fflag;
3635 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3636 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3637 *stat_fflags |= info2_flags_map[i].stat_fflag;
3639 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3644 /* If smb_fmask is asking to set any bits that are not supported by
3645 * our flag mappings, we should fail.
3647 if ((smb_fmask & max_fmask) != smb_fmask) {
3654 #endif /* HAVE_STAT_ST_FLAGS */
3658 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3659 * of file flags and birth (create) time.
3661 static char *store_file_unix_basic_info2(connection_struct *conn,
3664 const SMB_STRUCT_STAT *psbuf)
3666 uint32 file_flags = 0;
3667 uint32 flags_mask = 0;
3669 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3671 /* Create (birth) time 64 bit */
3672 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3675 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3676 SIVAL(pdata, 0, file_flags); /* flags */
3677 SIVAL(pdata, 4, flags_mask); /* mask */
3683 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3684 const struct stream_struct *streams,
3686 unsigned int max_data_bytes,
3687 unsigned int *data_size)
3690 unsigned int ofs = 0;
3692 for (i=0; i<num_streams; i++) {
3693 unsigned int next_offset;
3695 smb_ucs2_t *namebuf;
3697 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3698 streams[i].name, &namelen) ||
3701 return NT_STATUS_INVALID_PARAMETER;
3705 * name_buf is now null-terminated, we need to marshall as not
3711 if (ofs + 24 + namelen > max_data_bytes) {
3712 TALLOC_FREE(namebuf);
3713 return NT_STATUS_BUFFER_TOO_SMALL;
3716 SIVAL(data, ofs+4, namelen);
3717 SOFF_T(data, ofs+8, streams[i].size);
3718 SOFF_T(data, ofs+16, streams[i].alloc_size);
3719 memcpy(data+ofs+24, namebuf, namelen);
3720 TALLOC_FREE(namebuf);
3722 next_offset = ofs + 24 + namelen;
3724 if (i == num_streams-1) {
3725 SIVAL(data, ofs, 0);
3728 unsigned int align = ndr_align_size(next_offset, 8);
3730 if (next_offset + align > max_data_bytes) {
3731 return NT_STATUS_BUFFER_TOO_SMALL;
3734 memset(data+next_offset, 0, align);
3735 next_offset += align;
3737 SIVAL(data, ofs, next_offset - ofs);
3746 return NT_STATUS_OK;
3749 /****************************************************************************
3750 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3751 ****************************************************************************/
3753 static void call_trans2qpipeinfo(connection_struct *conn,
3754 struct smb_request *req,
3755 unsigned int tran_call,
3756 char **pparams, int total_params,
3757 char **ppdata, int total_data,
3758 unsigned int max_data_bytes)
3760 char *params = *pparams;
3761 char *pdata = *ppdata;
3762 unsigned int data_size = 0;
3763 unsigned int param_size = 2;
3768 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3772 if (total_params < 4) {
3773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3777 fsp = file_fsp(req, SVAL(params,0));
3778 if (!fsp_is_np(fsp)) {
3779 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3783 info_level = SVAL(params,2);
3785 *pparams = (char *)SMB_REALLOC(*pparams,2);
3786 if (*pparams == NULL) {
3787 reply_nterror(req, NT_STATUS_NO_MEMORY);
3792 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3793 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3794 if (*ppdata == NULL ) {
3795 reply_nterror(req, NT_STATUS_NO_MEMORY);
3800 switch (info_level) {
3801 case SMB_FILE_STANDARD_INFORMATION:
3803 SOFF_T(pdata,0,4096LL);
3810 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3814 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3820 /****************************************************************************
3821 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3822 file name or file id).
3823 ****************************************************************************/
3825 static void call_trans2qfilepathinfo(connection_struct *conn,
3826 struct smb_request *req,
3827 unsigned int tran_call,
3828 char **pparams, int total_params,
3829 char **ppdata, int total_data,
3830 unsigned int max_data_bytes)
3832 char *params = *pparams;
3833 char *pdata = *ppdata;
3834 char *dstart, *dend;
3838 SMB_OFF_T file_size=0;
3839 uint64_t allocation_size=0;
3840 unsigned int data_size = 0;
3841 unsigned int param_size = 2;
3842 SMB_STRUCT_STAT sbuf;
3843 char *dos_fname = NULL;
3849 bool delete_pending = False;
3851 time_t create_time, mtime, atime;
3852 struct timespec create_time_ts, mtime_ts, atime_ts;
3853 struct timespec write_time_ts;
3854 files_struct *fsp = NULL;
3855 struct file_id fileid;
3856 struct ea_list *ea_list = NULL;
3857 char *lock_data = NULL;
3858 bool ms_dfs_link = false;
3859 TALLOC_CTX *ctx = talloc_tos();
3862 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3867 ZERO_STRUCT(write_time_ts);
3869 if (tran_call == TRANSACT2_QFILEINFO) {
3870 if (total_params < 4) {
3871 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3876 call_trans2qpipeinfo(conn, req, tran_call,
3877 pparams, total_params,
3883 fsp = file_fsp(req, SVAL(params,0));
3884 info_level = SVAL(params,2);
3886 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3888 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3889 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3893 /* Initial check for valid fsp ptr. */
3894 if (!check_fsp_open(conn, req, fsp)) {
3898 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3900 reply_nterror(req, NT_STATUS_NO_MEMORY);
3904 if(fsp->fake_file_handle) {
3906 * This is actually for the QUOTA_FAKE_FILE --metze
3909 /* We know this name is ok, it's already passed the checks. */
3911 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3913 * This is actually a QFILEINFO on a directory
3914 * handle (returned from an NT SMB). NT5.0 seems
3915 * to do this call. JRA.
3918 if (INFO_LEVEL_IS_UNIX(info_level)) {
3919 /* Always do lstat for UNIX calls. */
3920 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3921 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3922 reply_unixerror(req,ERRDOS,ERRbadpath);
3925 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3926 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3927 reply_unixerror(req, ERRDOS, ERRbadpath);
3931 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3932 get_file_infos(fileid, &delete_pending, &write_time_ts);
3935 * Original code - this is an open file.
3937 if (!check_fsp(conn, req, fsp)) {
3941 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3942 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3943 reply_unixerror(req, ERRDOS, ERRbadfid);
3946 pos = fsp->fh->position_information;
3947 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3948 get_file_infos(fileid, &delete_pending, &write_time_ts);
3952 NTSTATUS status = NT_STATUS_OK;
3955 if (total_params < 7) {
3956 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3960 info_level = SVAL(params,0);
3962 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3964 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3965 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3969 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3971 STR_TERMINATE, &status);
3972 if (!NT_STATUS_IS_OK(status)) {
3973 reply_nterror(req, status);
3977 status = resolve_dfspath(ctx,
3979 req->flags2 & FLAGS2_DFS_PATHNAMES,
3982 if (!NT_STATUS_IS_OK(status)) {
3983 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3984 reply_botherror(req,
3985 NT_STATUS_PATH_NOT_COVERED,
3986 ERRSRV, ERRbadpath);
3988 reply_nterror(req, status);
3992 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3993 if (!NT_STATUS_IS_OK(status)) {
3994 reply_nterror(req, status);
3997 status = check_name(conn, fname);
3998 if (!NT_STATUS_IS_OK(status)) {
3999 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
4000 reply_nterror(req, status);
4004 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4005 && is_ntfs_stream_name(fname)) {
4007 SMB_STRUCT_STAT bsbuf;
4009 status = split_ntfs_stream_name(talloc_tos(), fname,
4011 if (!NT_STATUS_IS_OK(status)) {
4012 DEBUG(10, ("create_file_unixpath: "
4013 "split_ntfs_stream_name failed: %s\n",
4014 nt_errstr(status)));
4015 reply_nterror(req, status);
4019 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4021 if (INFO_LEVEL_IS_UNIX(info_level)) {
4022 /* Always do lstat for UNIX calls. */
4023 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4024 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4025 reply_unixerror(req,ERRDOS,ERRbadpath);
4029 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4030 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4031 reply_unixerror(req,ERRDOS,ERRbadpath);
4036 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4037 get_file_infos(fileid, &delete_pending, NULL);
4038 if (delete_pending) {
4039 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4044 if (INFO_LEVEL_IS_UNIX(info_level)) {
4045 /* Always do lstat for UNIX calls. */
4046 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4047 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4048 reply_unixerror(req, ERRDOS, ERRbadpath);
4052 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4053 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4056 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4057 reply_unixerror(req, ERRDOS, ERRbadpath);
4062 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4063 get_file_infos(fileid, &delete_pending, &write_time_ts);
4064 if (delete_pending) {
4065 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4070 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4071 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4075 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4076 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4078 p = strrchr_m(fname,'/');
4085 mode = dos_mode_msdfs(conn,fname,&sbuf);
4087 mode = dos_mode(conn,fname,&sbuf);
4090 mode = FILE_ATTRIBUTE_NORMAL;
4092 nlink = sbuf.st_nlink;
4094 if (nlink && (mode&aDIR)) {
4098 if ((nlink > 0) && delete_pending) {
4102 fullpathname = fname;
4104 file_size = get_file_size(sbuf);
4106 /* Pull out any data sent here before we realloc. */
4107 switch (info_level) {
4108 case SMB_INFO_QUERY_EAS_FROM_LIST:
4110 /* Pull any EA list from the data portion. */
4113 if (total_data < 4) {
4115 req, NT_STATUS_INVALID_PARAMETER);
4118 ea_size = IVAL(pdata,0);
4120 if (total_data > 0 && ea_size != total_data) {
4121 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4122 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4124 req, NT_STATUS_INVALID_PARAMETER);
4128 if (!lp_ea_support(SNUM(conn))) {
4129 reply_doserror(req, ERRDOS,
4130 ERReasnotsupported);
4134 /* Pull out the list of names. */
4135 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4138 req, NT_STATUS_INVALID_PARAMETER);
4144 case SMB_QUERY_POSIX_LOCK:
4146 if (fsp == NULL || fsp->fh->fd == -1) {
4147 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4151 if (total_data != POSIX_LOCK_DATA_SIZE) {
4153 req, NT_STATUS_INVALID_PARAMETER);
4157 /* Copy the lock range data. */
4158 lock_data = (char *)TALLOC_MEMDUP(
4159 ctx, pdata, total_data);
4161 reply_nterror(req, NT_STATUS_NO_MEMORY);
4169 *pparams = (char *)SMB_REALLOC(*pparams,2);
4170 if (*pparams == NULL) {
4171 reply_nterror(req, NT_STATUS_NO_MEMORY);
4176 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4177 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4178 if (*ppdata == NULL ) {
4179 reply_nterror(req, NT_STATUS_NO_MEMORY);
4184 dend = dstart + data_size - 1;
4186 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4187 mtime_ts = get_mtimespec(&sbuf);
4188 atime_ts = get_atimespec(&sbuf);
4190 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4193 /* Do we have this path open ? */
4195 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4196 fsp1 = file_find_di_first(fileid);
4197 if (fsp1 && fsp1->initial_allocation_size) {
4198 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4202 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4203 mtime_ts = write_time_ts;
4206 if (lp_dos_filetime_resolution(SNUM(conn))) {
4207 dos_filetime_timespec(&create_time_ts);
4208 dos_filetime_timespec(&mtime_ts);
4209 dos_filetime_timespec(&atime_ts);
4212 create_time = convert_timespec_to_time_t(create_time_ts);
4213 mtime = convert_timespec_to_time_t(mtime_ts);
4214 atime = convert_timespec_to_time_t(atime_ts);
4216 /* NT expects the name to be in an exact form of the *full*
4217 filename. See the trans2 torture test */
4218 if (ISDOT(base_name)) {
4219 dos_fname = talloc_strdup(ctx, "\\");
4221 reply_nterror(req, NT_STATUS_NO_MEMORY);
4225 dos_fname = talloc_asprintf(ctx,
4229 reply_nterror(req, NT_STATUS_NO_MEMORY);
4232 string_replace(dos_fname, '/', '\\');
4235 switch (info_level) {
4236 case SMB_INFO_STANDARD:
4237 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4239 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4240 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4241 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4242 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4243 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4244 SSVAL(pdata,l1_attrFile,mode);
4247 case SMB_INFO_QUERY_EA_SIZE:
4249 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4250 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4252 srv_put_dos_date2(pdata,0,create_time);
4253 srv_put_dos_date2(pdata,4,atime);
4254 srv_put_dos_date2(pdata,8,mtime); /* write time */
4255 SIVAL(pdata,12,(uint32)file_size);
4256 SIVAL(pdata,16,(uint32)allocation_size);
4257 SSVAL(pdata,20,mode);
4258 SIVAL(pdata,22,ea_size);
4262 case SMB_INFO_IS_NAME_VALID:
4263 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4264 if (tran_call == TRANSACT2_QFILEINFO) {
4265 /* os/2 needs this ? really ?*/
4266 reply_doserror(req, ERRDOS, ERRbadfunc);
4273 case SMB_INFO_QUERY_EAS_FROM_LIST:
4275 size_t total_ea_len = 0;
4276 struct ea_list *ea_file_list = NULL;
4278 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4280 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4281 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4283 if (!ea_list || (total_ea_len > data_size)) {
4285 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4289 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4293 case SMB_INFO_QUERY_ALL_EAS:
4295 /* We have data_size bytes to put EA's into. */
4296 size_t total_ea_len = 0;
4298 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4300 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4301 if (!ea_list || (total_ea_len > data_size)) {
4303 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4307 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4311 case SMB_FILE_BASIC_INFORMATION:
4312 case SMB_QUERY_FILE_BASIC_INFO:
4314 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4315 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4316 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4318 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4322 put_long_date_timespec(pdata,create_time_ts);
4323 put_long_date_timespec(pdata+8,atime_ts);
4324 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4325 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4326 SIVAL(pdata,32,mode);
4328 DEBUG(5,("SMB_QFBI - "));
4329 DEBUG(5,("create: %s ", ctime(&create_time)));
4330 DEBUG(5,("access: %s ", ctime(&atime)));
4331 DEBUG(5,("write: %s ", ctime(&mtime)));
4332 DEBUG(5,("change: %s ", ctime(&mtime)));
4333 DEBUG(5,("mode: %x\n", mode));
4336 case SMB_FILE_STANDARD_INFORMATION:
4337 case SMB_QUERY_FILE_STANDARD_INFO:
4339 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4341 SOFF_T(pdata,0,allocation_size);
4342 SOFF_T(pdata,8,file_size);
4343 SIVAL(pdata,16,nlink);
4344 SCVAL(pdata,20,delete_pending?1:0);
4345 SCVAL(pdata,21,(mode&aDIR)?1:0);
4346 SSVAL(pdata,22,0); /* Padding. */
4349 case SMB_FILE_EA_INFORMATION:
4350 case SMB_QUERY_FILE_EA_INFO:
4352 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4353 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4355 SIVAL(pdata,0,ea_size);
4359 /* Get the 8.3 name - used if NT SMB was negotiated. */
4360 case SMB_QUERY_FILE_ALT_NAME_INFO:
4361 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4363 char mangled_name[13];
4364 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4365 if (!name_to_8_3(base_name,mangled_name,
4366 True,conn->params)) {
4369 NT_STATUS_NO_MEMORY);
4371 len = srvstr_push(dstart, req->flags2,
4372 pdata+4, mangled_name,
4373 PTR_DIFF(dend, pdata+4),
4375 data_size = 4 + len;
4380 case SMB_QUERY_FILE_NAME_INFO:
4382 this must be *exactly* right for ACLs on mapped drives to work
4384 len = srvstr_push(dstart, req->flags2,
4386 PTR_DIFF(dend, pdata+4),
4388 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4389 data_size = 4 + len;
4393 case SMB_FILE_ALLOCATION_INFORMATION:
4394 case SMB_QUERY_FILE_ALLOCATION_INFO:
4395 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4397 SOFF_T(pdata,0,allocation_size);
4400 case SMB_FILE_END_OF_FILE_INFORMATION:
4401 case SMB_QUERY_FILE_END_OF_FILEINFO:
4402 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4404 SOFF_T(pdata,0,file_size);
4407 case SMB_QUERY_FILE_ALL_INFO:
4408 case SMB_FILE_ALL_INFORMATION:
4410 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4411 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4412 put_long_date_timespec(pdata,create_time_ts);
4413 put_long_date_timespec(pdata+8,atime_ts);
4414 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4415 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4416 SIVAL(pdata,32,mode);
4417 SIVAL(pdata,36,0); /* padding. */
4419 SOFF_T(pdata,0,allocation_size);
4420 SOFF_T(pdata,8,file_size);
4421 SIVAL(pdata,16,nlink);
4422 SCVAL(pdata,20,delete_pending);
4423 SCVAL(pdata,21,(mode&aDIR)?1:0);
4426 SIVAL(pdata,0,ea_size);
4427 pdata += 4; /* EA info */
4428 len = srvstr_push(dstart, req->flags2,
4430 PTR_DIFF(dend, pdata+4),
4434 data_size = PTR_DIFF(pdata,(*ppdata));
4437 case SMB_FILE_INTERNAL_INFORMATION:
4438 /* This should be an index number - looks like
4441 I think this causes us to fail the IFSKIT
4442 BasicFileInformationTest. -tpot */
4444 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4445 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4446 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4450 case SMB_FILE_ACCESS_INFORMATION:
4451 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4453 SIVAL(pdata,0,fsp->access_mask);
4455 /* GENERIC_EXECUTE mapping from Windows */
4456 SIVAL(pdata,0,0x12019F);
4461 case SMB_FILE_NAME_INFORMATION:
4462 /* Pathname with leading '\'. */
4465 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4466 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4467 SIVAL(pdata,0,byte_len);
4468 data_size = 4 + byte_len;
4472 case SMB_FILE_DISPOSITION_INFORMATION:
4473 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4475 SCVAL(pdata,0,delete_pending);
4478 case SMB_FILE_POSITION_INFORMATION:
4479 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4481 SOFF_T(pdata,0,pos);
4484 case SMB_FILE_MODE_INFORMATION:
4485 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4486 SIVAL(pdata,0,mode);
4490 case SMB_FILE_ALIGNMENT_INFORMATION:
4491 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4492 SIVAL(pdata,0,0); /* No alignment needed. */
4497 * NT4 server just returns "invalid query" to this - if we try
4498 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4501 /* The first statement above is false - verified using Thursby
4502 * client against NT4 -- gcolley.
4504 case SMB_QUERY_FILE_STREAM_INFO:
4505 case SMB_FILE_STREAM_INFORMATION: {
4506 unsigned int num_streams;
4507 struct stream_struct *streams;
4510 DEBUG(10,("call_trans2qfilepathinfo: "
4511 "SMB_FILE_STREAM_INFORMATION\n"));
4513 status = SMB_VFS_STREAMINFO(
4514 conn, fsp, fname, talloc_tos(),
4515 &num_streams, &streams);
4517 if (!NT_STATUS_IS_OK(status)) {
4518 DEBUG(10, ("could not get stream info: %s\n",
4519 nt_errstr(status)));
4520 reply_nterror(req, status);
4524 status = marshall_stream_info(num_streams, streams,
4525 pdata, max_data_bytes,
4528 if (!NT_STATUS_IS_OK(status)) {
4529 DEBUG(10, ("marshall_stream_info failed: %s\n",
4530 nt_errstr(status)));
4531 reply_nterror(req, status);
4535 TALLOC_FREE(streams);
4539 case SMB_QUERY_COMPRESSION_INFO:
4540 case SMB_FILE_COMPRESSION_INFORMATION:
4541 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4542 SOFF_T(pdata,0,file_size);
4543 SIVAL(pdata,8,0); /* ??? */
4544 SIVAL(pdata,12,0); /* ??? */
4548 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4549 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4550 put_long_date_timespec(pdata,create_time_ts);
4551 put_long_date_timespec(pdata+8,atime_ts);
4552 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4553 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4554 SOFF_T(pdata,32,allocation_size);
4555 SOFF_T(pdata,40,file_size);
4556 SIVAL(pdata,48,mode);
4557 SIVAL(pdata,52,0); /* ??? */
4561 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4562 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4563 SIVAL(pdata,0,mode);
4569 * CIFS UNIX Extensions.
4572 case SMB_QUERY_FILE_UNIX_BASIC:
4574 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4575 data_size = PTR_DIFF(pdata,(*ppdata));
4579 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4581 for (i=0; i<100; i++)
4582 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4588 case SMB_QUERY_FILE_UNIX_INFO2:
4590 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4591 data_size = PTR_DIFF(pdata,(*ppdata));
4595 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4597 for (i=0; i<100; i++)
4598 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4604 case SMB_QUERY_FILE_UNIX_LINK:
4606 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4609 reply_nterror(req, NT_STATUS_NO_MEMORY);
4613 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4615 if(!S_ISLNK(sbuf.st_mode)) {
4616 reply_unixerror(req, ERRSRV,
4621 reply_unixerror(req, ERRDOS, ERRbadlink);
4624 len = SMB_VFS_READLINK(conn,fullpathname,
4627 reply_unixerror(req, ERRDOS,
4632 len = srvstr_push(dstart, req->flags2,
4634 PTR_DIFF(dend, pdata),
4637 data_size = PTR_DIFF(pdata,(*ppdata));
4642 #if defined(HAVE_POSIX_ACLS)
4643 case SMB_QUERY_POSIX_ACL:
4645 SMB_ACL_T file_acl = NULL;
4646 SMB_ACL_T def_acl = NULL;
4647 uint16 num_file_acls = 0;
4648 uint16 num_def_acls = 0;
4650 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4651 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4653 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4656 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4657 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4661 NT_STATUS_NOT_IMPLEMENTED);
4665 if (S_ISDIR(sbuf.st_mode)) {
4666 if (fsp && fsp->is_directory) {
4667 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4669 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4671 def_acl = free_empty_sys_acl(conn, def_acl);
4674 num_file_acls = count_acl_entries(conn, file_acl);
4675 num_def_acls = count_acl_entries(conn, def_acl);
4677 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4678 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4680 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4681 SMB_POSIX_ACL_HEADER_SIZE) ));
4683 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4686 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4690 NT_STATUS_BUFFER_TOO_SMALL);
4694 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4695 SSVAL(pdata,2,num_file_acls);
4696 SSVAL(pdata,4,num_def_acls);
4697 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4699 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4702 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4705 req, NT_STATUS_INTERNAL_ERROR);
4708 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4710 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4713 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4717 NT_STATUS_INTERNAL_ERROR);
4722 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4725 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4727 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4733 case SMB_QUERY_POSIX_LOCK:
4735 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4739 enum brl_type lock_type;
4741 if (total_data != POSIX_LOCK_DATA_SIZE) {
4743 req, NT_STATUS_INVALID_PARAMETER);
4747 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4748 case POSIX_LOCK_TYPE_READ:
4749 lock_type = READ_LOCK;
4751 case POSIX_LOCK_TYPE_WRITE:
4752 lock_type = WRITE_LOCK;
4754 case POSIX_LOCK_TYPE_UNLOCK:
4756 /* There's no point in asking for an unlock... */
4759 NT_STATUS_INVALID_PARAMETER);
4763 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4764 #if defined(HAVE_LONGLONG)
4765 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4766 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4767 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4768 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4769 #else /* HAVE_LONGLONG */
4770 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4771 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4772 #endif /* HAVE_LONGLONG */
4774 status = query_lock(fsp,
4781 if (ERROR_WAS_LOCK_DENIED(status)) {
4782 /* Here we need to report who has it locked... */
4783 data_size = POSIX_LOCK_DATA_SIZE;
4785 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4786 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4787 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4788 #if defined(HAVE_LONGLONG)
4789 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4790 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4791 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4792 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4793 #else /* HAVE_LONGLONG */
4794 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4795 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4796 #endif /* HAVE_LONGLONG */
4798 } else if (NT_STATUS_IS_OK(status)) {
4799 /* For success we just return a copy of what we sent
4800 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4801 data_size = POSIX_LOCK_DATA_SIZE;
4802 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4803 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4805 reply_nterror(req, status);
4812 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4816 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4822 /****************************************************************************
4823 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4825 ****************************************************************************/
4827 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4828 connection_struct *conn,
4829 const char *oldname_in,
4830 const char *newname_in)
4832 SMB_STRUCT_STAT sbuf1, sbuf2;
4833 char *last_component_oldname = NULL;
4834 char *last_component_newname = NULL;
4835 char *oldname = NULL;
4836 char *newname = NULL;
4837 NTSTATUS status = NT_STATUS_OK;
4842 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4843 &last_component_oldname, &sbuf1);
4844 if (!NT_STATUS_IS_OK(status)) {
4848 status = check_name(conn, oldname);
4849 if (!NT_STATUS_IS_OK(status)) {
4853 /* source must already exist. */
4854 if (!VALID_STAT(sbuf1)) {
4855 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4858 status = unix_convert(ctx, conn, newname_in, False, &newname,
4859 &last_component_newname, &sbuf2);
4860 if (!NT_STATUS_IS_OK(status)) {
4864 status = check_name(conn, newname);
4865 if (!NT_STATUS_IS_OK(status)) {
4869 /* Disallow if newname already exists. */
4870 if (VALID_STAT(sbuf2)) {
4871 return NT_STATUS_OBJECT_NAME_COLLISION;
4874 /* No links from a directory. */
4875 if (S_ISDIR(sbuf1.st_mode)) {
4876 return NT_STATUS_FILE_IS_A_DIRECTORY;
4879 /* Ensure this is within the share. */
4880 status = check_reduced_name(conn, oldname);
4881 if (!NT_STATUS_IS_OK(status)) {
4885 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4887 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4888 status = map_nt_error_from_unix(errno);
4889 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4890 nt_errstr(status), newname, oldname));
4896 /****************************************************************************
4897 Deal with setting the time from any of the setfilepathinfo functions.
4898 ****************************************************************************/
4900 NTSTATUS smb_set_file_time(connection_struct *conn,
4903 const SMB_STRUCT_STAT *psbuf,
4904 struct timespec ts[2],
4905 bool setting_write_time)
4908 FILE_NOTIFY_CHANGE_LAST_ACCESS
4909 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4911 if (!VALID_STAT(*psbuf)) {
4912 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4915 /* get some defaults (no modifications) if any info is zero or -1. */
4916 if (null_timespec(ts[0])) {
4917 ts[0] = get_atimespec(psbuf);
4918 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4921 if (null_timespec(ts[1])) {
4922 ts[1] = get_mtimespec(psbuf);
4923 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4926 if (!setting_write_time) {
4927 /* ts[1] comes from change time, not write time. */
4928 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4931 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4932 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4935 * Try and set the times of this file if
4936 * they are different from the current values.
4940 struct timespec mts = get_mtimespec(psbuf);
4941 struct timespec ats = get_atimespec(psbuf);
4942 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4943 return NT_STATUS_OK;
4947 if (setting_write_time) {
4949 * This was a setfileinfo on an open file.
4950 * NT does this a lot. We also need to
4951 * set the time here, as it can be read by
4952 * FindFirst/FindNext and with the patch for bug #2045
4953 * in smbd/fileio.c it ensures that this timestamp is
4954 * kept sticky even after a write. We save the request
4955 * away and will set it on file close and after a write. JRA.
4958 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4959 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4962 if (fsp->base_fsp) {
4963 set_sticky_write_time_fsp(fsp->base_fsp, ts[1]);
4965 set_sticky_write_time_fsp(fsp, ts[1]);
4968 set_sticky_write_time_path(conn, fname,
4969 vfs_file_id_from_sbuf(conn, psbuf),
4974 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4976 if (fsp && fsp->base_fsp) {
4977 fname = fsp->base_fsp->fsp_name;
4980 if(file_ntimes(conn, fname, ts)!=0) {
4981 return map_nt_error_from_unix(errno);
4983 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4985 return NT_STATUS_OK;
4988 /****************************************************************************
4989 Deal with setting the dosmode from any of the setfilepathinfo functions.
4990 ****************************************************************************/
4992 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4994 SMB_STRUCT_STAT *psbuf,
4997 if (!VALID_STAT(*psbuf)) {
4998 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5002 if (S_ISDIR(psbuf->st_mode)) {
5009 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5011 /* check the mode isn't different, before changing it */
5012 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5014 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5015 fname, (unsigned int)dosmode ));
5017 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5018 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5019 fname, strerror(errno)));
5020 return map_nt_error_from_unix(errno);
5023 return NT_STATUS_OK;
5026 /****************************************************************************
5027 Deal with setting the size from any of the setfilepathinfo functions.
5028 ****************************************************************************/
5030 static NTSTATUS smb_set_file_size(connection_struct *conn,
5031 struct smb_request *req,
5034 SMB_STRUCT_STAT *psbuf,
5037 NTSTATUS status = NT_STATUS_OK;
5038 files_struct *new_fsp = NULL;
5040 if (!VALID_STAT(*psbuf)) {
5041 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5044 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5046 if (size == get_file_size(*psbuf)) {
5047 return NT_STATUS_OK;
5050 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5051 fname, (double)size ));
5053 if (fsp && fsp->fh->fd != -1) {
5054 /* Handle based call. */
5055 if (vfs_set_filelen(fsp, size) == -1) {
5056 return map_nt_error_from_unix(errno);
5058 trigger_write_time_update_immediate(fsp);
5059 return NT_STATUS_OK;
5062 status = open_file_ntcreate(conn, req, fname, psbuf,
5063 FILE_WRITE_ATTRIBUTES,
5064 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5067 FILE_ATTRIBUTE_NORMAL,
5068 FORCE_OPLOCK_BREAK_TO_NONE,
5071 if (!NT_STATUS_IS_OK(status)) {
5072 /* NB. We check for open_was_deferred in the caller. */
5076 if (vfs_set_filelen(new_fsp, size) == -1) {
5077 status = map_nt_error_from_unix(errno);
5078 close_file(req, new_fsp,NORMAL_CLOSE);
5082 trigger_write_time_update_immediate(new_fsp);
5083 close_file(req, new_fsp,NORMAL_CLOSE);
5084 return NT_STATUS_OK;
5087 /****************************************************************************
5088 Deal with SMB_INFO_SET_EA.
5089 ****************************************************************************/
5091 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5097 struct ea_list *ea_list = NULL;
5098 TALLOC_CTX *ctx = NULL;
5099 NTSTATUS status = NT_STATUS_OK;
5101 if (total_data < 10) {
5103 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5104 length. They seem to have no effect. Bug #3212. JRA */
5106 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5107 /* We're done. We only get EA info in this call. */
5108 return NT_STATUS_OK;
5111 return NT_STATUS_INVALID_PARAMETER;
5114 if (IVAL(pdata,0) > total_data) {
5115 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5116 IVAL(pdata,0), (unsigned int)total_data));
5117 return NT_STATUS_INVALID_PARAMETER;
5121 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5123 return NT_STATUS_INVALID_PARAMETER;
5125 status = set_ea(conn, fsp, fname, ea_list);
5130 /****************************************************************************
5131 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5132 ****************************************************************************/
5134 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5139 SMB_STRUCT_STAT *psbuf)
5141 NTSTATUS status = NT_STATUS_OK;
5142 bool delete_on_close;
5145 if (total_data < 1) {
5146 return NT_STATUS_INVALID_PARAMETER;
5150 return NT_STATUS_INVALID_HANDLE;
5153 delete_on_close = (CVAL(pdata,0) ? True : False);
5154 dosmode = dos_mode(conn, fname, psbuf);
5156 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5157 "delete_on_close = %u\n",
5159 (unsigned int)dosmode,
5160 (unsigned int)delete_on_close ));
5162 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5164 if (!NT_STATUS_IS_OK(status)) {
5168 /* The set is across all open files on this dev/inode pair. */
5169 if (!set_delete_on_close(fsp, delete_on_close,
5170 &conn->server_info->utok)) {
5171 return NT_STATUS_ACCESS_DENIED;
5173 return NT_STATUS_OK;
5176 /****************************************************************************
5177 Deal with SMB_FILE_POSITION_INFORMATION.
5178 ****************************************************************************/
5180 static NTSTATUS smb_file_position_information(connection_struct *conn,
5185 uint64_t position_information;
5187 if (total_data < 8) {
5188 return NT_STATUS_INVALID_PARAMETER;
5192 /* Ignore on pathname based set. */
5193 return NT_STATUS_OK;
5196 position_information = (uint64_t)IVAL(pdata,0);
5197 #ifdef LARGE_SMB_OFF_T
5198 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5199 #else /* LARGE_SMB_OFF_T */
5200 if (IVAL(pdata,4) != 0) {
5201 /* more than 32 bits? */
5202 return NT_STATUS_INVALID_PARAMETER;
5204 #endif /* LARGE_SMB_OFF_T */
5206 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5207 fsp->fsp_name, (double)position_information ));
5208 fsp->fh->position_information = position_information;
5209 return NT_STATUS_OK;
5212 /****************************************************************************
5213 Deal with SMB_FILE_MODE_INFORMATION.
5214 ****************************************************************************/
5216 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5222 if (total_data < 4) {
5223 return NT_STATUS_INVALID_PARAMETER;
5225 mode = IVAL(pdata,0);
5226 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5227 return NT_STATUS_INVALID_PARAMETER;
5229 return NT_STATUS_OK;
5232 /****************************************************************************
5233 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5234 ****************************************************************************/
5236 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5237 struct smb_request *req,
5242 char *link_target = NULL;
5243 const char *newname = fname;
5244 NTSTATUS status = NT_STATUS_OK;
5245 TALLOC_CTX *ctx = talloc_tos();
5247 /* Set a symbolic link. */
5248 /* Don't allow this if follow links is false. */
5250 if (total_data == 0) {
5251 return NT_STATUS_INVALID_PARAMETER;
5254 if (!lp_symlinks(SNUM(conn))) {
5255 return NT_STATUS_ACCESS_DENIED;
5258 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5259 total_data, STR_TERMINATE);
5262 return NT_STATUS_INVALID_PARAMETER;
5265 /* !widelinks forces the target path to be within the share. */
5266 /* This means we can interpret the target as a pathname. */
5267 if (!lp_widelinks(SNUM(conn))) {
5268 char *rel_name = NULL;
5269 char *last_dirp = NULL;
5271 if (*link_target == '/') {
5272 /* No absolute paths allowed. */
5273 return NT_STATUS_ACCESS_DENIED;
5275 rel_name = talloc_strdup(ctx,newname);
5277 return NT_STATUS_NO_MEMORY;
5279 last_dirp = strrchr_m(rel_name, '/');
5281 last_dirp[1] = '\0';
5283 rel_name = talloc_strdup(ctx,"./");
5285 return NT_STATUS_NO_MEMORY;
5288 rel_name = talloc_asprintf_append(rel_name,
5292 return NT_STATUS_NO_MEMORY;
5295 status = check_name(conn, rel_name);
5296 if (!NT_STATUS_IS_OK(status)) {
5301 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5302 newname, link_target ));
5304 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5305 return map_nt_error_from_unix(errno);
5308 return NT_STATUS_OK;
5311 /****************************************************************************
5312 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5313 ****************************************************************************/
5315 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5316 struct smb_request *req,
5317 const char *pdata, int total_data,
5320 char *oldname = NULL;
5321 TALLOC_CTX *ctx = talloc_tos();
5322 NTSTATUS status = NT_STATUS_OK;
5324 /* Set a hard link. */
5325 if (total_data == 0) {
5326 return NT_STATUS_INVALID_PARAMETER;
5329 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5330 total_data, STR_TERMINATE, &status);
5331 if (!NT_STATUS_IS_OK(status)) {
5335 status = resolve_dfspath(ctx, conn,
5336 req->flags2 & FLAGS2_DFS_PATHNAMES,
5339 if (!NT_STATUS_IS_OK(status)) {
5343 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5346 return hardlink_internals(ctx, conn, oldname, fname);
5349 /****************************************************************************
5350 Deal with SMB_FILE_RENAME_INFORMATION.
5351 ****************************************************************************/
5353 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5354 struct smb_request *req,
5363 char *newname = NULL;
5364 char *base_name = NULL;
5365 bool dest_has_wcard = False;
5366 NTSTATUS status = NT_STATUS_OK;
5368 TALLOC_CTX *ctx = talloc_tos();
5370 if (total_data < 13) {
5371 return NT_STATUS_INVALID_PARAMETER;
5374 overwrite = (CVAL(pdata,0) ? True : False);
5375 root_fid = IVAL(pdata,4);
5376 len = IVAL(pdata,8);
5378 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5379 return NT_STATUS_INVALID_PARAMETER;
5382 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5385 if (!NT_STATUS_IS_OK(status)) {
5389 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5392 status = resolve_dfspath_wcard(ctx, conn,
5393 req->flags2 & FLAGS2_DFS_PATHNAMES,
5397 if (!NT_STATUS_IS_OK(status)) {
5401 /* Check the new name has no '/' characters. */
5402 if (strchr_m(newname, '/')) {
5403 return NT_STATUS_NOT_SUPPORTED;
5406 if (fsp && fsp->base_fsp) {
5407 if (newname[0] != ':') {
5408 return NT_STATUS_NOT_SUPPORTED;
5410 base_name = talloc_asprintf(ctx, "%s%s",
5411 fsp->base_fsp->fsp_name,
5414 return NT_STATUS_NO_MEMORY;
5417 if (is_ntfs_stream_name(newname)) {
5418 return NT_STATUS_NOT_SUPPORTED;
5421 /* Create the base directory. */
5422 base_name = talloc_strdup(ctx, fname);
5424 return NT_STATUS_NO_MEMORY;
5426 p = strrchr_m(base_name, '/');
5430 base_name = talloc_strdup(ctx, "./");
5432 return NT_STATUS_NO_MEMORY;
5435 /* Append the new name. */
5436 base_name = talloc_asprintf_append(base_name,
5440 return NT_STATUS_NO_MEMORY;
5445 SMB_STRUCT_STAT sbuf;
5446 char *newname_last_component = NULL;
5450 status = unix_convert(ctx, conn, newname, False,
5452 &newname_last_component,
5455 /* If an error we expect this to be
5456 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5458 if (!NT_STATUS_IS_OK(status)
5459 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5464 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5465 fsp->fnum, fsp->fsp_name, base_name ));
5466 status = rename_internals_fsp(conn, fsp, base_name,
5467 newname_last_component, 0,
5470 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5471 fname, base_name ));
5472 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5473 overwrite, False, dest_has_wcard,
5474 FILE_WRITE_ATTRIBUTES);
5480 /****************************************************************************
5481 Deal with SMB_SET_POSIX_ACL.
5482 ****************************************************************************/
5484 #if defined(HAVE_POSIX_ACLS)
5485 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5490 SMB_STRUCT_STAT *psbuf)
5492 uint16 posix_acl_version;
5493 uint16 num_file_acls;
5494 uint16 num_def_acls;
5495 bool valid_file_acls = True;
5496 bool valid_def_acls = True;
5498 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5499 return NT_STATUS_INVALID_PARAMETER;
5501 posix_acl_version = SVAL(pdata,0);
5502 num_file_acls = SVAL(pdata,2);
5503 num_def_acls = SVAL(pdata,4);
5505 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5506 valid_file_acls = False;
5510 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5511 valid_def_acls = False;
5515 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5516 return NT_STATUS_INVALID_PARAMETER;
5519 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5520 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5521 return NT_STATUS_INVALID_PARAMETER;
5524 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5525 fname ? fname : fsp->fsp_name,
5526 (unsigned int)num_file_acls,
5527 (unsigned int)num_def_acls));
5529 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5530 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5531 return map_nt_error_from_unix(errno);
5534 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5535 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5536 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5537 return map_nt_error_from_unix(errno);
5539 return NT_STATUS_OK;
5543 /****************************************************************************
5544 Deal with SMB_SET_POSIX_LOCK.
5545 ****************************************************************************/
5547 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5548 struct smb_request *req,
5556 bool blocking_lock = False;
5557 enum brl_type lock_type;
5559 NTSTATUS status = NT_STATUS_OK;
5561 if (fsp == NULL || fsp->fh->fd == -1) {
5562 return NT_STATUS_INVALID_HANDLE;
5565 if (total_data != POSIX_LOCK_DATA_SIZE) {
5566 return NT_STATUS_INVALID_PARAMETER;
5569 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5570 case POSIX_LOCK_TYPE_READ:
5571 lock_type = READ_LOCK;
5573 case POSIX_LOCK_TYPE_WRITE:
5574 /* Return the right POSIX-mappable error code for files opened read-only. */
5575 if (!fsp->can_write) {
5576 return NT_STATUS_INVALID_HANDLE;
5578 lock_type = WRITE_LOCK;
5580 case POSIX_LOCK_TYPE_UNLOCK:
5581 lock_type = UNLOCK_LOCK;
5584 return NT_STATUS_INVALID_PARAMETER;
5587 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5588 blocking_lock = False;
5589 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5590 blocking_lock = True;
5592 return NT_STATUS_INVALID_PARAMETER;
5595 if (!lp_blocking_locks(SNUM(conn))) {
5596 blocking_lock = False;
5599 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5600 #if defined(HAVE_LONGLONG)
5601 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5602 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5603 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5604 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5605 #else /* HAVE_LONGLONG */
5606 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5607 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5608 #endif /* HAVE_LONGLONG */
5610 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5611 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5613 (unsigned int)lock_type,
5614 (unsigned int)lock_pid,
5618 if (lock_type == UNLOCK_LOCK) {
5619 status = do_unlock(smbd_messaging_context(),
5626 uint32 block_smbpid;
5628 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5639 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5641 * A blocking lock was requested. Package up
5642 * this smb into a queued request and push it
5643 * onto the blocking lock queue.
5645 if(push_blocking_lock_request(br_lck,
5648 -1, /* infinite timeout. */
5656 TALLOC_FREE(br_lck);
5660 TALLOC_FREE(br_lck);
5666 /****************************************************************************
5667 Deal with SMB_INFO_STANDARD.
5668 ****************************************************************************/
5670 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5675 const SMB_STRUCT_STAT *psbuf)
5677 struct timespec ts[2];
5679 if (total_data < 12) {
5680 return NT_STATUS_INVALID_PARAMETER;
5684 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5686 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5688 DEBUG(10,("smb_set_info_standard: file %s\n",
5689 fname ? fname : fsp->fsp_name ));
5691 return smb_set_file_time(conn,
5699 /****************************************************************************
5700 Deal with SMB_SET_FILE_BASIC_INFO.
5701 ****************************************************************************/
5703 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5708 SMB_STRUCT_STAT *psbuf)
5710 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5711 struct timespec write_time;
5712 struct timespec changed_time;
5714 struct timespec ts[2];
5715 NTSTATUS status = NT_STATUS_OK;
5716 bool setting_write_time = true;
5718 if (total_data < 36) {
5719 return NT_STATUS_INVALID_PARAMETER;
5722 /* Set the attributes */
5723 dosmode = IVAL(pdata,32);
5724 status = smb_set_file_dosmode(conn,
5728 if (!NT_STATUS_IS_OK(status)) {
5732 /* Ignore create time at offset pdata. */
5735 ts[0] = interpret_long_date(pdata+8);
5737 write_time = interpret_long_date(pdata+16);
5738 changed_time = interpret_long_date(pdata+24);
5741 ts[1] = timespec_min(&write_time, &changed_time);
5743 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5747 /* Prefer a defined time to an undefined one. */
5748 if (null_timespec(ts[1])) {
5749 if (null_timespec(write_time)) {
5750 ts[1] = changed_time;
5751 setting_write_time = false;
5757 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5758 fname ? fname : fsp->fsp_name ));
5760 return smb_set_file_time(conn,
5765 setting_write_time);
5768 /****************************************************************************
5769 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5770 ****************************************************************************/
5772 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5773 struct smb_request *req,
5778 SMB_STRUCT_STAT *psbuf)
5780 uint64_t allocation_size = 0;
5781 NTSTATUS status = NT_STATUS_OK;
5782 files_struct *new_fsp = NULL;
5784 if (!VALID_STAT(*psbuf)) {
5785 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5788 if (total_data < 8) {
5789 return NT_STATUS_INVALID_PARAMETER;
5792 allocation_size = (uint64_t)IVAL(pdata,0);
5793 #ifdef LARGE_SMB_OFF_T
5794 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5795 #else /* LARGE_SMB_OFF_T */
5796 if (IVAL(pdata,4) != 0) {
5797 /* more than 32 bits? */
5798 return NT_STATUS_INVALID_PARAMETER;
5800 #endif /* LARGE_SMB_OFF_T */
5802 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5803 fname, (double)allocation_size ));
5805 if (allocation_size) {
5806 allocation_size = smb_roundup(conn, allocation_size);
5809 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5810 fname, (double)allocation_size ));
5812 if (fsp && fsp->fh->fd != -1) {
5813 /* Open file handle. */
5814 /* Only change if needed. */
5815 if (allocation_size != get_file_size(*psbuf)) {
5816 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5817 return map_nt_error_from_unix(errno);
5820 /* But always update the time. */
5822 * This is equivalent to a write. Ensure it's seen immediately
5823 * if there are no pending writes.
5825 trigger_write_time_update_immediate(fsp);
5826 return NT_STATUS_OK;
5829 /* Pathname or stat or directory file. */
5831 status = open_file_ntcreate(conn, req, fname, psbuf,
5833 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5836 FILE_ATTRIBUTE_NORMAL,
5837 FORCE_OPLOCK_BREAK_TO_NONE,
5840 if (!NT_STATUS_IS_OK(status)) {
5841 /* NB. We check for open_was_deferred in the caller. */
5845 /* Only change if needed. */
5846 if (allocation_size != get_file_size(*psbuf)) {
5847 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5848 status = map_nt_error_from_unix(errno);
5849 close_file(req, new_fsp, NORMAL_CLOSE);
5854 /* Changing the allocation size should set the last mod time. */
5856 * This is equivalent to a write. Ensure it's seen immediately
5857 * if there are no pending writes.
5859 trigger_write_time_update_immediate(new_fsp);
5861 close_file(req, new_fsp, NORMAL_CLOSE);
5862 return NT_STATUS_OK;
5865 /****************************************************************************
5866 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5867 ****************************************************************************/
5869 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5870 struct smb_request *req,
5875 SMB_STRUCT_STAT *psbuf)
5879 if (total_data < 8) {
5880 return NT_STATUS_INVALID_PARAMETER;
5883 size = IVAL(pdata,0);
5884 #ifdef LARGE_SMB_OFF_T
5885 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5886 #else /* LARGE_SMB_OFF_T */
5887 if (IVAL(pdata,4) != 0) {
5888 /* more than 32 bits? */
5889 return NT_STATUS_INVALID_PARAMETER;
5891 #endif /* LARGE_SMB_OFF_T */
5892 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5893 "file %s to %.0f\n", fname, (double)size ));
5895 return smb_set_file_size(conn, req,
5902 /****************************************************************************
5903 Allow a UNIX info mknod.
5904 ****************************************************************************/
5906 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5910 SMB_STRUCT_STAT *psbuf)
5912 uint32 file_type = IVAL(pdata,56);
5913 #if defined(HAVE_MAKEDEV)
5914 uint32 dev_major = IVAL(pdata,60);
5915 uint32 dev_minor = IVAL(pdata,68);
5917 SMB_DEV_T dev = (SMB_DEV_T)0;
5918 uint32 raw_unixmode = IVAL(pdata,84);
5922 if (total_data < 100) {
5923 return NT_STATUS_INVALID_PARAMETER;
5926 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5927 if (!NT_STATUS_IS_OK(status)) {
5931 #if defined(HAVE_MAKEDEV)
5932 dev = makedev(dev_major, dev_minor);
5935 switch (file_type) {
5936 #if defined(S_IFIFO)
5937 case UNIX_TYPE_FIFO:
5938 unixmode |= S_IFIFO;
5941 #if defined(S_IFSOCK)
5942 case UNIX_TYPE_SOCKET:
5943 unixmode |= S_IFSOCK;
5946 #if defined(S_IFCHR)
5947 case UNIX_TYPE_CHARDEV:
5948 unixmode |= S_IFCHR;
5951 #if defined(S_IFBLK)
5952 case UNIX_TYPE_BLKDEV:
5953 unixmode |= S_IFBLK;
5957 return NT_STATUS_INVALID_PARAMETER;
5960 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5961 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5963 /* Ok - do the mknod. */
5964 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5965 return map_nt_error_from_unix(errno);
5968 /* If any of the other "set" calls fail we
5969 * don't want to end up with a half-constructed mknod.
5972 if (lp_inherit_perms(SNUM(conn))) {
5973 inherit_access_posix_acl(
5974 conn, parent_dirname(fname),
5978 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5979 status = map_nt_error_from_unix(errno);
5980 SMB_VFS_UNLINK(conn,fname);
5983 return NT_STATUS_OK;
5986 /****************************************************************************
5987 Deal with SMB_SET_FILE_UNIX_BASIC.
5988 ****************************************************************************/
5990 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5991 struct smb_request *req,
5996 SMB_STRUCT_STAT *psbuf)
5998 struct timespec ts[2];
5999 uint32 raw_unixmode;
6002 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6003 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6004 NTSTATUS status = NT_STATUS_OK;
6005 bool delete_on_fail = False;
6006 enum perm_type ptype;
6008 if (total_data < 100) {
6009 return NT_STATUS_INVALID_PARAMETER;
6012 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6013 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6014 size=IVAL(pdata,0); /* first 8 Bytes are size */
6015 #ifdef LARGE_SMB_OFF_T
6016 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6017 #else /* LARGE_SMB_OFF_T */
6018 if (IVAL(pdata,4) != 0) {
6019 /* more than 32 bits? */
6020 return NT_STATUS_INVALID_PARAMETER;
6022 #endif /* LARGE_SMB_OFF_T */
6025 ts[0] = interpret_long_date(pdata+24); /* access_time */
6026 ts[1] = interpret_long_date(pdata+32); /* modification_time */
6027 set_owner = (uid_t)IVAL(pdata,40);
6028 set_grp = (gid_t)IVAL(pdata,48);
6029 raw_unixmode = IVAL(pdata,84);
6031 if (VALID_STAT(*psbuf)) {
6032 if (S_ISDIR(psbuf->st_mode)) {
6033 ptype = PERM_EXISTING_DIR;
6035 ptype = PERM_EXISTING_FILE;
6038 ptype = PERM_NEW_FILE;
6041 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6042 if (!NT_STATUS_IS_OK(status)) {
6046 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6047 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6048 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6050 if (!VALID_STAT(*psbuf)) {
6052 * The only valid use of this is to create character and block
6053 * devices, and named pipes. This is deprecated (IMHO) and
6054 * a new info level should be used for mknod. JRA.
6057 status = smb_unix_mknod(conn,
6062 if (!NT_STATUS_IS_OK(status)) {
6066 /* Ensure we don't try and change anything else. */
6067 raw_unixmode = SMB_MODE_NO_CHANGE;
6068 size = get_file_size(*psbuf);
6069 ts[0] = get_atimespec(psbuf);
6070 ts[1] = get_mtimespec(psbuf);
6072 * We continue here as we might want to change the
6075 delete_on_fail = True;
6079 /* Horrible backwards compatibility hack as an old server bug
6080 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6084 size = get_file_size(*psbuf);
6089 * Deal with the UNIX specific mode set.
6092 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6093 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6094 (unsigned int)unixmode, fname ));
6095 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6096 return map_nt_error_from_unix(errno);
6101 * Deal with the UNIX specific uid set.
6104 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6107 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6108 (unsigned int)set_owner, fname ));
6110 if (S_ISLNK(psbuf->st_mode)) {
6111 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6113 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6117 status = map_nt_error_from_unix(errno);
6118 if (delete_on_fail) {
6119 SMB_VFS_UNLINK(conn,fname);
6126 * Deal with the UNIX specific gid set.
6129 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6130 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6131 (unsigned int)set_owner, fname ));
6132 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6133 status = map_nt_error_from_unix(errno);
6134 if (delete_on_fail) {
6135 SMB_VFS_UNLINK(conn,fname);
6141 /* Deal with any size changes. */
6143 status = smb_set_file_size(conn, req,
6148 if (!NT_STATUS_IS_OK(status)) {
6152 /* Deal with any time changes. */
6154 return smb_set_file_time(conn,
6162 /****************************************************************************
6163 Deal with SMB_SET_FILE_UNIX_INFO2.
6164 ****************************************************************************/
6166 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6167 struct smb_request *req,
6172 SMB_STRUCT_STAT *psbuf)
6178 if (total_data < 116) {
6179 return NT_STATUS_INVALID_PARAMETER;
6182 /* Start by setting all the fields that are common between UNIX_BASIC
6185 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6187 if (!NT_STATUS_IS_OK(status)) {
6191 smb_fflags = IVAL(pdata, 108);
6192 smb_fmask = IVAL(pdata, 112);
6194 /* NB: We should only attempt to alter the file flags if the client
6195 * sends a non-zero mask.
6197 if (smb_fmask != 0) {
6198 int stat_fflags = 0;
6200 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6202 /* Client asked to alter a flag we don't understand. */
6203 return NT_STATUS_INVALID_PARAMETER;
6206 if (fsp && fsp->fh->fd != -1) {
6207 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6208 return NT_STATUS_NOT_SUPPORTED;
6210 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6211 return map_nt_error_from_unix(errno);
6216 /* XXX: need to add support for changing the create_time here. You
6217 * can do this for paths on Darwin with setattrlist(2). The right way
6218 * to hook this up is probably by extending the VFS utimes interface.
6221 return NT_STATUS_OK;
6224 /****************************************************************************
6225 Create a directory with POSIX semantics.
6226 ****************************************************************************/
6228 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6229 struct smb_request *req,
6233 SMB_STRUCT_STAT *psbuf,
6234 int *pdata_return_size)
6236 NTSTATUS status = NT_STATUS_OK;
6237 uint32 raw_unixmode = 0;
6238 uint32 mod_unixmode = 0;
6239 mode_t unixmode = (mode_t)0;
6240 files_struct *fsp = NULL;
6241 uint16 info_level_return = 0;
6243 char *pdata = *ppdata;
6245 if (total_data < 18) {
6246 return NT_STATUS_INVALID_PARAMETER;
6249 raw_unixmode = IVAL(pdata,8);
6250 /* Next 4 bytes are not yet defined. */
6252 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6253 if (!NT_STATUS_IS_OK(status)) {
6257 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6259 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6260 fname, (unsigned int)unixmode ));
6262 status = open_directory(conn, req,
6265 FILE_READ_ATTRIBUTES, /* Just a stat open */
6266 FILE_SHARE_NONE, /* Ignored for stat opens */
6273 if (NT_STATUS_IS_OK(status)) {
6274 close_file(req, fsp, NORMAL_CLOSE);
6277 info_level_return = SVAL(pdata,16);
6279 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6280 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6281 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6282 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6284 *pdata_return_size = 12;
6287 /* Realloc the data size */
6288 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6289 if (*ppdata == NULL) {
6290 *pdata_return_size = 0;
6291 return NT_STATUS_NO_MEMORY;
6295 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6296 SSVAL(pdata,2,0); /* No fnum. */
6297 SIVAL(pdata,4,info); /* Was directory created. */
6299 switch (info_level_return) {
6300 case SMB_QUERY_FILE_UNIX_BASIC:
6301 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6302 SSVAL(pdata,10,0); /* Padding. */
6303 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6305 case SMB_QUERY_FILE_UNIX_INFO2:
6306 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6307 SSVAL(pdata,10,0); /* Padding. */
6308 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6311 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6312 SSVAL(pdata,10,0); /* Padding. */
6319 /****************************************************************************
6320 Open/Create a file with POSIX semantics.
6321 ****************************************************************************/
6323 static NTSTATUS smb_posix_open(connection_struct *conn,
6324 struct smb_request *req,
6328 SMB_STRUCT_STAT *psbuf,
6329 int *pdata_return_size)
6331 bool extended_oplock_granted = False;
6332 char *pdata = *ppdata;
6334 uint32 wire_open_mode = 0;
6335 uint32 raw_unixmode = 0;
6336 uint32 mod_unixmode = 0;
6337 uint32 create_disp = 0;
6338 uint32 access_mask = 0;
6339 uint32 create_options = 0;
6340 NTSTATUS status = NT_STATUS_OK;
6341 mode_t unixmode = (mode_t)0;
6342 files_struct *fsp = NULL;
6343 int oplock_request = 0;
6345 uint16 info_level_return = 0;
6347 if (total_data < 18) {
6348 return NT_STATUS_INVALID_PARAMETER;
6351 flags = IVAL(pdata,0);
6352 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6353 if (oplock_request) {
6354 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6357 wire_open_mode = IVAL(pdata,4);
6359 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6360 return smb_posix_mkdir(conn, req,
6368 switch (wire_open_mode & SMB_ACCMODE) {
6370 access_mask = FILE_READ_DATA;
6373 access_mask = FILE_WRITE_DATA;
6376 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6379 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6380 (unsigned int)wire_open_mode ));
6381 return NT_STATUS_INVALID_PARAMETER;
6384 wire_open_mode &= ~SMB_ACCMODE;
6386 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6387 create_disp = FILE_CREATE;
6388 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6389 create_disp = FILE_OVERWRITE_IF;
6390 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6391 create_disp = FILE_OPEN_IF;
6393 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6394 (unsigned int)wire_open_mode ));
6395 return NT_STATUS_INVALID_PARAMETER;
6398 raw_unixmode = IVAL(pdata,8);
6399 /* Next 4 bytes are not yet defined. */
6401 status = unix_perms_from_wire(conn,
6404 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6407 if (!NT_STATUS_IS_OK(status)) {
6411 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6413 if (wire_open_mode & SMB_O_SYNC) {
6414 create_options |= FILE_WRITE_THROUGH;
6416 if (wire_open_mode & SMB_O_APPEND) {
6417 access_mask |= FILE_APPEND_DATA;
6419 if (wire_open_mode & SMB_O_DIRECT) {
6420 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6423 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6425 (unsigned int)wire_open_mode,
6426 (unsigned int)unixmode ));
6428 status = open_file_ntcreate(conn, req,
6432 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6434 0, /* no create options yet. */
6440 if (!NT_STATUS_IS_OK(status)) {
6444 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6445 extended_oplock_granted = True;
6448 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6449 extended_oplock_granted = True;
6452 info_level_return = SVAL(pdata,16);
6454 /* Allocate the correct return size. */
6456 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6457 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6458 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6459 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6461 *pdata_return_size = 12;
6464 /* Realloc the data size */
6465 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6466 if (*ppdata == NULL) {
6467 close_file(req, fsp, ERROR_CLOSE);
6468 *pdata_return_size = 0;
6469 return NT_STATUS_NO_MEMORY;
6473 if (extended_oplock_granted) {
6474 if (flags & REQUEST_BATCH_OPLOCK) {
6475 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6477 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6479 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6480 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6482 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6485 SSVAL(pdata,2,fsp->fnum);
6486 SIVAL(pdata,4,info); /* Was file created etc. */
6488 switch (info_level_return) {
6489 case SMB_QUERY_FILE_UNIX_BASIC:
6490 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6491 SSVAL(pdata,10,0); /* padding. */
6492 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6494 case SMB_QUERY_FILE_UNIX_INFO2:
6495 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6496 SSVAL(pdata,10,0); /* padding. */
6497 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6500 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6501 SSVAL(pdata,10,0); /* padding. */
6504 return NT_STATUS_OK;
6507 /****************************************************************************
6508 Delete a file with POSIX semantics.
6509 ****************************************************************************/
6511 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6512 struct smb_request *req,
6516 SMB_STRUCT_STAT *psbuf)
6518 NTSTATUS status = NT_STATUS_OK;
6519 files_struct *fsp = NULL;
6524 struct share_mode_lock *lck = NULL;
6526 if (total_data < 2) {
6527 return NT_STATUS_INVALID_PARAMETER;
6530 flags = SVAL(pdata,0);
6532 if (!VALID_STAT(*psbuf)) {
6533 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6536 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6537 !VALID_STAT_OF_DIR(*psbuf)) {
6538 return NT_STATUS_NOT_A_DIRECTORY;
6541 DEBUG(10,("smb_posix_unlink: %s %s\n",
6542 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6545 if (VALID_STAT_OF_DIR(*psbuf)) {
6546 status = open_directory(conn, req,
6550 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6553 FILE_FLAG_POSIX_SEMANTICS|0777,
6558 status = open_file_ntcreate(conn, req,
6562 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6565 FILE_FLAG_POSIX_SEMANTICS|0777,
6566 0, /* No oplock, but break existing ones. */
6571 if (!NT_STATUS_IS_OK(status)) {
6576 * Don't lie to client. If we can't really delete due to
6577 * non-POSIX opens return SHARING_VIOLATION.
6580 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6583 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6584 "lock for file %s\n", fsp->fsp_name));
6585 close_file(req, fsp, NORMAL_CLOSE);
6586 return NT_STATUS_INVALID_PARAMETER;
6590 * See if others still have the file open. If this is the case, then
6591 * don't delete. If all opens are POSIX delete we can set the delete
6592 * on close disposition.
6594 for (i=0; i<lck->num_share_modes; i++) {
6595 struct share_mode_entry *e = &lck->share_modes[i];
6596 if (is_valid_share_mode_entry(e)) {
6597 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6600 /* Fail with sharing violation. */
6601 close_file(req, fsp, NORMAL_CLOSE);
6603 return NT_STATUS_SHARING_VIOLATION;
6608 * Set the delete on close.
6610 status = smb_set_file_disposition_info(conn,
6617 if (!NT_STATUS_IS_OK(status)) {
6618 close_file(req, fsp, NORMAL_CLOSE);
6623 return close_file(req, fsp, NORMAL_CLOSE);
6626 /****************************************************************************
6627 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6628 ****************************************************************************/
6630 static void call_trans2setfilepathinfo(connection_struct *conn,
6631 struct smb_request *req,
6632 unsigned int tran_call,
6633 char **pparams, int total_params,
6634 char **ppdata, int total_data,
6635 unsigned int max_data_bytes)
6637 char *params = *pparams;
6638 char *pdata = *ppdata;
6640 SMB_STRUCT_STAT sbuf;
6642 files_struct *fsp = NULL;
6643 NTSTATUS status = NT_STATUS_OK;
6644 int data_return_size = 0;
6645 TALLOC_CTX *ctx = talloc_tos();
6648 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6654 if (tran_call == TRANSACT2_SETFILEINFO) {
6655 if (total_params < 4) {
6656 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6660 fsp = file_fsp(req, SVAL(params,0));
6661 /* Basic check for non-null fsp. */
6662 if (!check_fsp_open(conn, req, fsp)) {
6665 info_level = SVAL(params,2);
6667 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6669 reply_nterror(req, NT_STATUS_NO_MEMORY);
6673 if(fsp->is_directory || fsp->fh->fd == -1) {
6675 * This is actually a SETFILEINFO on a directory
6676 * handle (returned from an NT SMB). NT5.0 seems
6677 * to do this call. JRA.
6679 if (INFO_LEVEL_IS_UNIX(info_level)) {
6680 /* Always do lstat for UNIX calls. */
6681 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6682 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6683 reply_unixerror(req,ERRDOS,ERRbadpath);
6687 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6688 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6689 reply_unixerror(req,ERRDOS,ERRbadpath);
6693 } else if (fsp->print_file) {
6695 * Doing a DELETE_ON_CLOSE should cancel a print job.
6697 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6698 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6700 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6703 send_trans2_replies(conn, req, params, 2,
6708 reply_unixerror(req, ERRDOS, ERRbadpath);
6713 * Original code - this is an open file.
6715 if (!check_fsp(conn, req, fsp)) {
6719 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6720 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6721 reply_unixerror(req, ERRDOS, ERRbadfid);
6727 if (total_params < 7) {
6728 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6732 info_level = SVAL(params,0);
6733 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6734 total_params - 6, STR_TERMINATE,
6736 if (!NT_STATUS_IS_OK(status)) {
6737 reply_nterror(req, status);
6741 status = resolve_dfspath(ctx, conn,
6742 req->flags2 & FLAGS2_DFS_PATHNAMES,
6745 if (!NT_STATUS_IS_OK(status)) {
6746 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6747 reply_botherror(req,
6748 NT_STATUS_PATH_NOT_COVERED,
6749 ERRSRV, ERRbadpath);
6752 reply_nterror(req, status);
6756 status = unix_convert(ctx, conn, fname, False,
6757 &fname, NULL, &sbuf);
6758 if (!NT_STATUS_IS_OK(status)) {
6759 reply_nterror(req, status);
6763 status = check_name(conn, fname);
6764 if (!NT_STATUS_IS_OK(status)) {
6765 reply_nterror(req, status);
6769 if (INFO_LEVEL_IS_UNIX(info_level)) {
6771 * For CIFS UNIX extensions the target name may not exist.
6774 /* Always do lstat for UNIX calls. */
6775 SMB_VFS_LSTAT(conn,fname,&sbuf);
6777 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6778 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6779 reply_unixerror(req, ERRDOS, ERRbadpath);
6784 if (!CAN_WRITE(conn)) {
6785 reply_doserror(req, ERRSRV, ERRaccess);
6789 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6790 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6794 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6795 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6797 /* Realloc the parameter size */
6798 *pparams = (char *)SMB_REALLOC(*pparams,2);
6799 if (*pparams == NULL) {
6800 reply_nterror(req, NT_STATUS_NO_MEMORY);
6807 switch (info_level) {
6809 case SMB_INFO_STANDARD:
6811 status = smb_set_info_standard(conn,
6820 case SMB_INFO_SET_EA:
6822 status = smb_info_set_ea(conn,
6830 case SMB_SET_FILE_BASIC_INFO:
6831 case SMB_FILE_BASIC_INFORMATION:
6833 status = smb_set_file_basic_info(conn,
6842 case SMB_FILE_ALLOCATION_INFORMATION:
6843 case SMB_SET_FILE_ALLOCATION_INFO:
6845 status = smb_set_file_allocation_info(conn, req,
6854 case SMB_FILE_END_OF_FILE_INFORMATION:
6855 case SMB_SET_FILE_END_OF_FILE_INFO:
6857 status = smb_set_file_end_of_file_info(conn, req,
6866 case SMB_FILE_DISPOSITION_INFORMATION:
6867 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6870 /* JRA - We used to just ignore this on a path ?
6871 * Shouldn't this be invalid level on a pathname
6874 if (tran_call != TRANSACT2_SETFILEINFO) {
6875 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6878 status = smb_set_file_disposition_info(conn,
6887 case SMB_FILE_POSITION_INFORMATION:
6889 status = smb_file_position_information(conn,
6896 /* From tridge Samba4 :
6897 * MODE_INFORMATION in setfileinfo (I have no
6898 * idea what "mode information" on a file is - it takes a value of 0,
6899 * 2, 4 or 6. What could it be?).
6902 case SMB_FILE_MODE_INFORMATION:
6904 status = smb_file_mode_information(conn,
6911 * CIFS UNIX extensions.
6914 case SMB_SET_FILE_UNIX_BASIC:
6916 status = smb_set_file_unix_basic(conn, req,
6925 case SMB_SET_FILE_UNIX_INFO2:
6927 status = smb_set_file_unix_info2(conn, req,
6936 case SMB_SET_FILE_UNIX_LINK:
6938 if (tran_call != TRANSACT2_SETPATHINFO) {
6939 /* We must have a pathname for this. */
6940 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6943 status = smb_set_file_unix_link(conn, req, pdata,
6948 case SMB_SET_FILE_UNIX_HLINK:
6950 if (tran_call != TRANSACT2_SETPATHINFO) {
6951 /* We must have a pathname for this. */
6952 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6955 status = smb_set_file_unix_hlink(conn, req,
6961 case SMB_FILE_RENAME_INFORMATION:
6963 status = smb_file_rename_information(conn, req,
6969 #if defined(HAVE_POSIX_ACLS)
6970 case SMB_SET_POSIX_ACL:
6972 status = smb_set_posix_acl(conn,
6982 case SMB_SET_POSIX_LOCK:
6984 if (tran_call != TRANSACT2_SETFILEINFO) {
6985 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6988 status = smb_set_posix_lock(conn, req,
6989 pdata, total_data, fsp);
6993 case SMB_POSIX_PATH_OPEN:
6995 if (tran_call != TRANSACT2_SETPATHINFO) {
6996 /* We must have a pathname for this. */
6997 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7001 status = smb_posix_open(conn, req,
7010 case SMB_POSIX_PATH_UNLINK:
7012 if (tran_call != TRANSACT2_SETPATHINFO) {
7013 /* We must have a pathname for this. */
7014 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7018 status = smb_posix_unlink(conn, req,
7027 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7032 if (!NT_STATUS_IS_OK(status)) {
7033 if (open_was_deferred(req->mid)) {
7034 /* We have re-scheduled this call. */
7037 if (blocking_lock_was_deferred(req->mid)) {
7038 /* We have re-scheduled this call. */
7041 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7042 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7043 ERRSRV, ERRbadpath);
7046 if (info_level == SMB_POSIX_PATH_OPEN) {
7047 reply_openerror(req, status);
7051 reply_nterror(req, status);
7056 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7062 /****************************************************************************
7063 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7064 ****************************************************************************/
7066 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7067 char **pparams, int total_params,
7068 char **ppdata, int total_data,
7069 unsigned int max_data_bytes)
7071 char *params = *pparams;
7072 char *pdata = *ppdata;
7073 char *directory = NULL;
7074 SMB_STRUCT_STAT sbuf;
7075 NTSTATUS status = NT_STATUS_OK;
7076 struct ea_list *ea_list = NULL;
7077 TALLOC_CTX *ctx = talloc_tos();
7079 if (!CAN_WRITE(conn)) {
7080 reply_doserror(req, ERRSRV, ERRaccess);
7084 if (total_params < 5) {
7085 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7089 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7090 total_params - 4, STR_TERMINATE,
7092 if (!NT_STATUS_IS_OK(status)) {
7093 reply_nterror(req, status);
7097 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7099 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7100 if (!NT_STATUS_IS_OK(status)) {
7101 reply_nterror(req, status);
7105 status = check_name(conn, directory);
7106 if (!NT_STATUS_IS_OK(status)) {
7107 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7108 reply_nterror(req, status);
7112 /* Any data in this call is an EA list. */
7113 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7114 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7119 * OS/2 workplace shell seems to send SET_EA requests of "null"
7120 * length (4 bytes containing IVAL 4).
7121 * They seem to have no effect. Bug #3212. JRA.
7124 if (total_data != 4) {
7125 if (total_data < 10) {
7126 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7130 if (IVAL(pdata,0) > total_data) {
7131 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7132 IVAL(pdata,0), (unsigned int)total_data));
7133 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7137 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7144 /* If total_data == 4 Windows doesn't care what values
7145 * are placed in that field, it just ignores them.
7146 * The System i QNTC IBM SMB client puts bad values here,
7147 * so ignore them. */
7149 status = create_directory(conn, req, directory);
7151 if (!NT_STATUS_IS_OK(status)) {
7152 reply_nterror(req, status);
7156 /* Try and set any given EA. */
7158 status = set_ea(conn, NULL, directory, ea_list);
7159 if (!NT_STATUS_IS_OK(status)) {
7160 reply_nterror(req, status);
7165 /* Realloc the parameter and data sizes */
7166 *pparams = (char *)SMB_REALLOC(*pparams,2);
7167 if(*pparams == NULL) {
7168 reply_nterror(req, NT_STATUS_NO_MEMORY);
7175 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7180 /****************************************************************************
7181 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7182 We don't actually do this - we just send a null response.
7183 ****************************************************************************/
7185 static void call_trans2findnotifyfirst(connection_struct *conn,
7186 struct smb_request *req,
7187 char **pparams, int total_params,
7188 char **ppdata, int total_data,
7189 unsigned int max_data_bytes)
7191 static uint16 fnf_handle = 257;
7192 char *params = *pparams;
7195 if (total_params < 6) {
7196 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7200 info_level = SVAL(params,4);
7201 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7203 switch (info_level) {
7208 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7212 /* Realloc the parameter and data sizes */
7213 *pparams = (char *)SMB_REALLOC(*pparams,6);
7214 if (*pparams == NULL) {
7215 reply_nterror(req, NT_STATUS_NO_MEMORY);
7220 SSVAL(params,0,fnf_handle);
7221 SSVAL(params,2,0); /* No changes */
7222 SSVAL(params,4,0); /* No EA errors */
7229 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7234 /****************************************************************************
7235 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7236 changes). Currently this does nothing.
7237 ****************************************************************************/
7239 static void call_trans2findnotifynext(connection_struct *conn,
7240 struct smb_request *req,
7241 char **pparams, int total_params,
7242 char **ppdata, int total_data,
7243 unsigned int max_data_bytes)
7245 char *params = *pparams;
7247 DEBUG(3,("call_trans2findnotifynext\n"));
7249 /* Realloc the parameter and data sizes */
7250 *pparams = (char *)SMB_REALLOC(*pparams,4);
7251 if (*pparams == NULL) {
7252 reply_nterror(req, NT_STATUS_NO_MEMORY);
7257 SSVAL(params,0,0); /* No changes */
7258 SSVAL(params,2,0); /* No EA errors */
7260 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7265 /****************************************************************************
7266 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7267 ****************************************************************************/
7269 static void call_trans2getdfsreferral(connection_struct *conn,
7270 struct smb_request *req,
7271 char **pparams, int total_params,
7272 char **ppdata, int total_data,
7273 unsigned int max_data_bytes)
7275 char *params = *pparams;
7276 char *pathname = NULL;
7278 int max_referral_level;
7279 NTSTATUS status = NT_STATUS_OK;
7280 TALLOC_CTX *ctx = talloc_tos();
7282 DEBUG(10,("call_trans2getdfsreferral\n"));
7284 if (total_params < 3) {
7285 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7289 max_referral_level = SVAL(params,0);
7291 if(!lp_host_msdfs()) {
7292 reply_doserror(req, ERRDOS, ERRbadfunc);
7296 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7297 total_params - 2, STR_TERMINATE);
7299 reply_nterror(req, NT_STATUS_NOT_FOUND);
7302 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7303 ppdata,&status)) < 0) {
7304 reply_nterror(req, status);
7308 SSVAL(req->inbuf, smb_flg2,
7309 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7310 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7315 #define LMCAT_SPL 0x53
7316 #define LMFUNC_GETJOBID 0x60
7318 /****************************************************************************
7319 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7320 ****************************************************************************/
7322 static void call_trans2ioctl(connection_struct *conn,
7323 struct smb_request *req,
7324 char **pparams, int total_params,
7325 char **ppdata, int total_data,
7326 unsigned int max_data_bytes)
7328 char *pdata = *ppdata;
7329 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7331 /* check for an invalid fid before proceeding */
7334 reply_doserror(req, ERRDOS, ERRbadfid);
7338 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7339 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7340 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7341 if (*ppdata == NULL) {
7342 reply_nterror(req, NT_STATUS_NO_MEMORY);
7347 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7348 CAN ACCEPT THIS IN UNICODE. JRA. */
7350 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7351 srvstr_push(pdata, req->flags2, pdata + 2,
7352 global_myname(), 15,
7353 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7354 srvstr_push(pdata, req->flags2, pdata+18,
7355 lp_servicename(SNUM(conn)), 13,
7356 STR_ASCII|STR_TERMINATE); /* Service name */
7357 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7362 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7363 reply_doserror(req, ERRSRV, ERRerror);
7366 /****************************************************************************
7367 Reply to a SMBfindclose (stop trans2 directory search).
7368 ****************************************************************************/
7370 void reply_findclose(struct smb_request *req)
7374 START_PROFILE(SMBfindclose);
7377 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7378 END_PROFILE(SMBfindclose);
7382 dptr_num = SVALS(req->vwv+0, 0);
7384 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7386 dptr_close(&dptr_num);
7388 reply_outbuf(req, 0, 0);
7390 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7392 END_PROFILE(SMBfindclose);
7396 /****************************************************************************
7397 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7398 ****************************************************************************/
7400 void reply_findnclose(struct smb_request *req)
7404 START_PROFILE(SMBfindnclose);
7407 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7408 END_PROFILE(SMBfindnclose);
7412 dptr_num = SVAL(req->vwv+0, 0);
7414 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7416 /* We never give out valid handles for a
7417 findnotifyfirst - so any dptr_num is ok here.
7420 reply_outbuf(req, 0, 0);
7422 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7424 END_PROFILE(SMBfindnclose);
7428 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7429 struct trans_state *state)
7431 if (Protocol >= PROTOCOL_NT1) {
7432 req->flags2 |= 0x40; /* IS_LONG_NAME */
7433 SSVAL(req->inbuf,smb_flg2,req->flags2);
7436 if (conn->encrypt_level == Required && !req->encrypted) {
7437 if (state->call != TRANSACT2_QFSINFO &&
7438 state->call != TRANSACT2_SETFSINFO) {
7439 DEBUG(0,("handle_trans2: encryption required "
7441 (unsigned int)state->call));
7442 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7447 /* Now we must call the relevant TRANS2 function */
7448 switch(state->call) {
7449 case TRANSACT2_OPEN:
7451 START_PROFILE(Trans2_open);
7452 call_trans2open(conn, req,
7453 &state->param, state->total_param,
7454 &state->data, state->total_data,
7455 state->max_data_return);
7456 END_PROFILE(Trans2_open);
7460 case TRANSACT2_FINDFIRST:
7462 START_PROFILE(Trans2_findfirst);
7463 call_trans2findfirst(conn, req,
7464 &state->param, state->total_param,
7465 &state->data, state->total_data,
7466 state->max_data_return);
7467 END_PROFILE(Trans2_findfirst);
7471 case TRANSACT2_FINDNEXT:
7473 START_PROFILE(Trans2_findnext);
7474 call_trans2findnext(conn, req,
7475 &state->param, state->total_param,
7476 &state->data, state->total_data,
7477 state->max_data_return);
7478 END_PROFILE(Trans2_findnext);
7482 case TRANSACT2_QFSINFO:
7484 START_PROFILE(Trans2_qfsinfo);
7485 call_trans2qfsinfo(conn, req,
7486 &state->param, state->total_param,
7487 &state->data, state->total_data,
7488 state->max_data_return);
7489 END_PROFILE(Trans2_qfsinfo);
7493 case TRANSACT2_SETFSINFO:
7495 START_PROFILE(Trans2_setfsinfo);
7496 call_trans2setfsinfo(conn, req,
7497 &state->param, state->total_param,
7498 &state->data, state->total_data,
7499 state->max_data_return);
7500 END_PROFILE(Trans2_setfsinfo);
7504 case TRANSACT2_QPATHINFO:
7505 case TRANSACT2_QFILEINFO:
7507 START_PROFILE(Trans2_qpathinfo);
7508 call_trans2qfilepathinfo(conn, req, state->call,
7509 &state->param, state->total_param,
7510 &state->data, state->total_data,
7511 state->max_data_return);
7512 END_PROFILE(Trans2_qpathinfo);
7516 case TRANSACT2_SETPATHINFO:
7517 case TRANSACT2_SETFILEINFO:
7519 START_PROFILE(Trans2_setpathinfo);
7520 call_trans2setfilepathinfo(conn, req, state->call,
7521 &state->param, state->total_param,
7522 &state->data, state->total_data,
7523 state->max_data_return);
7524 END_PROFILE(Trans2_setpathinfo);
7528 case TRANSACT2_FINDNOTIFYFIRST:
7530 START_PROFILE(Trans2_findnotifyfirst);
7531 call_trans2findnotifyfirst(conn, req,
7532 &state->param, state->total_param,
7533 &state->data, state->total_data,
7534 state->max_data_return);
7535 END_PROFILE(Trans2_findnotifyfirst);
7539 case TRANSACT2_FINDNOTIFYNEXT:
7541 START_PROFILE(Trans2_findnotifynext);
7542 call_trans2findnotifynext(conn, req,
7543 &state->param, state->total_param,
7544 &state->data, state->total_data,
7545 state->max_data_return);
7546 END_PROFILE(Trans2_findnotifynext);
7550 case TRANSACT2_MKDIR:
7552 START_PROFILE(Trans2_mkdir);
7553 call_trans2mkdir(conn, req,
7554 &state->param, state->total_param,
7555 &state->data, state->total_data,
7556 state->max_data_return);
7557 END_PROFILE(Trans2_mkdir);
7561 case TRANSACT2_GET_DFS_REFERRAL:
7563 START_PROFILE(Trans2_get_dfs_referral);
7564 call_trans2getdfsreferral(conn, req,
7565 &state->param, state->total_param,
7566 &state->data, state->total_data,
7567 state->max_data_return);
7568 END_PROFILE(Trans2_get_dfs_referral);
7572 case TRANSACT2_IOCTL:
7574 START_PROFILE(Trans2_ioctl);
7575 call_trans2ioctl(conn, req,
7576 &state->param, state->total_param,
7577 &state->data, state->total_data,
7578 state->max_data_return);
7579 END_PROFILE(Trans2_ioctl);
7584 /* Error in request */
7585 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7586 reply_doserror(req, ERRSRV,ERRerror);
7590 /****************************************************************************
7591 Reply to a SMBtrans2.
7592 ****************************************************************************/
7594 void reply_trans2(struct smb_request *req)
7596 connection_struct *conn = req->conn;
7601 unsigned int tran_call;
7602 struct trans_state *state;
7605 START_PROFILE(SMBtrans2);
7607 if (req->wct < 14) {
7608 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7609 END_PROFILE(SMBtrans2);
7613 dsoff = SVAL(req->vwv+12, 0);
7614 dscnt = SVAL(req->vwv+11, 0);
7615 psoff = SVAL(req->vwv+10, 0);
7616 pscnt = SVAL(req->vwv+9, 0);
7617 tran_call = SVAL(req->vwv+14, 0);
7619 result = allow_new_trans(conn->pending_trans, req->mid);
7620 if (!NT_STATUS_IS_OK(result)) {
7621 DEBUG(2, ("Got invalid trans2 request: %s\n",
7622 nt_errstr(result)));
7623 reply_nterror(req, result);
7624 END_PROFILE(SMBtrans2);
7629 switch (tran_call) {
7630 /* List the allowed trans2 calls on IPC$ */
7631 case TRANSACT2_OPEN:
7632 case TRANSACT2_GET_DFS_REFERRAL:
7633 case TRANSACT2_QFILEINFO:
7634 case TRANSACT2_QFSINFO:
7635 case TRANSACT2_SETFSINFO:
7638 reply_doserror(req, ERRSRV, ERRaccess);
7639 END_PROFILE(SMBtrans2);
7644 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7645 DEBUG(0, ("talloc failed\n"));
7646 reply_nterror(req, NT_STATUS_NO_MEMORY);
7647 END_PROFILE(SMBtrans2);
7651 state->cmd = SMBtrans2;
7653 state->mid = req->mid;
7654 state->vuid = req->vuid;
7655 state->setup_count = SVAL(req->vwv+13, 0);
7656 state->setup = NULL;
7657 state->total_param = SVAL(req->vwv+0, 0);
7658 state->param = NULL;
7659 state->total_data = SVAL(req->vwv+1, 0);
7661 state->max_param_return = SVAL(req->vwv+2, 0);
7662 state->max_data_return = SVAL(req->vwv+3, 0);
7663 state->max_setup_return = SVAL(req->vwv+4, 0);
7664 state->close_on_completion = BITSETW(req->vwv+5, 0);
7665 state->one_way = BITSETW(req->vwv+5, 1);
7667 state->call = tran_call;
7669 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7670 is so as a sanity check */
7671 if (state->setup_count != 1) {
7673 * Need to have rc=0 for ioctl to get job id for OS/2.
7674 * Network printing will fail if function is not successful.
7675 * Similar function in reply.c will be used if protocol
7676 * is LANMAN1.0 instead of LM1.2X002.
7677 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7678 * outbuf doesn't have to be set(only job id is used).
7680 if ( (state->setup_count == 4)
7681 && (tran_call == TRANSACT2_IOCTL)
7682 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7683 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7684 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7686 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7687 DEBUG(2,("Transaction is %d\n",tran_call));
7689 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7690 END_PROFILE(SMBtrans2);
7695 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7698 if (state->total_data) {
7700 if (trans_oob(state->total_data, 0, dscnt)
7701 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7705 /* Can't use talloc here, the core routines do realloc on the
7706 * params and data. */
7707 state->data = (char *)SMB_MALLOC(state->total_data);
7708 if (state->data == NULL) {
7709 DEBUG(0,("reply_trans2: data malloc fail for %u "
7710 "bytes !\n", (unsigned int)state->total_data));
7712 reply_nterror(req, NT_STATUS_NO_MEMORY);
7713 END_PROFILE(SMBtrans2);
7717 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7720 if (state->total_param) {
7722 if (trans_oob(state->total_param, 0, pscnt)
7723 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7727 /* Can't use talloc here, the core routines do realloc on the
7728 * params and data. */
7729 state->param = (char *)SMB_MALLOC(state->total_param);
7730 if (state->param == NULL) {
7731 DEBUG(0,("reply_trans: param malloc fail for %u "
7732 "bytes !\n", (unsigned int)state->total_param));
7733 SAFE_FREE(state->data);
7735 reply_nterror(req, NT_STATUS_NO_MEMORY);
7736 END_PROFILE(SMBtrans2);
7740 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7743 state->received_data = dscnt;
7744 state->received_param = pscnt;
7746 if ((state->received_param == state->total_param) &&
7747 (state->received_data == state->total_data)) {
7749 handle_trans2(conn, req, state);
7751 SAFE_FREE(state->data);
7752 SAFE_FREE(state->param);
7754 END_PROFILE(SMBtrans2);
7758 DLIST_ADD(conn->pending_trans, state);
7760 /* We need to send an interim response then receive the rest
7761 of the parameter/data bytes */
7762 reply_outbuf(req, 0, 0);
7763 show_msg((char *)req->outbuf);
7764 END_PROFILE(SMBtrans2);
7769 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7770 SAFE_FREE(state->data);
7771 SAFE_FREE(state->param);
7773 END_PROFILE(SMBtrans2);
7774 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7778 /****************************************************************************
7779 Reply to a SMBtranss2
7780 ****************************************************************************/
7782 void reply_transs2(struct smb_request *req)
7784 connection_struct *conn = req->conn;
7785 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7786 struct trans_state *state;
7788 START_PROFILE(SMBtranss2);
7790 show_msg((char *)req->inbuf);
7793 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7794 END_PROFILE(SMBtranss2);
7798 for (state = conn->pending_trans; state != NULL;
7799 state = state->next) {
7800 if (state->mid == req->mid) {
7805 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7806 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7807 END_PROFILE(SMBtranss2);
7811 /* Revise state->total_param and state->total_data in case they have
7812 changed downwards */
7814 if (SVAL(req->vwv+0, 0) < state->total_param)
7815 state->total_param = SVAL(req->vwv+0, 0);
7816 if (SVAL(req->vwv+1, 0) < state->total_data)
7817 state->total_data = SVAL(req->vwv+1, 0);
7819 pcnt = SVAL(req->vwv+2, 0);
7820 poff = SVAL(req->vwv+3, 0);
7821 pdisp = SVAL(req->vwv+4, 0);
7823 dcnt = SVAL(req->vwv+5, 0);
7824 doff = SVAL(req->vwv+6, 0);
7825 ddisp = SVAL(req->vwv+7, 0);
7827 state->received_param += pcnt;
7828 state->received_data += dcnt;
7830 if ((state->received_data > state->total_data) ||
7831 (state->received_param > state->total_param))
7835 if (trans_oob(state->total_param, pdisp, pcnt)
7836 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7839 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7843 if (trans_oob(state->total_data, ddisp, dcnt)
7844 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7847 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7850 if ((state->received_param < state->total_param) ||
7851 (state->received_data < state->total_data)) {
7852 END_PROFILE(SMBtranss2);
7856 handle_trans2(conn, req, state);
7858 DLIST_REMOVE(conn->pending_trans, state);
7859 SAFE_FREE(state->data);
7860 SAFE_FREE(state->param);
7863 END_PROFILE(SMBtranss2);
7868 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7869 DLIST_REMOVE(conn->pending_trans, state);
7870 SAFE_FREE(state->data);
7871 SAFE_FREE(state->param);
7873 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7874 END_PROFILE(SMBtranss2);