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 access_mask, /* access_mask */
1015 share_mode, /* share_access */
1016 create_disposition, /* create_disposition*/
1017 create_options, /* create_options */
1018 open_attr, /* file_attributes */
1019 oplock_request, /* oplock_request */
1020 open_size, /* allocation_size */
1022 ea_list, /* ea_list */
1024 &smb_action, /* pinfo */
1027 if (!NT_STATUS_IS_OK(status)) {
1028 if (open_was_deferred(req->mid)) {
1029 /* We have re-scheduled this call. */
1032 reply_openerror(req, status);
1036 size = get_file_size(sbuf);
1037 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1038 mtime = sbuf.st_mtime;
1039 inode = sbuf.st_ino;
1041 close_file(req, fsp, ERROR_CLOSE);
1042 reply_doserror(req, ERRDOS,ERRnoaccess);
1046 /* Realloc the size of parameters and data we will return */
1047 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1048 if(*pparams == NULL ) {
1049 reply_nterror(req, NT_STATUS_NO_MEMORY);
1054 SSVAL(params,0,fsp->fnum);
1055 SSVAL(params,2,fattr);
1056 srv_put_dos_date2(params,4, mtime);
1057 SIVAL(params,8, (uint32)size);
1058 SSVAL(params,12,deny_mode);
1059 SSVAL(params,14,0); /* open_type - file or directory. */
1060 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1062 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1063 smb_action |= EXTENDED_OPLOCK_GRANTED;
1066 SSVAL(params,18,smb_action);
1069 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1071 SIVAL(params,20,inode);
1072 SSVAL(params,24,0); /* Padding. */
1074 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1075 SIVAL(params, 26, ea_size);
1077 SIVAL(params, 26, 0);
1080 /* Send the required number of replies */
1081 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1084 /*********************************************************
1085 Routine to check if a given string matches exactly.
1086 as a special case a mask of "." does NOT match. That
1087 is required for correct wildcard semantics
1088 Case can be significant or not.
1089 **********************************************************/
1091 static bool exact_match(connection_struct *conn,
1095 if (mask[0] == '.' && mask[1] == 0)
1097 if (conn->case_sensitive)
1098 return strcmp(str,mask)==0;
1099 if (StrCaseCmp(str,mask) != 0) {
1102 if (dptr_has_wild(conn->dirptr)) {
1108 /****************************************************************************
1109 Return the filetype for UNIX extensions.
1110 ****************************************************************************/
1112 static uint32 unix_filetype(mode_t mode)
1115 return UNIX_TYPE_FILE;
1116 else if(S_ISDIR(mode))
1117 return UNIX_TYPE_DIR;
1119 else if(S_ISLNK(mode))
1120 return UNIX_TYPE_SYMLINK;
1123 else if(S_ISCHR(mode))
1124 return UNIX_TYPE_CHARDEV;
1127 else if(S_ISBLK(mode))
1128 return UNIX_TYPE_BLKDEV;
1131 else if(S_ISFIFO(mode))
1132 return UNIX_TYPE_FIFO;
1135 else if(S_ISSOCK(mode))
1136 return UNIX_TYPE_SOCKET;
1139 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1140 return UNIX_TYPE_UNKNOWN;
1143 /****************************************************************************
1144 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1145 ****************************************************************************/
1147 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1149 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1150 SMB_STRUCT_STAT *psbuf,
1152 enum perm_type ptype,
1157 if (perms == SMB_MODE_NO_CHANGE) {
1158 if (!VALID_STAT(*psbuf)) {
1159 return NT_STATUS_INVALID_PARAMETER;
1161 *ret_perms = psbuf->st_mode;
1162 return NT_STATUS_OK;
1166 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1167 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1168 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1169 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1170 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1171 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1172 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1173 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1174 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1176 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1179 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1182 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1187 /* Apply mode mask */
1188 ret &= lp_create_mask(SNUM(conn));
1189 /* Add in force bits */
1190 ret |= lp_force_create_mode(SNUM(conn));
1193 ret &= lp_dir_mask(SNUM(conn));
1194 /* Add in force bits */
1195 ret |= lp_force_dir_mode(SNUM(conn));
1197 case PERM_EXISTING_FILE:
1198 /* Apply mode mask */
1199 ret &= lp_security_mask(SNUM(conn));
1200 /* Add in force bits */
1201 ret |= lp_force_security_mode(SNUM(conn));
1203 case PERM_EXISTING_DIR:
1204 /* Apply mode mask */
1205 ret &= lp_dir_security_mask(SNUM(conn));
1206 /* Add in force bits */
1207 ret |= lp_force_dir_security_mode(SNUM(conn));
1212 return NT_STATUS_OK;
1215 /****************************************************************************
1216 Needed to show the msdfs symlinks as directories. Modifies psbuf
1217 to be a directory if it's a msdfs link.
1218 ****************************************************************************/
1220 static bool check_msdfs_link(connection_struct *conn,
1221 const char *pathname,
1222 SMB_STRUCT_STAT *psbuf)
1224 int saved_errno = errno;
1225 if(lp_host_msdfs() &&
1226 lp_msdfs_root(SNUM(conn)) &&
1227 is_msdfs_link(conn, pathname, psbuf)) {
1229 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1232 psbuf->st_mode = (psbuf->st_mode & 0xFFF) | S_IFDIR;
1233 errno = saved_errno;
1236 errno = saved_errno;
1241 /****************************************************************************
1242 Get a level dependent lanman2 dir entry.
1243 ****************************************************************************/
1245 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1246 connection_struct *conn,
1248 const char *path_mask,
1251 int requires_resume_key,
1257 int space_remaining,
1259 bool *got_exact_match,
1260 int *last_entry_off,
1261 struct ea_list *name_list)
1265 SMB_STRUCT_STAT sbuf;
1266 const char *mask = NULL;
1267 char *pathreal = NULL;
1268 const char *fname = NULL;
1269 char *p, *q, *pdata = *ppdata;
1273 SMB_OFF_T file_size = 0;
1274 uint64_t allocation_size = 0;
1276 struct timespec mdate_ts, adate_ts, create_date_ts;
1277 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1279 char *last_entry_ptr;
1281 uint32 nt_extmode; /* Used for NT connections instead of mode */
1282 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1283 bool check_mangled_names = lp_manglednames(conn->params);
1284 char mangled_name[13]; /* mangled 8.3 name. */
1286 *out_of_space = False;
1287 *got_exact_match = False;
1289 ZERO_STRUCT(mdate_ts);
1290 ZERO_STRUCT(adate_ts);
1291 ZERO_STRUCT(create_date_ts);
1293 if (!conn->dirptr) {
1297 p = strrchr_m(path_mask,'/');
1300 mask = talloc_strdup(ctx,"*.*");
1310 bool ms_dfs_link = False;
1312 /* Needed if we run out of space */
1313 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1314 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1317 * Due to bugs in NT client redirectors we are not using
1318 * resume keys any more - set them to zero.
1319 * Check out the related comments in findfirst/findnext.
1325 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1326 (long)conn->dirptr,curr_dirpos));
1333 * fname may get mangled, dname is never mangled.
1334 * Whenever we're accessing the filesystem we use
1335 * pathreal which is composed from dname.
1341 /* Mangle fname if it's an illegal name. */
1342 if (mangle_must_mangle(dname,conn->params)) {
1343 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1344 continue; /* Error - couldn't mangle. */
1346 fname = mangled_name;
1349 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1350 got_match = mask_match(fname, mask, conn->case_sensitive);
1353 if(!got_match && check_mangled_names &&
1354 !mangle_is_8_3(fname, False, conn->params)) {
1356 * It turns out that NT matches wildcards against
1357 * both long *and* short names. This may explain some
1358 * of the wildcard wierdness from old DOS clients
1359 * that some people have been seeing.... JRA.
1361 /* Force the mangling into 8.3. */
1362 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1363 continue; /* Error - couldn't mangle. */
1366 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1367 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1372 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1374 if (dont_descend && !isdots) {
1380 pathreal = talloc_asprintf(ctx,
1385 pathreal = talloc_asprintf(ctx,
1395 if (INFO_LEVEL_IS_UNIX(info_level)) {
1396 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1397 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1398 pathreal,strerror(errno)));
1399 TALLOC_FREE(pathreal);
1402 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1403 /* Needed to show the msdfs symlinks as
1406 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1408 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1409 pathreal,strerror(errno)));
1410 TALLOC_FREE(pathreal);
1416 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1418 mode = dos_mode(conn,pathreal,&sbuf);
1421 if (!dir_check_ftype(conn,mode,dirtype)) {
1422 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1423 TALLOC_FREE(pathreal);
1427 if (!(mode & aDIR)) {
1428 file_size = get_file_size(sbuf);
1430 allocation_size = get_allocation_size(conn,NULL,&sbuf);
1432 mdate_ts = get_mtimespec(&sbuf);
1433 adate_ts = get_atimespec(&sbuf);
1434 create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
1436 if (ask_sharemode) {
1437 struct timespec write_time_ts;
1438 struct file_id fileid;
1440 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1441 get_file_infos(fileid, NULL, &write_time_ts);
1442 if (!null_timespec(write_time_ts)) {
1443 mdate_ts = write_time_ts;
1447 if (lp_dos_filetime_resolution(SNUM(conn))) {
1448 dos_filetime_timespec(&create_date_ts);
1449 dos_filetime_timespec(&mdate_ts);
1450 dos_filetime_timespec(&adate_ts);
1453 create_date = convert_timespec_to_time_t(create_date_ts);
1454 mdate = convert_timespec_to_time_t(mdate_ts);
1455 adate = convert_timespec_to_time_t(adate_ts);
1457 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
1461 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1468 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1470 switch (info_level) {
1471 case SMB_FIND_INFO_STANDARD:
1472 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1473 if(requires_resume_key) {
1477 srv_put_dos_date2(p,0,create_date);
1478 srv_put_dos_date2(p,4,adate);
1479 srv_put_dos_date2(p,8,mdate);
1480 SIVAL(p,12,(uint32)file_size);
1481 SIVAL(p,16,(uint32)allocation_size);
1485 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1486 p += ucs2_align(base_data, p, 0);
1488 len = srvstr_push(base_data, flags2, p,
1489 fname, PTR_DIFF(end_data, p),
1491 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1493 SCVAL(nameptr, -1, len - 2);
1495 SCVAL(nameptr, -1, 0);
1499 SCVAL(nameptr, -1, len - 1);
1501 SCVAL(nameptr, -1, 0);
1507 case SMB_FIND_EA_SIZE:
1508 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1509 if(requires_resume_key) {
1513 srv_put_dos_date2(p,0,create_date);
1514 srv_put_dos_date2(p,4,adate);
1515 srv_put_dos_date2(p,8,mdate);
1516 SIVAL(p,12,(uint32)file_size);
1517 SIVAL(p,16,(uint32)allocation_size);
1520 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1521 SIVAL(p,22,ea_size); /* Extended attributes */
1525 len = srvstr_push(base_data, flags2,
1526 p, fname, PTR_DIFF(end_data, p),
1527 STR_TERMINATE | STR_NOALIGN);
1528 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1541 SCVAL(nameptr,0,len);
1543 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1546 case SMB_FIND_EA_LIST:
1548 struct ea_list *file_list = NULL;
1551 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1555 if(requires_resume_key) {
1559 srv_put_dos_date2(p,0,create_date);
1560 srv_put_dos_date2(p,4,adate);
1561 srv_put_dos_date2(p,8,mdate);
1562 SIVAL(p,12,(uint32)file_size);
1563 SIVAL(p,16,(uint32)allocation_size);
1565 p += 22; /* p now points to the EA area. */
1567 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1568 name_list = ea_list_union(name_list, file_list, &ea_len);
1570 /* We need to determine if this entry will fit in the space available. */
1571 /* Max string size is 255 bytes. */
1572 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1573 /* Move the dirptr back to prev_dirpos */
1574 dptr_SeekDir(conn->dirptr, prev_dirpos);
1575 *out_of_space = True;
1576 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1577 return False; /* Not finished - just out of space */
1580 /* Push the ea_data followed by the name. */
1581 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1583 len = srvstr_push(base_data, flags2,
1584 p + 1, fname, PTR_DIFF(end_data, p+1),
1585 STR_TERMINATE | STR_NOALIGN);
1586 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1599 SCVAL(nameptr,0,len);
1601 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1605 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1606 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1607 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1609 SIVAL(p,0,reskey); p += 4;
1610 put_long_date_timespec(p,create_date_ts); p += 8;
1611 put_long_date_timespec(p,adate_ts); p += 8;
1612 put_long_date_timespec(p,mdate_ts); p += 8;
1613 put_long_date_timespec(p,mdate_ts); p += 8;
1614 SOFF_T(p,0,file_size); p += 8;
1615 SOFF_T(p,0,allocation_size); p += 8;
1616 SIVAL(p,0,nt_extmode); p += 4;
1617 q = p; p += 4; /* q is placeholder for name length. */
1619 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1620 SIVAL(p,0,ea_size); /* Extended attributes */
1623 /* Clear the short name buffer. This is
1624 * IMPORTANT as not doing so will trigger
1625 * a Win2k client bug. JRA.
1627 if (!was_8_3 && check_mangled_names) {
1628 if (!name_to_8_3(fname,mangled_name,True,
1630 /* Error - mangle failed ! */
1631 memset(mangled_name,'\0',12);
1633 mangled_name[12] = 0;
1634 len = srvstr_push(base_data, flags2,
1635 p+2, mangled_name, 24,
1636 STR_UPPER|STR_UNICODE);
1638 memset(p + 2 + len,'\0',24 - len);
1645 len = srvstr_push(base_data, flags2, p,
1646 fname, PTR_DIFF(end_data, p),
1647 STR_TERMINATE_ASCII);
1650 SIVAL(p,0,0); /* Ensure any padding is null. */
1651 len = PTR_DIFF(p, pdata);
1652 len = (len + 3) & ~3;
1657 case SMB_FIND_FILE_DIRECTORY_INFO:
1658 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1660 SIVAL(p,0,reskey); p += 4;
1661 put_long_date_timespec(p,create_date_ts); p += 8;
1662 put_long_date_timespec(p,adate_ts); p += 8;
1663 put_long_date_timespec(p,mdate_ts); p += 8;
1664 put_long_date_timespec(p,mdate_ts); p += 8;
1665 SOFF_T(p,0,file_size); p += 8;
1666 SOFF_T(p,0,allocation_size); p += 8;
1667 SIVAL(p,0,nt_extmode); p += 4;
1668 len = srvstr_push(base_data, flags2,
1669 p + 4, fname, PTR_DIFF(end_data, p+4),
1670 STR_TERMINATE_ASCII);
1673 SIVAL(p,0,0); /* Ensure any padding is null. */
1674 len = PTR_DIFF(p, pdata);
1675 len = (len + 3) & ~3;
1680 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1681 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1683 SIVAL(p,0,reskey); p += 4;
1684 put_long_date_timespec(p,create_date_ts); p += 8;
1685 put_long_date_timespec(p,adate_ts); p += 8;
1686 put_long_date_timespec(p,mdate_ts); p += 8;
1687 put_long_date_timespec(p,mdate_ts); p += 8;
1688 SOFF_T(p,0,file_size); p += 8;
1689 SOFF_T(p,0,allocation_size); p += 8;
1690 SIVAL(p,0,nt_extmode); p += 4;
1691 q = p; p += 4; /* q is placeholder for name length. */
1693 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1694 SIVAL(p,0,ea_size); /* Extended attributes */
1697 len = srvstr_push(base_data, flags2, p,
1698 fname, PTR_DIFF(end_data, p),
1699 STR_TERMINATE_ASCII);
1703 SIVAL(p,0,0); /* Ensure any padding is null. */
1704 len = PTR_DIFF(p, pdata);
1705 len = (len + 3) & ~3;
1710 case SMB_FIND_FILE_NAMES_INFO:
1711 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1713 SIVAL(p,0,reskey); p += 4;
1715 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1716 acl on a dir (tridge) */
1717 len = srvstr_push(base_data, flags2, p,
1718 fname, PTR_DIFF(end_data, p),
1719 STR_TERMINATE_ASCII);
1722 SIVAL(p,0,0); /* Ensure any padding is null. */
1723 len = PTR_DIFF(p, pdata);
1724 len = (len + 3) & ~3;
1729 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1730 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1732 SIVAL(p,0,reskey); p += 4;
1733 put_long_date_timespec(p,create_date_ts); p += 8;
1734 put_long_date_timespec(p,adate_ts); p += 8;
1735 put_long_date_timespec(p,mdate_ts); p += 8;
1736 put_long_date_timespec(p,mdate_ts); p += 8;
1737 SOFF_T(p,0,file_size); p += 8;
1738 SOFF_T(p,0,allocation_size); p += 8;
1739 SIVAL(p,0,nt_extmode); p += 4;
1740 q = p; p += 4; /* q is placeholder for name length. */
1742 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1743 SIVAL(p,0,ea_size); /* Extended attributes */
1746 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1747 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1748 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1749 len = srvstr_push(base_data, flags2, p,
1750 fname, PTR_DIFF(end_data, p),
1751 STR_TERMINATE_ASCII);
1754 SIVAL(p,0,0); /* Ensure any padding is null. */
1755 len = PTR_DIFF(p, pdata);
1756 len = (len + 3) & ~3;
1761 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1762 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1763 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1765 SIVAL(p,0,reskey); p += 4;
1766 put_long_date_timespec(p,create_date_ts); p += 8;
1767 put_long_date_timespec(p,adate_ts); p += 8;
1768 put_long_date_timespec(p,mdate_ts); p += 8;
1769 put_long_date_timespec(p,mdate_ts); p += 8;
1770 SOFF_T(p,0,file_size); p += 8;
1771 SOFF_T(p,0,allocation_size); p += 8;
1772 SIVAL(p,0,nt_extmode); p += 4;
1773 q = p; p += 4; /* q is placeholder for name length */
1775 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1776 SIVAL(p,0,ea_size); /* Extended attributes */
1779 /* Clear the short name buffer. This is
1780 * IMPORTANT as not doing so will trigger
1781 * a Win2k client bug. JRA.
1783 if (!was_8_3 && check_mangled_names) {
1784 if (!name_to_8_3(fname,mangled_name,True,
1786 /* Error - mangle failed ! */
1787 memset(mangled_name,'\0',12);
1789 mangled_name[12] = 0;
1790 len = srvstr_push(base_data, flags2,
1791 p+2, mangled_name, 24,
1792 STR_UPPER|STR_UNICODE);
1795 memset(p + 2 + len,'\0',24 - len);
1802 SSVAL(p,0,0); p += 2; /* Reserved ? */
1803 SIVAL(p,0,sbuf.st_ino); p += 4; /* FileIndexLow */
1804 SIVAL(p,0,sbuf.st_dev); p += 4; /* FileIndexHigh */
1805 len = srvstr_push(base_data, flags2, p,
1806 fname, PTR_DIFF(end_data, p),
1807 STR_TERMINATE_ASCII);
1810 SIVAL(p,0,0); /* Ensure any padding is null. */
1811 len = PTR_DIFF(p, pdata);
1812 len = (len + 3) & ~3;
1817 /* CIFS UNIX Extension. */
1819 case SMB_FIND_FILE_UNIX:
1820 case SMB_FIND_FILE_UNIX_INFO2:
1822 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1824 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1826 if (info_level == SMB_FIND_FILE_UNIX) {
1827 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1828 p = store_file_unix_basic(conn, p,
1830 len = srvstr_push(base_data, flags2, p,
1831 fname, PTR_DIFF(end_data, p),
1834 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1835 p = store_file_unix_basic_info2(conn, p,
1839 len = srvstr_push(base_data, flags2, p, fname,
1840 PTR_DIFF(end_data, p), 0);
1841 SIVAL(nameptr, 0, len);
1845 SIVAL(p,0,0); /* Ensure any padding is null. */
1847 len = PTR_DIFF(p, pdata);
1848 len = (len + 3) & ~3;
1849 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1851 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1860 if (PTR_DIFF(p,pdata) > space_remaining) {
1861 /* Move the dirptr back to prev_dirpos */
1862 dptr_SeekDir(conn->dirptr, prev_dirpos);
1863 *out_of_space = True;
1864 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1865 return False; /* Not finished - just out of space */
1868 /* Setup the last entry pointer, as an offset from base_data */
1869 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1870 /* Advance the data pointer to the next slot */
1876 /****************************************************************************
1877 Reply to a TRANS2_FINDFIRST.
1878 ****************************************************************************/
1880 static void call_trans2findfirst(connection_struct *conn,
1881 struct smb_request *req,
1882 char **pparams, int total_params,
1883 char **ppdata, int total_data,
1884 unsigned int max_data_bytes)
1886 /* We must be careful here that we don't return more than the
1887 allowed number of data bytes. If this means returning fewer than
1888 maxentries then so be it. We assume that the redirector has
1889 enough room for the fixed number of parameter bytes it has
1891 char *params = *pparams;
1892 char *pdata = *ppdata;
1896 uint16 findfirst_flags;
1897 bool close_after_first;
1899 bool requires_resume_key;
1901 char *directory = NULL;
1904 int last_entry_off=0;
1908 bool finished = False;
1909 bool dont_descend = False;
1910 bool out_of_space = False;
1911 int space_remaining;
1912 bool mask_contains_wcard = False;
1913 SMB_STRUCT_STAT sbuf;
1914 struct ea_list *ea_list = NULL;
1915 NTSTATUS ntstatus = NT_STATUS_OK;
1916 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1917 TALLOC_CTX *ctx = talloc_tos();
1919 if (total_params < 13) {
1920 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1924 dirtype = SVAL(params,0);
1925 maxentries = SVAL(params,2);
1926 findfirst_flags = SVAL(params,4);
1927 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1928 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1929 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1930 info_level = SVAL(params,6);
1932 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1933 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1934 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1935 info_level, max_data_bytes));
1938 /* W2K3 seems to treat zero as 1. */
1942 switch (info_level) {
1943 case SMB_FIND_INFO_STANDARD:
1944 case SMB_FIND_EA_SIZE:
1945 case SMB_FIND_EA_LIST:
1946 case SMB_FIND_FILE_DIRECTORY_INFO:
1947 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1948 case SMB_FIND_FILE_NAMES_INFO:
1949 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1950 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1951 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1953 case SMB_FIND_FILE_UNIX:
1954 case SMB_FIND_FILE_UNIX_INFO2:
1955 /* Always use filesystem for UNIX mtime query. */
1956 ask_sharemode = false;
1957 if (!lp_unix_extensions()) {
1958 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1963 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1967 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1968 params+12, total_params - 12,
1969 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1970 if (!NT_STATUS_IS_OK(ntstatus)) {
1971 reply_nterror(req, ntstatus);
1975 ntstatus = resolve_dfspath_wcard(ctx, conn,
1976 req->flags2 & FLAGS2_DFS_PATHNAMES,
1979 &mask_contains_wcard);
1980 if (!NT_STATUS_IS_OK(ntstatus)) {
1981 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1982 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1983 ERRSRV, ERRbadpath);
1986 reply_nterror(req, ntstatus);
1990 ntstatus = unix_convert(ctx, conn, directory, True, &directory, &mask, &sbuf);
1991 if (!NT_STATUS_IS_OK(ntstatus)) {
1992 reply_nterror(req, ntstatus);
1996 ntstatus = check_name(conn, directory);
1997 if (!NT_STATUS_IS_OK(ntstatus)) {
1998 reply_nterror(req, ntstatus);
2002 p = strrchr_m(directory,'/');
2004 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2005 if((directory[0] == '.') && (directory[1] == '\0')) {
2006 mask = talloc_strdup(ctx,"*");
2008 reply_nterror(req, NT_STATUS_NO_MEMORY);
2011 mask_contains_wcard = True;
2013 directory = talloc_strdup(talloc_tos(), "./");
2015 reply_nterror(req, NT_STATUS_NO_MEMORY);
2022 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2024 if (info_level == SMB_FIND_EA_LIST) {
2027 if (total_data < 4) {
2028 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2032 ea_size = IVAL(pdata,0);
2033 if (ea_size != total_data) {
2034 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2035 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2036 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2040 if (!lp_ea_support(SNUM(conn))) {
2041 reply_doserror(req, ERRDOS, ERReasnotsupported);
2045 /* Pull out the list of names. */
2046 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2048 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2053 *ppdata = (char *)SMB_REALLOC(
2054 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2055 if(*ppdata == NULL ) {
2056 reply_nterror(req, NT_STATUS_NO_MEMORY);
2060 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2062 /* Realloc the params space */
2063 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2064 if (*pparams == NULL) {
2065 reply_nterror(req, NT_STATUS_NO_MEMORY);
2070 /* Save the wildcard match and attribs we are using on this directory -
2071 needed as lanman2 assumes these are being saved between calls */
2073 ntstatus = dptr_create(conn,
2079 mask_contains_wcard,
2083 if (!NT_STATUS_IS_OK(ntstatus)) {
2084 reply_nterror(req, ntstatus);
2088 dptr_num = dptr_dnum(conn->dirptr);
2089 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2091 /* We don't need to check for VOL here as this is returned by
2092 a different TRANS2 call. */
2094 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2095 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2096 dont_descend = True;
2099 space_remaining = max_data_bytes;
2100 out_of_space = False;
2102 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2103 bool got_exact_match = False;
2105 /* this is a heuristic to avoid seeking the dirptr except when
2106 absolutely necessary. It allows for a filename of about 40 chars */
2107 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2108 out_of_space = True;
2111 finished = !get_lanman2_dir_entry(ctx,
2114 mask,dirtype,info_level,
2115 requires_resume_key,dont_descend,
2118 space_remaining, &out_of_space,
2120 &last_entry_off, ea_list);
2123 if (finished && out_of_space)
2126 if (!finished && !out_of_space)
2130 * As an optimisation if we know we aren't looking
2131 * for a wildcard name (ie. the name matches the wildcard exactly)
2132 * then we can finish on any (first) match.
2133 * This speeds up large directory searches. JRA.
2139 /* Ensure space_remaining never goes -ve. */
2140 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2141 space_remaining = 0;
2142 out_of_space = true;
2144 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2148 /* Check if we can close the dirptr */
2149 if(close_after_first || (finished && close_if_end)) {
2150 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2151 dptr_close(&dptr_num);
2155 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2156 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2157 * the protocol level is less than NT1. Tested with smbclient. JRA.
2158 * This should fix the OS/2 client bug #2335.
2161 if(numentries == 0) {
2162 dptr_close(&dptr_num);
2163 if (Protocol < PROTOCOL_NT1) {
2164 reply_doserror(req, ERRDOS, ERRnofiles);
2167 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2168 ERRDOS, ERRbadfile);
2173 /* At this point pdata points to numentries directory entries. */
2175 /* Set up the return parameter block */
2176 SSVAL(params,0,dptr_num);
2177 SSVAL(params,2,numentries);
2178 SSVAL(params,4,finished);
2179 SSVAL(params,6,0); /* Never an EA error */
2180 SSVAL(params,8,last_entry_off);
2182 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2185 if ((! *directory) && dptr_path(dptr_num)) {
2186 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2188 reply_nterror(req, NT_STATUS_NO_MEMORY);
2192 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2193 smb_fn_name(req->cmd),
2194 mask, directory, dirtype, numentries ) );
2197 * Force a name mangle here to ensure that the
2198 * mask as an 8.3 name is top of the mangled cache.
2199 * The reasons for this are subtle. Don't remove
2200 * this code unless you know what you are doing
2201 * (see PR#13758). JRA.
2204 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2205 char mangled_name[13];
2206 name_to_8_3(mask, mangled_name, True, conn->params);
2212 /****************************************************************************
2213 Reply to a TRANS2_FINDNEXT.
2214 ****************************************************************************/
2216 static void call_trans2findnext(connection_struct *conn,
2217 struct smb_request *req,
2218 char **pparams, int total_params,
2219 char **ppdata, int total_data,
2220 unsigned int max_data_bytes)
2222 /* We must be careful here that we don't return more than the
2223 allowed number of data bytes. If this means returning fewer than
2224 maxentries then so be it. We assume that the redirector has
2225 enough room for the fixed number of parameter bytes it has
2227 char *params = *pparams;
2228 char *pdata = *ppdata;
2234 uint16 findnext_flags;
2235 bool close_after_request;
2237 bool requires_resume_key;
2239 bool mask_contains_wcard = False;
2240 char *resume_name = NULL;
2241 const char *mask = NULL;
2242 const char *directory = NULL;
2246 int i, last_entry_off=0;
2247 bool finished = False;
2248 bool dont_descend = False;
2249 bool out_of_space = False;
2250 int space_remaining;
2251 struct ea_list *ea_list = NULL;
2252 NTSTATUS ntstatus = NT_STATUS_OK;
2253 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2254 TALLOC_CTX *ctx = talloc_tos();
2256 if (total_params < 13) {
2257 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2261 dptr_num = SVAL(params,0);
2262 maxentries = SVAL(params,2);
2263 info_level = SVAL(params,4);
2264 resume_key = IVAL(params,6);
2265 findnext_flags = SVAL(params,10);
2266 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2267 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2268 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2269 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2271 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2273 total_params - 12, STR_TERMINATE, &ntstatus,
2274 &mask_contains_wcard);
2275 if (!NT_STATUS_IS_OK(ntstatus)) {
2276 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2277 complain (it thinks we're asking for the directory above the shared
2278 path or an invalid name). Catch this as the resume name is only compared, never used in
2279 a file access. JRA. */
2280 srvstr_pull_talloc(ctx, params, req->flags2,
2281 &resume_name, params+12,
2285 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2286 reply_nterror(req, ntstatus);
2291 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2292 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2293 resume_key = %d resume name = %s continue=%d level = %d\n",
2294 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2295 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2298 /* W2K3 seems to treat zero as 1. */
2302 switch (info_level) {
2303 case SMB_FIND_INFO_STANDARD:
2304 case SMB_FIND_EA_SIZE:
2305 case SMB_FIND_EA_LIST:
2306 case SMB_FIND_FILE_DIRECTORY_INFO:
2307 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2308 case SMB_FIND_FILE_NAMES_INFO:
2309 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2310 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2311 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2313 case SMB_FIND_FILE_UNIX:
2314 case SMB_FIND_FILE_UNIX_INFO2:
2315 /* Always use filesystem for UNIX mtime query. */
2316 ask_sharemode = false;
2317 if (!lp_unix_extensions()) {
2318 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2323 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2327 if (info_level == SMB_FIND_EA_LIST) {
2330 if (total_data < 4) {
2331 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2335 ea_size = IVAL(pdata,0);
2336 if (ea_size != total_data) {
2337 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2338 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2339 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2343 if (!lp_ea_support(SNUM(conn))) {
2344 reply_doserror(req, ERRDOS, ERReasnotsupported);
2348 /* Pull out the list of names. */
2349 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2351 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2356 *ppdata = (char *)SMB_REALLOC(
2357 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2358 if(*ppdata == NULL) {
2359 reply_nterror(req, NT_STATUS_NO_MEMORY);
2364 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2366 /* Realloc the params space */
2367 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2368 if(*pparams == NULL ) {
2369 reply_nterror(req, NT_STATUS_NO_MEMORY);
2375 /* Check that the dptr is valid */
2376 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2377 reply_doserror(req, ERRDOS, ERRnofiles);
2381 string_set(&conn->dirpath,dptr_path(dptr_num));
2383 /* Get the wildcard mask from the dptr */
2384 if((p = dptr_wcard(dptr_num))== NULL) {
2385 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2386 reply_doserror(req, ERRDOS, ERRnofiles);
2391 directory = conn->dirpath;
2393 /* Get the attr mask from the dptr */
2394 dirtype = dptr_attr(dptr_num);
2396 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2397 dptr_num, mask, dirtype,
2399 dptr_TellDir(conn->dirptr)));
2401 /* We don't need to check for VOL here as this is returned by
2402 a different TRANS2 call. */
2404 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2405 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2406 dont_descend = True;
2409 space_remaining = max_data_bytes;
2410 out_of_space = False;
2413 * Seek to the correct position. We no longer use the resume key but
2414 * depend on the last file name instead.
2417 if(*resume_name && !continue_bit) {
2420 long current_pos = 0;
2422 * Remember, name_to_8_3 is called by
2423 * get_lanman2_dir_entry(), so the resume name
2424 * could be mangled. Ensure we check the unmangled name.
2427 if (mangle_is_mangled(resume_name, conn->params)) {
2428 char *new_resume_name = NULL;
2429 mangle_lookup_name_from_8_3(ctx,
2433 if (new_resume_name) {
2434 resume_name = new_resume_name;
2439 * Fix for NT redirector problem triggered by resume key indexes
2440 * changing between directory scans. We now return a resume key of 0
2441 * and instead look for the filename to continue from (also given
2442 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2443 * findfirst/findnext (as is usual) then the directory pointer
2444 * should already be at the correct place.
2447 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2448 } /* end if resume_name && !continue_bit */
2450 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2451 bool got_exact_match = False;
2453 /* this is a heuristic to avoid seeking the dirptr except when
2454 absolutely necessary. It allows for a filename of about 40 chars */
2455 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2456 out_of_space = True;
2459 finished = !get_lanman2_dir_entry(ctx,
2462 mask,dirtype,info_level,
2463 requires_resume_key,dont_descend,
2466 space_remaining, &out_of_space,
2468 &last_entry_off, ea_list);
2471 if (finished && out_of_space)
2474 if (!finished && !out_of_space)
2478 * As an optimisation if we know we aren't looking
2479 * for a wildcard name (ie. the name matches the wildcard exactly)
2480 * then we can finish on any (first) match.
2481 * This speeds up large directory searches. JRA.
2487 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2490 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2491 smb_fn_name(req->cmd),
2492 mask, directory, dirtype, numentries ) );
2494 /* Check if we can close the dirptr */
2495 if(close_after_request || (finished && close_if_end)) {
2496 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2497 dptr_close(&dptr_num); /* This frees up the saved mask */
2500 /* Set up the return parameter block */
2501 SSVAL(params,0,numentries);
2502 SSVAL(params,2,finished);
2503 SSVAL(params,4,0); /* Never an EA error */
2504 SSVAL(params,6,last_entry_off);
2506 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2512 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2514 E_md4hash(lp_servicename(SNUM(conn)),objid);
2518 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2520 SMB_ASSERT(extended_info != NULL);
2522 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2523 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2524 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2525 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2526 #ifdef SAMBA_VERSION_REVISION
2527 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2529 extended_info->samba_subversion = 0;
2530 #ifdef SAMBA_VERSION_RC_RELEASE
2531 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2533 #ifdef SAMBA_VERSION_PRE_RELEASE
2534 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2537 #ifdef SAMBA_VERSION_VENDOR_PATCH
2538 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2540 extended_info->samba_gitcommitdate = 0;
2541 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2542 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2545 memset(extended_info->samba_version_string, 0,
2546 sizeof(extended_info->samba_version_string));
2548 snprintf (extended_info->samba_version_string,
2549 sizeof(extended_info->samba_version_string),
2550 "%s", samba_version_string());
2553 /****************************************************************************
2554 Reply to a TRANS2_QFSINFO (query filesystem info).
2555 ****************************************************************************/
2557 static void call_trans2qfsinfo(connection_struct *conn,
2558 struct smb_request *req,
2559 char **pparams, int total_params,
2560 char **ppdata, int total_data,
2561 unsigned int max_data_bytes)
2563 char *pdata, *end_data;
2564 char *params = *pparams;
2568 const char *vname = volume_label(SNUM(conn));
2569 int snum = SNUM(conn);
2570 char *fstype = lp_fstype(SNUM(conn));
2571 uint32 additional_flags = 0;
2573 if (total_params < 2) {
2574 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2578 info_level = SVAL(params,0);
2581 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2582 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2583 "info level (0x%x) on IPC$.\n",
2584 (unsigned int)info_level));
2585 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2590 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2591 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2592 DEBUG(0,("call_trans2qfsinfo: encryption required "
2593 "and info level 0x%x sent.\n",
2594 (unsigned int)info_level));
2595 exit_server_cleanly("encryption required "
2601 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2603 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2604 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2605 reply_doserror(req, ERRSRV, ERRinvdevice);
2609 *ppdata = (char *)SMB_REALLOC(
2610 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2611 if (*ppdata == NULL ) {
2612 reply_nterror(req, NT_STATUS_NO_MEMORY);
2617 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2618 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2620 switch (info_level) {
2621 case SMB_INFO_ALLOCATION:
2623 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2625 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2626 reply_unixerror(req, ERRHRD, ERRgeneral);
2630 block_size = lp_block_size(snum);
2631 if (bsize < block_size) {
2632 uint64_t factor = block_size/bsize;
2637 if (bsize > block_size) {
2638 uint64_t factor = bsize/block_size;
2643 bytes_per_sector = 512;
2644 sectors_per_unit = bsize/bytes_per_sector;
2646 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2647 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2648 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2650 SIVAL(pdata,l1_idFileSystem,st.st_dev);
2651 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2652 SIVAL(pdata,l1_cUnit,dsize);
2653 SIVAL(pdata,l1_cUnitAvail,dfree);
2654 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2658 case SMB_INFO_VOLUME:
2659 /* Return volume name */
2661 * Add volume serial number - hash of a combination of
2662 * the called hostname and the service name.
2664 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2666 * Win2k3 and previous mess this up by sending a name length
2667 * one byte short. I believe only older clients (OS/2 Win9x) use
2668 * this call so try fixing this by adding a terminating null to
2669 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2673 pdata+l2_vol_szVolLabel, vname,
2674 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2675 STR_NOALIGN|STR_TERMINATE);
2676 SCVAL(pdata,l2_vol_cch,len);
2677 data_len = l2_vol_szVolLabel + len;
2678 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2679 (unsigned)st.st_ctime, len, vname));
2682 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2683 case SMB_FS_ATTRIBUTE_INFORMATION:
2685 additional_flags = 0;
2686 #if defined(HAVE_SYS_QUOTAS)
2687 additional_flags |= FILE_VOLUME_QUOTAS;
2690 if(lp_nt_acl_support(SNUM(conn))) {
2691 additional_flags |= FILE_PERSISTENT_ACLS;
2694 /* Capabilities are filled in at connection time through STATVFS call */
2695 additional_flags |= conn->fs_capabilities;
2697 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2698 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2699 additional_flags); /* FS ATTRIBUTES */
2701 SIVAL(pdata,4,255); /* Max filename component length */
2702 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2703 and will think we can't do long filenames */
2704 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2705 PTR_DIFF(end_data, pdata+12),
2708 data_len = 12 + len;
2711 case SMB_QUERY_FS_LABEL_INFO:
2712 case SMB_FS_LABEL_INFORMATION:
2713 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2714 PTR_DIFF(end_data, pdata+4), 0);
2719 case SMB_QUERY_FS_VOLUME_INFO:
2720 case SMB_FS_VOLUME_INFORMATION:
2723 * Add volume serial number - hash of a combination of
2724 * the called hostname and the service name.
2726 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2727 (str_checksum(get_local_machine_name())<<16));
2729 /* Max label len is 32 characters. */
2730 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2731 PTR_DIFF(end_data, pdata+18),
2733 SIVAL(pdata,12,len);
2736 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2737 (int)strlen(vname),vname, lp_servicename(snum)));
2740 case SMB_QUERY_FS_SIZE_INFO:
2741 case SMB_FS_SIZE_INFORMATION:
2743 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2745 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2746 reply_unixerror(req, ERRHRD, ERRgeneral);
2749 block_size = lp_block_size(snum);
2750 if (bsize < block_size) {
2751 uint64_t factor = block_size/bsize;
2756 if (bsize > block_size) {
2757 uint64_t factor = bsize/block_size;
2762 bytes_per_sector = 512;
2763 sectors_per_unit = bsize/bytes_per_sector;
2764 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2765 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2766 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2767 SBIG_UINT(pdata,0,dsize);
2768 SBIG_UINT(pdata,8,dfree);
2769 SIVAL(pdata,16,sectors_per_unit);
2770 SIVAL(pdata,20,bytes_per_sector);
2774 case SMB_FS_FULL_SIZE_INFORMATION:
2776 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2778 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2779 reply_unixerror(req, ERRHRD, ERRgeneral);
2782 block_size = lp_block_size(snum);
2783 if (bsize < block_size) {
2784 uint64_t factor = block_size/bsize;
2789 if (bsize > block_size) {
2790 uint64_t factor = bsize/block_size;
2795 bytes_per_sector = 512;
2796 sectors_per_unit = bsize/bytes_per_sector;
2797 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2798 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2799 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2800 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2801 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2802 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2803 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2804 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2808 case SMB_QUERY_FS_DEVICE_INFO:
2809 case SMB_FS_DEVICE_INFORMATION:
2811 SIVAL(pdata,0,0); /* dev type */
2812 SIVAL(pdata,4,0); /* characteristics */
2815 #ifdef HAVE_SYS_QUOTAS
2816 case SMB_FS_QUOTA_INFORMATION:
2818 * what we have to send --metze:
2820 * Unknown1: 24 NULL bytes
2821 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2822 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2823 * Quota Flags: 2 byte :
2824 * Unknown3: 6 NULL bytes
2828 * details for Quota Flags:
2830 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2831 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2832 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2833 * 0x0001 Enable Quotas: enable quota for this fs
2837 /* we need to fake up a fsp here,
2838 * because its not send in this call
2841 SMB_NTQUOTA_STRUCT quotas;
2844 ZERO_STRUCT(quotas);
2850 if (conn->server_info->utok.uid != 0) {
2851 DEBUG(0,("set_user_quota: access_denied "
2852 "service [%s] user [%s]\n",
2853 lp_servicename(SNUM(conn)),
2854 conn->server_info->unix_name));
2855 reply_doserror(req, ERRDOS, ERRnoaccess);
2859 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2860 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2861 reply_doserror(req, ERRSRV, ERRerror);
2867 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2869 /* Unknown1 24 NULL bytes*/
2870 SBIG_UINT(pdata,0,(uint64_t)0);
2871 SBIG_UINT(pdata,8,(uint64_t)0);
2872 SBIG_UINT(pdata,16,(uint64_t)0);
2874 /* Default Soft Quota 8 bytes */
2875 SBIG_UINT(pdata,24,quotas.softlim);
2877 /* Default Hard Quota 8 bytes */
2878 SBIG_UINT(pdata,32,quotas.hardlim);
2880 /* Quota flag 2 bytes */
2881 SSVAL(pdata,40,quotas.qflags);
2883 /* Unknown3 6 NULL bytes */
2889 #endif /* HAVE_SYS_QUOTAS */
2890 case SMB_FS_OBJECTID_INFORMATION:
2892 unsigned char objid[16];
2893 struct smb_extended_info extended_info;
2894 memcpy(pdata,create_volume_objectid(conn, objid),16);
2895 samba_extended_info_version (&extended_info);
2896 SIVAL(pdata,16,extended_info.samba_magic);
2897 SIVAL(pdata,20,extended_info.samba_version);
2898 SIVAL(pdata,24,extended_info.samba_subversion);
2899 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2900 memcpy(pdata+36,extended_info.samba_version_string,28);
2906 * Query the version and capabilities of the CIFS UNIX extensions
2910 case SMB_QUERY_CIFS_UNIX_INFO:
2912 bool large_write = lp_min_receive_file_size() &&
2913 !srv_is_signing_active();
2914 bool large_read = !srv_is_signing_active();
2915 int encrypt_caps = 0;
2917 if (!lp_unix_extensions()) {
2918 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2922 switch (conn->encrypt_level) {
2928 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2931 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2932 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2933 large_write = false;
2939 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2940 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2942 /* We have POSIX ACLs, pathname, encryption,
2943 * large read/write, and locking capability. */
2945 SBIG_UINT(pdata,4,((uint64_t)(
2946 CIFS_UNIX_POSIX_ACLS_CAP|
2947 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2948 CIFS_UNIX_FCNTL_LOCKS_CAP|
2949 CIFS_UNIX_EXTATTR_CAP|
2950 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2952 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2954 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2958 case SMB_QUERY_POSIX_FS_INFO:
2961 vfs_statvfs_struct svfs;
2963 if (!lp_unix_extensions()) {
2964 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2968 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2972 SIVAL(pdata,0,svfs.OptimalTransferSize);
2973 SIVAL(pdata,4,svfs.BlockSize);
2974 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2975 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2976 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2977 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2978 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2979 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2980 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2982 } else if (rc == EOPNOTSUPP) {
2983 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2985 #endif /* EOPNOTSUPP */
2987 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2988 reply_doserror(req, ERRSRV, ERRerror);
2994 case SMB_QUERY_POSIX_WHOAMI:
3000 if (!lp_unix_extensions()) {
3001 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3005 if (max_data_bytes < 40) {
3006 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3010 /* We ARE guest if global_sid_Builtin_Guests is
3011 * in our list of SIDs.
3013 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3014 conn->server_info->ptok)) {
3015 flags |= SMB_WHOAMI_GUEST;
3018 /* We are NOT guest if global_sid_Authenticated_Users
3019 * is in our list of SIDs.
3021 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3022 conn->server_info->ptok)) {
3023 flags &= ~SMB_WHOAMI_GUEST;
3026 /* NOTE: 8 bytes for UID/GID, irrespective of native
3027 * platform size. This matches
3028 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3030 data_len = 4 /* flags */
3037 + 4 /* pad/reserved */
3038 + (conn->server_info->utok.ngroups * 8)
3040 + (conn->server_info->ptok->num_sids *
3044 SIVAL(pdata, 0, flags);
3045 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3047 (uint64_t)conn->server_info->utok.uid);
3048 SBIG_UINT(pdata, 16,
3049 (uint64_t)conn->server_info->utok.gid);
3052 if (data_len >= max_data_bytes) {
3053 /* Potential overflow, skip the GIDs and SIDs. */
3055 SIVAL(pdata, 24, 0); /* num_groups */
3056 SIVAL(pdata, 28, 0); /* num_sids */
3057 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3058 SIVAL(pdata, 36, 0); /* reserved */
3064 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3065 SIVAL(pdata, 28, conn->server_info->num_sids);
3067 /* We walk the SID list twice, but this call is fairly
3068 * infrequent, and I don't expect that it's performance
3069 * sensitive -- jpeach
3071 for (i = 0, sid_bytes = 0;
3072 i < conn->server_info->ptok->num_sids; ++i) {
3073 sid_bytes += ndr_size_dom_sid(
3074 &conn->server_info->ptok->user_sids[i],
3078 /* SID list byte count */
3079 SIVAL(pdata, 32, sid_bytes);
3081 /* 4 bytes pad/reserved - must be zero */
3082 SIVAL(pdata, 36, 0);
3086 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3087 SBIG_UINT(pdata, data_len,
3088 (uint64_t)conn->server_info->utok.groups[i]);
3094 i < conn->server_info->ptok->num_sids; ++i) {
3095 int sid_len = ndr_size_dom_sid(
3096 &conn->server_info->ptok->user_sids[i],
3099 sid_linearize(pdata + data_len, sid_len,
3100 &conn->server_info->ptok->user_sids[i]);
3101 data_len += sid_len;
3107 case SMB_MAC_QUERY_FS_INFO:
3109 * Thursby MAC extension... ONLY on NTFS filesystems
3110 * once we do streams then we don't need this
3112 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3114 SIVAL(pdata,84,0x100); /* Don't support mac... */
3119 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3124 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3127 DEBUG( 4, ( "%s info_level = %d\n",
3128 smb_fn_name(req->cmd), info_level) );
3133 /****************************************************************************
3134 Reply to a TRANS2_SETFSINFO (set filesystem info).
3135 ****************************************************************************/
3137 static void call_trans2setfsinfo(connection_struct *conn,
3138 struct smb_request *req,
3139 char **pparams, int total_params,
3140 char **ppdata, int total_data,
3141 unsigned int max_data_bytes)
3143 char *pdata = *ppdata;
3144 char *params = *pparams;
3147 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3150 if (total_params < 4) {
3151 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3153 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3157 info_level = SVAL(params,2);
3160 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3161 info_level != SMB_SET_CIFS_UNIX_INFO) {
3162 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3163 "info level (0x%x) on IPC$.\n",
3164 (unsigned int)info_level));
3165 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3170 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3171 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3172 DEBUG(0,("call_trans2setfsinfo: encryption required "
3173 "and info level 0x%x sent.\n",
3174 (unsigned int)info_level));
3175 exit_server_cleanly("encryption required "
3181 switch(info_level) {
3182 case SMB_SET_CIFS_UNIX_INFO:
3184 uint16 client_unix_major;
3185 uint16 client_unix_minor;
3186 uint32 client_unix_cap_low;
3187 uint32 client_unix_cap_high;
3189 if (!lp_unix_extensions()) {
3191 NT_STATUS_INVALID_LEVEL);
3195 /* There should be 12 bytes of capabilities set. */
3196 if (total_data < 8) {
3199 NT_STATUS_INVALID_PARAMETER);
3202 client_unix_major = SVAL(pdata,0);
3203 client_unix_minor = SVAL(pdata,2);
3204 client_unix_cap_low = IVAL(pdata,4);
3205 client_unix_cap_high = IVAL(pdata,8);
3206 /* Just print these values for now. */
3207 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3208 cap_low = 0x%x, cap_high = 0x%x\n",
3209 (unsigned int)client_unix_major,
3210 (unsigned int)client_unix_minor,
3211 (unsigned int)client_unix_cap_low,
3212 (unsigned int)client_unix_cap_high ));
3214 /* Here is where we must switch to posix pathname processing... */
3215 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3216 lp_set_posix_pathnames();
3217 mangle_change_to_posix();
3220 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3221 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3222 /* Client that knows how to do posix locks,
3223 * but not posix open/mkdir operations. Set a
3224 * default type for read/write checks. */
3226 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3232 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3235 size_t param_len = 0;
3236 size_t data_len = total_data;
3238 if (!lp_unix_extensions()) {
3241 NT_STATUS_INVALID_LEVEL);
3245 if (lp_smb_encrypt(SNUM(conn)) == false) {
3248 NT_STATUS_NOT_SUPPORTED);
3252 DEBUG( 4,("call_trans2setfsinfo: "
3253 "request transport encryption.\n"));
3255 status = srv_request_encryption_setup(conn,
3256 (unsigned char **)ppdata,
3258 (unsigned char **)pparams,
3261 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3262 !NT_STATUS_IS_OK(status)) {
3263 reply_nterror(req, status);
3267 send_trans2_replies(conn, req,
3274 if (NT_STATUS_IS_OK(status)) {
3275 /* Server-side transport
3276 * encryption is now *on*. */
3277 status = srv_encryption_start(conn);
3278 if (!NT_STATUS_IS_OK(status)) {
3279 exit_server_cleanly(
3280 "Failure in setting "
3281 "up encrypted transport");
3287 case SMB_FS_QUOTA_INFORMATION:
3289 files_struct *fsp = NULL;
3290 SMB_NTQUOTA_STRUCT quotas;
3292 ZERO_STRUCT(quotas);
3295 if ((conn->server_info->utok.uid != 0)
3296 ||!CAN_WRITE(conn)) {
3297 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3298 lp_servicename(SNUM(conn)),
3299 conn->server_info->unix_name));
3300 reply_doserror(req, ERRSRV, ERRaccess);
3304 /* note: normaly there're 48 bytes,
3305 * but we didn't use the last 6 bytes for now
3308 fsp = file_fsp(req, SVAL(params,0));
3310 if (!check_fsp_ntquota_handle(conn, req,
3312 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3314 req, NT_STATUS_INVALID_HANDLE);
3318 if (total_data < 42) {
3319 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3323 NT_STATUS_INVALID_PARAMETER);
3327 /* unknown_1 24 NULL bytes in pdata*/
3329 /* the soft quotas 8 bytes (uint64_t)*/
3330 quotas.softlim = (uint64_t)IVAL(pdata,24);
3331 #ifdef LARGE_SMB_OFF_T
3332 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3333 #else /* LARGE_SMB_OFF_T */
3334 if ((IVAL(pdata,28) != 0)&&
3335 ((quotas.softlim != 0xFFFFFFFF)||
3336 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3337 /* more than 32 bits? */
3340 NT_STATUS_INVALID_PARAMETER);
3343 #endif /* LARGE_SMB_OFF_T */
3345 /* the hard quotas 8 bytes (uint64_t)*/
3346 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3347 #ifdef LARGE_SMB_OFF_T
3348 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3349 #else /* LARGE_SMB_OFF_T */
3350 if ((IVAL(pdata,36) != 0)&&
3351 ((quotas.hardlim != 0xFFFFFFFF)||
3352 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3353 /* more than 32 bits? */
3356 NT_STATUS_INVALID_PARAMETER);
3359 #endif /* LARGE_SMB_OFF_T */
3361 /* quota_flags 2 bytes **/
3362 quotas.qflags = SVAL(pdata,40);
3364 /* unknown_2 6 NULL bytes follow*/
3366 /* now set the quotas */
3367 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3368 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3369 reply_doserror(req, ERRSRV, ERRerror);
3376 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3378 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3384 * sending this reply works fine,
3385 * but I'm not sure it's the same
3386 * like windows do...
3389 reply_outbuf(req, 10, 0);
3392 #if defined(HAVE_POSIX_ACLS)
3393 /****************************************************************************
3394 Utility function to count the number of entries in a POSIX acl.
3395 ****************************************************************************/
3397 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3399 unsigned int ace_count = 0;
3400 int entry_id = SMB_ACL_FIRST_ENTRY;
3401 SMB_ACL_ENTRY_T entry;
3403 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3405 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3406 entry_id = SMB_ACL_NEXT_ENTRY;
3413 /****************************************************************************
3414 Utility function to marshall a POSIX acl into wire format.
3415 ****************************************************************************/
3417 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3419 int entry_id = SMB_ACL_FIRST_ENTRY;
3420 SMB_ACL_ENTRY_T entry;
3422 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3423 SMB_ACL_TAG_T tagtype;
3424 SMB_ACL_PERMSET_T permset;
3425 unsigned char perms = 0;
3426 unsigned int own_grp;
3429 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3430 entry_id = SMB_ACL_NEXT_ENTRY;
3433 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3434 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3438 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3439 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3443 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3444 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3445 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3447 SCVAL(pdata,1,perms);
3450 case SMB_ACL_USER_OBJ:
3451 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3452 own_grp = (unsigned int)pst->st_uid;
3453 SIVAL(pdata,2,own_grp);
3458 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3460 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3463 own_grp = (unsigned int)*puid;
3464 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3465 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3466 SIVAL(pdata,2,own_grp);
3470 case SMB_ACL_GROUP_OBJ:
3471 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3472 own_grp = (unsigned int)pst->st_gid;
3473 SIVAL(pdata,2,own_grp);
3478 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3480 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3483 own_grp = (unsigned int)*pgid;
3484 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3485 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3486 SIVAL(pdata,2,own_grp);
3491 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3492 SIVAL(pdata,2,0xFFFFFFFF);
3493 SIVAL(pdata,6,0xFFFFFFFF);
3496 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3497 SIVAL(pdata,2,0xFFFFFFFF);
3498 SIVAL(pdata,6,0xFFFFFFFF);
3501 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3504 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3511 /****************************************************************************
3512 Store the FILE_UNIX_BASIC info.
3513 ****************************************************************************/
3515 static char *store_file_unix_basic(connection_struct *conn,
3518 const SMB_STRUCT_STAT *psbuf)
3520 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3521 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_mode));
3523 SOFF_T(pdata,0,get_file_size(*psbuf)); /* File size 64 Bit */
3526 SOFF_T(pdata,0,get_allocation_size(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3529 put_long_date_timespec(pdata,get_ctimespec(psbuf)); /* Change Time 64 Bit */
3530 put_long_date_timespec(pdata+8,get_atimespec(psbuf)); /* Last access time 64 Bit */
3531 put_long_date_timespec(pdata+16,get_mtimespec(psbuf)); /* Last modification time 64 Bit */
3534 SIVAL(pdata,0,psbuf->st_uid); /* user id for the owner */
3538 SIVAL(pdata,0,psbuf->st_gid); /* group id of owner */
3542 SIVAL(pdata,0,unix_filetype(psbuf->st_mode));
3545 SIVAL(pdata,0,unix_dev_major(psbuf->st_rdev)); /* Major device number if type is device */
3549 SIVAL(pdata,0,unix_dev_minor(psbuf->st_rdev)); /* Minor device number if type is device */
3553 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ino); /* inode number */
3556 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_mode)); /* Standard UNIX file permissions */
3560 SIVAL(pdata,0,psbuf->st_nlink); /* number of hard links */
3567 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3568 * the chflags(2) (or equivalent) flags.
3570 * XXX: this really should be behind the VFS interface. To do this, we would
3571 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3572 * Each VFS module could then implement its own mapping as appropriate for the
3573 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3575 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3579 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3583 { UF_IMMUTABLE, EXT_IMMUTABLE },
3587 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3591 { UF_HIDDEN, EXT_HIDDEN },
3594 /* Do not remove. We need to guarantee that this array has at least one
3595 * entry to build on HP-UX.
3601 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3602 uint32 *smb_fflags, uint32 *smb_fmask)
3604 #ifdef HAVE_STAT_ST_FLAGS
3607 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3608 *smb_fmask |= info2_flags_map[i].smb_fflag;
3609 if (psbuf->st_flags & info2_flags_map[i].stat_fflag) {
3610 *smb_fflags |= info2_flags_map[i].smb_fflag;
3613 #endif /* HAVE_STAT_ST_FLAGS */
3616 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3617 const uint32 smb_fflags,
3618 const uint32 smb_fmask,
3621 #ifdef HAVE_STAT_ST_FLAGS
3622 uint32 max_fmask = 0;
3625 *stat_fflags = psbuf->st_flags;
3627 /* For each flags requested in smb_fmask, check the state of the
3628 * corresponding flag in smb_fflags and set or clear the matching
3632 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3633 max_fmask |= info2_flags_map[i].smb_fflag;
3634 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3635 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3636 *stat_fflags |= info2_flags_map[i].stat_fflag;
3638 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3643 /* If smb_fmask is asking to set any bits that are not supported by
3644 * our flag mappings, we should fail.
3646 if ((smb_fmask & max_fmask) != smb_fmask) {
3653 #endif /* HAVE_STAT_ST_FLAGS */
3657 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3658 * of file flags and birth (create) time.
3660 static char *store_file_unix_basic_info2(connection_struct *conn,
3663 const SMB_STRUCT_STAT *psbuf)
3665 uint32 file_flags = 0;
3666 uint32 flags_mask = 0;
3668 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3670 /* Create (birth) time 64 bit */
3671 put_long_date_timespec(pdata, get_create_timespec(psbuf, False));
3674 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3675 SIVAL(pdata, 0, file_flags); /* flags */
3676 SIVAL(pdata, 4, flags_mask); /* mask */
3682 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3683 const struct stream_struct *streams,
3685 unsigned int max_data_bytes,
3686 unsigned int *data_size)
3689 unsigned int ofs = 0;
3691 for (i=0; i<num_streams; i++) {
3692 unsigned int next_offset;
3694 smb_ucs2_t *namebuf;
3696 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3697 streams[i].name, &namelen) ||
3700 return NT_STATUS_INVALID_PARAMETER;
3704 * name_buf is now null-terminated, we need to marshall as not
3710 if (ofs + 24 + namelen > max_data_bytes) {
3711 TALLOC_FREE(namebuf);
3712 return NT_STATUS_BUFFER_TOO_SMALL;
3715 SIVAL(data, ofs+4, namelen);
3716 SOFF_T(data, ofs+8, streams[i].size);
3717 SOFF_T(data, ofs+16, streams[i].alloc_size);
3718 memcpy(data+ofs+24, namebuf, namelen);
3719 TALLOC_FREE(namebuf);
3721 next_offset = ofs + 24 + namelen;
3723 if (i == num_streams-1) {
3724 SIVAL(data, ofs, 0);
3727 unsigned int align = ndr_align_size(next_offset, 8);
3729 if (next_offset + align > max_data_bytes) {
3730 return NT_STATUS_BUFFER_TOO_SMALL;
3733 memset(data+next_offset, 0, align);
3734 next_offset += align;
3736 SIVAL(data, ofs, next_offset - ofs);
3745 return NT_STATUS_OK;
3748 /****************************************************************************
3749 Reply to a TRANSACT2_QFILEINFO on a PIPE !
3750 ****************************************************************************/
3752 static void call_trans2qpipeinfo(connection_struct *conn,
3753 struct smb_request *req,
3754 unsigned int tran_call,
3755 char **pparams, int total_params,
3756 char **ppdata, int total_data,
3757 unsigned int max_data_bytes)
3759 char *params = *pparams;
3760 char *pdata = *ppdata;
3761 unsigned int data_size = 0;
3762 unsigned int param_size = 2;
3767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3771 if (total_params < 4) {
3772 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3776 fsp = file_fsp(req, SVAL(params,0));
3777 if (!fsp_is_np(fsp)) {
3778 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
3782 info_level = SVAL(params,2);
3784 *pparams = (char *)SMB_REALLOC(*pparams,2);
3785 if (*pparams == NULL) {
3786 reply_nterror(req, NT_STATUS_NO_MEMORY);
3791 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3792 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3793 if (*ppdata == NULL ) {
3794 reply_nterror(req, NT_STATUS_NO_MEMORY);
3799 switch (info_level) {
3800 case SMB_FILE_STANDARD_INFORMATION:
3802 SOFF_T(pdata,0,4096LL);
3809 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3813 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
3819 /****************************************************************************
3820 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
3821 file name or file id).
3822 ****************************************************************************/
3824 static void call_trans2qfilepathinfo(connection_struct *conn,
3825 struct smb_request *req,
3826 unsigned int tran_call,
3827 char **pparams, int total_params,
3828 char **ppdata, int total_data,
3829 unsigned int max_data_bytes)
3831 char *params = *pparams;
3832 char *pdata = *ppdata;
3833 char *dstart, *dend;
3837 SMB_OFF_T file_size=0;
3838 uint64_t allocation_size=0;
3839 unsigned int data_size = 0;
3840 unsigned int param_size = 2;
3841 SMB_STRUCT_STAT sbuf;
3842 char *dos_fname = NULL;
3848 bool delete_pending = False;
3850 time_t create_time, mtime, atime;
3851 struct timespec create_time_ts, mtime_ts, atime_ts;
3852 struct timespec write_time_ts;
3853 files_struct *fsp = NULL;
3854 struct file_id fileid;
3855 struct ea_list *ea_list = NULL;
3856 char *lock_data = NULL;
3857 bool ms_dfs_link = false;
3858 TALLOC_CTX *ctx = talloc_tos();
3861 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3866 ZERO_STRUCT(write_time_ts);
3868 if (tran_call == TRANSACT2_QFILEINFO) {
3869 if (total_params < 4) {
3870 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3875 call_trans2qpipeinfo(conn, req, tran_call,
3876 pparams, total_params,
3882 fsp = file_fsp(req, SVAL(params,0));
3883 info_level = SVAL(params,2);
3885 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
3887 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3888 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3892 /* Initial check for valid fsp ptr. */
3893 if (!check_fsp_open(conn, req, fsp)) {
3897 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
3899 reply_nterror(req, NT_STATUS_NO_MEMORY);
3903 if(fsp->fake_file_handle) {
3905 * This is actually for the QUOTA_FAKE_FILE --metze
3908 /* We know this name is ok, it's already passed the checks. */
3910 } else if(fsp && (fsp->is_directory || fsp->fh->fd == -1)) {
3912 * This is actually a QFILEINFO on a directory
3913 * handle (returned from an NT SMB). NT5.0 seems
3914 * to do this call. JRA.
3917 if (INFO_LEVEL_IS_UNIX(info_level)) {
3918 /* Always do lstat for UNIX calls. */
3919 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
3920 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
3921 reply_unixerror(req,ERRDOS,ERRbadpath);
3924 } else if (SMB_VFS_STAT(conn,fname,&sbuf)) {
3925 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
3926 reply_unixerror(req, ERRDOS, ERRbadpath);
3930 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3931 get_file_infos(fileid, &delete_pending, &write_time_ts);
3934 * Original code - this is an open file.
3936 if (!check_fsp(conn, req, fsp)) {
3940 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
3941 DEBUG(3,("fstat of fnum %d failed (%s)\n", fsp->fnum, strerror(errno)));
3942 reply_unixerror(req, ERRDOS, ERRbadfid);
3945 pos = fsp->fh->position_information;
3946 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
3947 get_file_infos(fileid, &delete_pending, &write_time_ts);
3951 NTSTATUS status = NT_STATUS_OK;
3954 if (total_params < 7) {
3955 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3959 info_level = SVAL(params,0);
3961 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
3963 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
3964 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3968 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
3970 STR_TERMINATE, &status);
3971 if (!NT_STATUS_IS_OK(status)) {
3972 reply_nterror(req, status);
3976 status = resolve_dfspath(ctx,
3978 req->flags2 & FLAGS2_DFS_PATHNAMES,
3981 if (!NT_STATUS_IS_OK(status)) {
3982 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
3983 reply_botherror(req,
3984 NT_STATUS_PATH_NOT_COVERED,
3985 ERRSRV, ERRbadpath);
3987 reply_nterror(req, status);
3991 status = unix_convert(ctx, conn, fname, False, &fname, NULL, &sbuf);
3992 if (!NT_STATUS_IS_OK(status)) {
3993 reply_nterror(req, status);
3996 status = check_name(conn, fname);
3997 if (!NT_STATUS_IS_OK(status)) {
3998 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",fname,nt_errstr(status)));
3999 reply_nterror(req, status);
4003 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
4004 && is_ntfs_stream_name(fname)) {
4006 SMB_STRUCT_STAT bsbuf;
4008 status = split_ntfs_stream_name(talloc_tos(), fname,
4010 if (!NT_STATUS_IS_OK(status)) {
4011 DEBUG(10, ("create_file_unixpath: "
4012 "split_ntfs_stream_name failed: %s\n",
4013 nt_errstr(status)));
4014 reply_nterror(req, status);
4018 SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */
4020 if (INFO_LEVEL_IS_UNIX(info_level)) {
4021 /* Always do lstat for UNIX calls. */
4022 if (SMB_VFS_LSTAT(conn,base,&bsbuf)) {
4023 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",base,strerror(errno)));
4024 reply_unixerror(req,ERRDOS,ERRbadpath);
4028 if (SMB_VFS_STAT(conn,base,&bsbuf) != 0) {
4029 DEBUG(3,("call_trans2qfilepathinfo: fileinfo of %s failed (%s)\n",base,strerror(errno)));
4030 reply_unixerror(req,ERRDOS,ERRbadpath);
4035 fileid = vfs_file_id_from_sbuf(conn, &bsbuf);
4036 get_file_infos(fileid, &delete_pending, NULL);
4037 if (delete_pending) {
4038 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4043 if (INFO_LEVEL_IS_UNIX(info_level)) {
4044 /* Always do lstat for UNIX calls. */
4045 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
4046 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
4047 reply_unixerror(req, ERRDOS, ERRbadpath);
4051 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf) && (info_level != SMB_INFO_IS_NAME_VALID)) {
4052 ms_dfs_link = check_msdfs_link(conn,fname,&sbuf);
4055 DEBUG(3,("call_trans2qfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
4056 reply_unixerror(req, ERRDOS, ERRbadpath);
4061 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4062 get_file_infos(fileid, &delete_pending, &write_time_ts);
4063 if (delete_pending) {
4064 reply_nterror(req, NT_STATUS_DELETE_PENDING);
4069 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4070 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4074 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d total_data=%d\n",
4075 fname,fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
4077 p = strrchr_m(fname,'/');
4084 mode = dos_mode_msdfs(conn,fname,&sbuf);
4086 mode = dos_mode(conn,fname,&sbuf);
4089 mode = FILE_ATTRIBUTE_NORMAL;
4091 nlink = sbuf.st_nlink;
4093 if (nlink && (mode&aDIR)) {
4097 if ((nlink > 0) && delete_pending) {
4101 fullpathname = fname;
4103 file_size = get_file_size(sbuf);
4105 /* Pull out any data sent here before we realloc. */
4106 switch (info_level) {
4107 case SMB_INFO_QUERY_EAS_FROM_LIST:
4109 /* Pull any EA list from the data portion. */
4112 if (total_data < 4) {
4114 req, NT_STATUS_INVALID_PARAMETER);
4117 ea_size = IVAL(pdata,0);
4119 if (total_data > 0 && ea_size != total_data) {
4120 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
4121 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
4123 req, NT_STATUS_INVALID_PARAMETER);
4127 if (!lp_ea_support(SNUM(conn))) {
4128 reply_doserror(req, ERRDOS,
4129 ERReasnotsupported);
4133 /* Pull out the list of names. */
4134 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
4137 req, NT_STATUS_INVALID_PARAMETER);
4143 case SMB_QUERY_POSIX_LOCK:
4145 if (fsp == NULL || fsp->fh->fd == -1) {
4146 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4150 if (total_data != POSIX_LOCK_DATA_SIZE) {
4152 req, NT_STATUS_INVALID_PARAMETER);
4156 /* Copy the lock range data. */
4157 lock_data = (char *)TALLOC_MEMDUP(
4158 ctx, pdata, total_data);
4160 reply_nterror(req, NT_STATUS_NO_MEMORY);
4168 *pparams = (char *)SMB_REALLOC(*pparams,2);
4169 if (*pparams == NULL) {
4170 reply_nterror(req, NT_STATUS_NO_MEMORY);
4175 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4176 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4177 if (*ppdata == NULL ) {
4178 reply_nterror(req, NT_STATUS_NO_MEMORY);
4183 dend = dstart + data_size - 1;
4185 create_time_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
4186 mtime_ts = get_mtimespec(&sbuf);
4187 atime_ts = get_atimespec(&sbuf);
4189 allocation_size = get_allocation_size(conn,fsp,&sbuf);
4192 /* Do we have this path open ? */
4194 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
4195 fsp1 = file_find_di_first(fileid);
4196 if (fsp1 && fsp1->initial_allocation_size) {
4197 allocation_size = get_allocation_size(conn, fsp1, &sbuf);
4201 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4202 mtime_ts = write_time_ts;
4205 if (lp_dos_filetime_resolution(SNUM(conn))) {
4206 dos_filetime_timespec(&create_time_ts);
4207 dos_filetime_timespec(&mtime_ts);
4208 dos_filetime_timespec(&atime_ts);
4211 create_time = convert_timespec_to_time_t(create_time_ts);
4212 mtime = convert_timespec_to_time_t(mtime_ts);
4213 atime = convert_timespec_to_time_t(atime_ts);
4215 /* NT expects the name to be in an exact form of the *full*
4216 filename. See the trans2 torture test */
4217 if (ISDOT(base_name)) {
4218 dos_fname = talloc_strdup(ctx, "\\");
4220 reply_nterror(req, NT_STATUS_NO_MEMORY);
4224 dos_fname = talloc_asprintf(ctx,
4228 reply_nterror(req, NT_STATUS_NO_MEMORY);
4231 string_replace(dos_fname, '/', '\\');
4234 switch (info_level) {
4235 case SMB_INFO_STANDARD:
4236 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_STANDARD\n"));
4238 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4239 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4240 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4241 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4242 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4243 SSVAL(pdata,l1_attrFile,mode);
4246 case SMB_INFO_QUERY_EA_SIZE:
4248 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4249 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4251 srv_put_dos_date2(pdata,0,create_time);
4252 srv_put_dos_date2(pdata,4,atime);
4253 srv_put_dos_date2(pdata,8,mtime); /* write time */
4254 SIVAL(pdata,12,(uint32)file_size);
4255 SIVAL(pdata,16,(uint32)allocation_size);
4256 SSVAL(pdata,20,mode);
4257 SIVAL(pdata,22,ea_size);
4261 case SMB_INFO_IS_NAME_VALID:
4262 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4263 if (tran_call == TRANSACT2_QFILEINFO) {
4264 /* os/2 needs this ? really ?*/
4265 reply_doserror(req, ERRDOS, ERRbadfunc);
4272 case SMB_INFO_QUERY_EAS_FROM_LIST:
4274 size_t total_ea_len = 0;
4275 struct ea_list *ea_file_list = NULL;
4277 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4279 ea_file_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4280 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4282 if (!ea_list || (total_ea_len > data_size)) {
4284 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4288 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4292 case SMB_INFO_QUERY_ALL_EAS:
4294 /* We have data_size bytes to put EA's into. */
4295 size_t total_ea_len = 0;
4297 DEBUG(10,("call_trans2qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4299 ea_list = get_ea_list_from_file(ctx, conn, fsp, fname, &total_ea_len);
4300 if (!ea_list || (total_ea_len > data_size)) {
4302 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4306 data_size = fill_ea_buffer(ctx, pdata, data_size, conn, ea_list);
4310 case SMB_FILE_BASIC_INFORMATION:
4311 case SMB_QUERY_FILE_BASIC_INFO:
4313 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4314 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4315 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4317 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4321 put_long_date_timespec(pdata,create_time_ts);
4322 put_long_date_timespec(pdata+8,atime_ts);
4323 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4324 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4325 SIVAL(pdata,32,mode);
4327 DEBUG(5,("SMB_QFBI - "));
4328 DEBUG(5,("create: %s ", ctime(&create_time)));
4329 DEBUG(5,("access: %s ", ctime(&atime)));
4330 DEBUG(5,("write: %s ", ctime(&mtime)));
4331 DEBUG(5,("change: %s ", ctime(&mtime)));
4332 DEBUG(5,("mode: %x\n", mode));
4335 case SMB_FILE_STANDARD_INFORMATION:
4336 case SMB_QUERY_FILE_STANDARD_INFO:
4338 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4340 SOFF_T(pdata,0,allocation_size);
4341 SOFF_T(pdata,8,file_size);
4342 SIVAL(pdata,16,nlink);
4343 SCVAL(pdata,20,delete_pending?1:0);
4344 SCVAL(pdata,21,(mode&aDIR)?1:0);
4345 SSVAL(pdata,22,0); /* Padding. */
4348 case SMB_FILE_EA_INFORMATION:
4349 case SMB_QUERY_FILE_EA_INFO:
4351 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4352 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4354 SIVAL(pdata,0,ea_size);
4358 /* Get the 8.3 name - used if NT SMB was negotiated. */
4359 case SMB_QUERY_FILE_ALT_NAME_INFO:
4360 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4362 char mangled_name[13];
4363 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4364 if (!name_to_8_3(base_name,mangled_name,
4365 True,conn->params)) {
4368 NT_STATUS_NO_MEMORY);
4370 len = srvstr_push(dstart, req->flags2,
4371 pdata+4, mangled_name,
4372 PTR_DIFF(dend, pdata+4),
4374 data_size = 4 + len;
4379 case SMB_QUERY_FILE_NAME_INFO:
4381 this must be *exactly* right for ACLs on mapped drives to work
4383 len = srvstr_push(dstart, req->flags2,
4385 PTR_DIFF(dend, pdata+4),
4387 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4388 data_size = 4 + len;
4392 case SMB_FILE_ALLOCATION_INFORMATION:
4393 case SMB_QUERY_FILE_ALLOCATION_INFO:
4394 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4396 SOFF_T(pdata,0,allocation_size);
4399 case SMB_FILE_END_OF_FILE_INFORMATION:
4400 case SMB_QUERY_FILE_END_OF_FILEINFO:
4401 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4403 SOFF_T(pdata,0,file_size);
4406 case SMB_QUERY_FILE_ALL_INFO:
4407 case SMB_FILE_ALL_INFORMATION:
4409 unsigned int ea_size = estimate_ea_size(conn, fsp, fname);
4410 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4411 put_long_date_timespec(pdata,create_time_ts);
4412 put_long_date_timespec(pdata+8,atime_ts);
4413 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4414 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4415 SIVAL(pdata,32,mode);
4416 SIVAL(pdata,36,0); /* padding. */
4418 SOFF_T(pdata,0,allocation_size);
4419 SOFF_T(pdata,8,file_size);
4420 SIVAL(pdata,16,nlink);
4421 SCVAL(pdata,20,delete_pending);
4422 SCVAL(pdata,21,(mode&aDIR)?1:0);
4425 SIVAL(pdata,0,ea_size);
4426 pdata += 4; /* EA info */
4427 len = srvstr_push(dstart, req->flags2,
4429 PTR_DIFF(dend, pdata+4),
4433 data_size = PTR_DIFF(pdata,(*ppdata));
4436 case SMB_FILE_INTERNAL_INFORMATION:
4437 /* This should be an index number - looks like
4440 I think this causes us to fail the IFSKIT
4441 BasicFileInformationTest. -tpot */
4443 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4444 SIVAL(pdata,0,sbuf.st_ino); /* FileIndexLow */
4445 SIVAL(pdata,4,sbuf.st_dev); /* FileIndexHigh */
4449 case SMB_FILE_ACCESS_INFORMATION:
4450 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4452 SIVAL(pdata,0,fsp->access_mask);
4454 /* GENERIC_EXECUTE mapping from Windows */
4455 SIVAL(pdata,0,0x12019F);
4460 case SMB_FILE_NAME_INFORMATION:
4461 /* Pathname with leading '\'. */
4464 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4465 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4466 SIVAL(pdata,0,byte_len);
4467 data_size = 4 + byte_len;
4471 case SMB_FILE_DISPOSITION_INFORMATION:
4472 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4474 SCVAL(pdata,0,delete_pending);
4477 case SMB_FILE_POSITION_INFORMATION:
4478 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4480 SOFF_T(pdata,0,pos);
4483 case SMB_FILE_MODE_INFORMATION:
4484 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4485 SIVAL(pdata,0,mode);
4489 case SMB_FILE_ALIGNMENT_INFORMATION:
4490 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4491 SIVAL(pdata,0,0); /* No alignment needed. */
4496 * NT4 server just returns "invalid query" to this - if we try
4497 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4500 /* The first statement above is false - verified using Thursby
4501 * client against NT4 -- gcolley.
4503 case SMB_QUERY_FILE_STREAM_INFO:
4504 case SMB_FILE_STREAM_INFORMATION: {
4505 unsigned int num_streams;
4506 struct stream_struct *streams;
4509 DEBUG(10,("call_trans2qfilepathinfo: "
4510 "SMB_FILE_STREAM_INFORMATION\n"));
4512 status = SMB_VFS_STREAMINFO(
4513 conn, fsp, fname, talloc_tos(),
4514 &num_streams, &streams);
4516 if (!NT_STATUS_IS_OK(status)) {
4517 DEBUG(10, ("could not get stream info: %s\n",
4518 nt_errstr(status)));
4519 reply_nterror(req, status);
4523 status = marshall_stream_info(num_streams, streams,
4524 pdata, max_data_bytes,
4527 if (!NT_STATUS_IS_OK(status)) {
4528 DEBUG(10, ("marshall_stream_info failed: %s\n",
4529 nt_errstr(status)));
4530 reply_nterror(req, status);
4534 TALLOC_FREE(streams);
4538 case SMB_QUERY_COMPRESSION_INFO:
4539 case SMB_FILE_COMPRESSION_INFORMATION:
4540 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4541 SOFF_T(pdata,0,file_size);
4542 SIVAL(pdata,8,0); /* ??? */
4543 SIVAL(pdata,12,0); /* ??? */
4547 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4548 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4549 put_long_date_timespec(pdata,create_time_ts);
4550 put_long_date_timespec(pdata+8,atime_ts);
4551 put_long_date_timespec(pdata+16,mtime_ts); /* write time */
4552 put_long_date_timespec(pdata+24,mtime_ts); /* change time */
4553 SOFF_T(pdata,32,allocation_size);
4554 SOFF_T(pdata,40,file_size);
4555 SIVAL(pdata,48,mode);
4556 SIVAL(pdata,52,0); /* ??? */
4560 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4561 DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4562 SIVAL(pdata,0,mode);
4568 * CIFS UNIX Extensions.
4571 case SMB_QUERY_FILE_UNIX_BASIC:
4573 pdata = store_file_unix_basic(conn, pdata, fsp, &sbuf);
4574 data_size = PTR_DIFF(pdata,(*ppdata));
4578 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4580 for (i=0; i<100; i++)
4581 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4587 case SMB_QUERY_FILE_UNIX_INFO2:
4589 pdata = store_file_unix_basic_info2(conn, pdata, fsp, &sbuf);
4590 data_size = PTR_DIFF(pdata,(*ppdata));
4594 DEBUG(4,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4596 for (i=0; i<100; i++)
4597 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4603 case SMB_QUERY_FILE_UNIX_LINK:
4605 char *buffer = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
4608 reply_nterror(req, NT_STATUS_NO_MEMORY);
4612 DEBUG(10,("call_trans2qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4614 if(!S_ISLNK(sbuf.st_mode)) {
4615 reply_unixerror(req, ERRSRV,
4620 reply_unixerror(req, ERRDOS, ERRbadlink);
4623 len = SMB_VFS_READLINK(conn,fullpathname,
4626 reply_unixerror(req, ERRDOS,
4631 len = srvstr_push(dstart, req->flags2,
4633 PTR_DIFF(dend, pdata),
4636 data_size = PTR_DIFF(pdata,(*ppdata));
4641 #if defined(HAVE_POSIX_ACLS)
4642 case SMB_QUERY_POSIX_ACL:
4644 SMB_ACL_T file_acl = NULL;
4645 SMB_ACL_T def_acl = NULL;
4646 uint16 num_file_acls = 0;
4647 uint16 num_def_acls = 0;
4649 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4650 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4652 file_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_ACCESS);
4655 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4656 DEBUG(5,("call_trans2qfilepathinfo: ACLs not implemented on filesystem containing %s\n",
4660 NT_STATUS_NOT_IMPLEMENTED);
4664 if (S_ISDIR(sbuf.st_mode)) {
4665 if (fsp && fsp->is_directory) {
4666 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fsp->fsp_name, SMB_ACL_TYPE_DEFAULT);
4668 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn, fname, SMB_ACL_TYPE_DEFAULT);
4670 def_acl = free_empty_sys_acl(conn, def_acl);
4673 num_file_acls = count_acl_entries(conn, file_acl);
4674 num_def_acls = count_acl_entries(conn, def_acl);
4676 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4677 DEBUG(5,("call_trans2qfilepathinfo: data_size too small (%u) need %u\n",
4679 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4680 SMB_POSIX_ACL_HEADER_SIZE) ));
4682 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4685 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4689 NT_STATUS_BUFFER_TOO_SMALL);
4693 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4694 SSVAL(pdata,2,num_file_acls);
4695 SSVAL(pdata,4,num_def_acls);
4696 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, &sbuf, file_acl)) {
4698 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4701 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4704 req, NT_STATUS_INTERNAL_ERROR);
4707 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), &sbuf, def_acl)) {
4709 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4712 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4716 NT_STATUS_INTERNAL_ERROR);
4721 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4724 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4726 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4732 case SMB_QUERY_POSIX_LOCK:
4734 NTSTATUS status = NT_STATUS_INVALID_LEVEL;
4738 enum brl_type lock_type;
4740 if (total_data != POSIX_LOCK_DATA_SIZE) {
4742 req, NT_STATUS_INVALID_PARAMETER);
4746 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4747 case POSIX_LOCK_TYPE_READ:
4748 lock_type = READ_LOCK;
4750 case POSIX_LOCK_TYPE_WRITE:
4751 lock_type = WRITE_LOCK;
4753 case POSIX_LOCK_TYPE_UNLOCK:
4755 /* There's no point in asking for an unlock... */
4758 NT_STATUS_INVALID_PARAMETER);
4762 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4763 #if defined(HAVE_LONGLONG)
4764 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4765 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4766 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4767 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4768 #else /* HAVE_LONGLONG */
4769 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4770 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4771 #endif /* HAVE_LONGLONG */
4773 status = query_lock(fsp,
4780 if (ERROR_WAS_LOCK_DENIED(status)) {
4781 /* Here we need to report who has it locked... */
4782 data_size = POSIX_LOCK_DATA_SIZE;
4784 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4785 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4786 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4787 #if defined(HAVE_LONGLONG)
4788 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4789 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4790 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4791 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4792 #else /* HAVE_LONGLONG */
4793 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4794 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4795 #endif /* HAVE_LONGLONG */
4797 } else if (NT_STATUS_IS_OK(status)) {
4798 /* For success we just return a copy of what we sent
4799 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4800 data_size = POSIX_LOCK_DATA_SIZE;
4801 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4802 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4804 reply_nterror(req, status);
4811 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4815 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4821 /****************************************************************************
4822 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4824 ****************************************************************************/
4826 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4827 connection_struct *conn,
4828 const char *oldname_in,
4829 const char *newname_in)
4831 SMB_STRUCT_STAT sbuf1, sbuf2;
4832 char *last_component_oldname = NULL;
4833 char *last_component_newname = NULL;
4834 char *oldname = NULL;
4835 char *newname = NULL;
4836 NTSTATUS status = NT_STATUS_OK;
4841 status = unix_convert(ctx, conn, oldname_in, False, &oldname,
4842 &last_component_oldname, &sbuf1);
4843 if (!NT_STATUS_IS_OK(status)) {
4847 status = check_name(conn, oldname);
4848 if (!NT_STATUS_IS_OK(status)) {
4852 /* source must already exist. */
4853 if (!VALID_STAT(sbuf1)) {
4854 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4857 status = unix_convert(ctx, conn, newname_in, False, &newname,
4858 &last_component_newname, &sbuf2);
4859 if (!NT_STATUS_IS_OK(status)) {
4863 status = check_name(conn, newname);
4864 if (!NT_STATUS_IS_OK(status)) {
4868 /* Disallow if newname already exists. */
4869 if (VALID_STAT(sbuf2)) {
4870 return NT_STATUS_OBJECT_NAME_COLLISION;
4873 /* No links from a directory. */
4874 if (S_ISDIR(sbuf1.st_mode)) {
4875 return NT_STATUS_FILE_IS_A_DIRECTORY;
4878 /* Ensure this is within the share. */
4879 status = check_reduced_name(conn, oldname);
4880 if (!NT_STATUS_IS_OK(status)) {
4884 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n", newname, oldname ));
4886 if (SMB_VFS_LINK(conn,oldname,newname) != 0) {
4887 status = map_nt_error_from_unix(errno);
4888 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4889 nt_errstr(status), newname, oldname));
4895 /****************************************************************************
4896 Deal with setting the time from any of the setfilepathinfo functions.
4897 ****************************************************************************/
4899 NTSTATUS smb_set_file_time(connection_struct *conn,
4902 const SMB_STRUCT_STAT *psbuf,
4903 struct timespec ts[2],
4904 bool setting_write_time)
4907 FILE_NOTIFY_CHANGE_LAST_ACCESS
4908 |FILE_NOTIFY_CHANGE_LAST_WRITE;
4910 if (!VALID_STAT(*psbuf)) {
4911 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4914 /* get some defaults (no modifications) if any info is zero or -1. */
4915 if (null_timespec(ts[0])) {
4916 ts[0] = get_atimespec(psbuf);
4917 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4920 if (null_timespec(ts[1])) {
4921 ts[1] = get_mtimespec(psbuf);
4922 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4925 if (!setting_write_time) {
4926 /* ts[1] comes from change time, not write time. */
4927 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4930 DEBUG(6,("smb_set_file_time: actime: %s " , time_to_asc(convert_timespec_to_time_t(ts[0])) ));
4931 DEBUG(6,("smb_set_file_time: modtime: %s ", time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4934 * Try and set the times of this file if
4935 * they are different from the current values.
4939 struct timespec mts = get_mtimespec(psbuf);
4940 struct timespec ats = get_atimespec(psbuf);
4941 if ((timespec_compare(&ts[0], &ats) == 0) && (timespec_compare(&ts[1], &mts) == 0)) {
4942 return NT_STATUS_OK;
4946 if (setting_write_time) {
4948 * This was a setfileinfo on an open file.
4949 * NT does this a lot. We also need to
4950 * set the time here, as it can be read by
4951 * FindFirst/FindNext and with the patch for bug #2045
4952 * in smbd/fileio.c it ensures that this timestamp is
4953 * kept sticky even after a write. We save the request
4954 * away and will set it on file close and after a write. JRA.
4957 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
4958 time_to_asc(convert_timespec_to_time_t(ts[1])) ));
4961 if (fsp->base_fsp) {
4962 set_sticky_write_time_fsp(fsp->base_fsp, ts[1]);
4964 set_sticky_write_time_fsp(fsp, ts[1]);
4967 set_sticky_write_time_path(conn, fname,
4968 vfs_file_id_from_sbuf(conn, psbuf),
4973 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4975 if (fsp && fsp->base_fsp) {
4976 fname = fsp->base_fsp->fsp_name;
4979 if(file_ntimes(conn, fname, ts)!=0) {
4980 return map_nt_error_from_unix(errno);
4982 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action, fname);
4984 return NT_STATUS_OK;
4987 /****************************************************************************
4988 Deal with setting the dosmode from any of the setfilepathinfo functions.
4989 ****************************************************************************/
4991 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4993 SMB_STRUCT_STAT *psbuf,
4996 if (!VALID_STAT(*psbuf)) {
4997 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5001 if (S_ISDIR(psbuf->st_mode)) {
5008 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5010 /* check the mode isn't different, before changing it */
5011 if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, psbuf))) {
5013 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode 0x%x\n",
5014 fname, (unsigned int)dosmode ));
5016 if(file_set_dosmode(conn, fname, dosmode, psbuf, NULL, false)) {
5017 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of %s failed (%s)\n",
5018 fname, strerror(errno)));
5019 return map_nt_error_from_unix(errno);
5022 return NT_STATUS_OK;
5025 /****************************************************************************
5026 Deal with setting the size from any of the setfilepathinfo functions.
5027 ****************************************************************************/
5029 static NTSTATUS smb_set_file_size(connection_struct *conn,
5030 struct smb_request *req,
5033 SMB_STRUCT_STAT *psbuf,
5036 NTSTATUS status = NT_STATUS_OK;
5037 files_struct *new_fsp = NULL;
5039 if (!VALID_STAT(*psbuf)) {
5040 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5043 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5045 if (size == get_file_size(*psbuf)) {
5046 return NT_STATUS_OK;
5049 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5050 fname, (double)size ));
5052 if (fsp && fsp->fh->fd != -1) {
5053 /* Handle based call. */
5054 if (vfs_set_filelen(fsp, size) == -1) {
5055 return map_nt_error_from_unix(errno);
5057 trigger_write_time_update_immediate(fsp);
5058 return NT_STATUS_OK;
5061 status = open_file_ntcreate(conn, req, fname, psbuf,
5062 FILE_WRITE_ATTRIBUTES,
5063 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5066 FILE_ATTRIBUTE_NORMAL,
5067 FORCE_OPLOCK_BREAK_TO_NONE,
5070 if (!NT_STATUS_IS_OK(status)) {
5071 /* NB. We check for open_was_deferred in the caller. */
5075 if (vfs_set_filelen(new_fsp, size) == -1) {
5076 status = map_nt_error_from_unix(errno);
5077 close_file(req, new_fsp,NORMAL_CLOSE);
5081 trigger_write_time_update_immediate(new_fsp);
5082 close_file(req, new_fsp,NORMAL_CLOSE);
5083 return NT_STATUS_OK;
5086 /****************************************************************************
5087 Deal with SMB_INFO_SET_EA.
5088 ****************************************************************************/
5090 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5096 struct ea_list *ea_list = NULL;
5097 TALLOC_CTX *ctx = NULL;
5098 NTSTATUS status = NT_STATUS_OK;
5100 if (total_data < 10) {
5102 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5103 length. They seem to have no effect. Bug #3212. JRA */
5105 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5106 /* We're done. We only get EA info in this call. */
5107 return NT_STATUS_OK;
5110 return NT_STATUS_INVALID_PARAMETER;
5113 if (IVAL(pdata,0) > total_data) {
5114 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5115 IVAL(pdata,0), (unsigned int)total_data));
5116 return NT_STATUS_INVALID_PARAMETER;
5120 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5122 return NT_STATUS_INVALID_PARAMETER;
5124 status = set_ea(conn, fsp, fname, ea_list);
5129 /****************************************************************************
5130 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5131 ****************************************************************************/
5133 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5138 SMB_STRUCT_STAT *psbuf)
5140 NTSTATUS status = NT_STATUS_OK;
5141 bool delete_on_close;
5144 if (total_data < 1) {
5145 return NT_STATUS_INVALID_PARAMETER;
5149 return NT_STATUS_INVALID_HANDLE;
5152 delete_on_close = (CVAL(pdata,0) ? True : False);
5153 dosmode = dos_mode(conn, fname, psbuf);
5155 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5156 "delete_on_close = %u\n",
5158 (unsigned int)dosmode,
5159 (unsigned int)delete_on_close ));
5161 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5163 if (!NT_STATUS_IS_OK(status)) {
5167 /* The set is across all open files on this dev/inode pair. */
5168 if (!set_delete_on_close(fsp, delete_on_close,
5169 &conn->server_info->utok)) {
5170 return NT_STATUS_ACCESS_DENIED;
5172 return NT_STATUS_OK;
5175 /****************************************************************************
5176 Deal with SMB_FILE_POSITION_INFORMATION.
5177 ****************************************************************************/
5179 static NTSTATUS smb_file_position_information(connection_struct *conn,
5184 uint64_t position_information;
5186 if (total_data < 8) {
5187 return NT_STATUS_INVALID_PARAMETER;
5191 /* Ignore on pathname based set. */
5192 return NT_STATUS_OK;
5195 position_information = (uint64_t)IVAL(pdata,0);
5196 #ifdef LARGE_SMB_OFF_T
5197 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5198 #else /* LARGE_SMB_OFF_T */
5199 if (IVAL(pdata,4) != 0) {
5200 /* more than 32 bits? */
5201 return NT_STATUS_INVALID_PARAMETER;
5203 #endif /* LARGE_SMB_OFF_T */
5205 DEBUG(10,("smb_file_position_information: Set file position information for file %s to %.0f\n",
5206 fsp->fsp_name, (double)position_information ));
5207 fsp->fh->position_information = position_information;
5208 return NT_STATUS_OK;
5211 /****************************************************************************
5212 Deal with SMB_FILE_MODE_INFORMATION.
5213 ****************************************************************************/
5215 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5221 if (total_data < 4) {
5222 return NT_STATUS_INVALID_PARAMETER;
5224 mode = IVAL(pdata,0);
5225 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5226 return NT_STATUS_INVALID_PARAMETER;
5228 return NT_STATUS_OK;
5231 /****************************************************************************
5232 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5233 ****************************************************************************/
5235 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5236 struct smb_request *req,
5241 char *link_target = NULL;
5242 const char *newname = fname;
5243 NTSTATUS status = NT_STATUS_OK;
5244 TALLOC_CTX *ctx = talloc_tos();
5246 /* Set a symbolic link. */
5247 /* Don't allow this if follow links is false. */
5249 if (total_data == 0) {
5250 return NT_STATUS_INVALID_PARAMETER;
5253 if (!lp_symlinks(SNUM(conn))) {
5254 return NT_STATUS_ACCESS_DENIED;
5257 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5258 total_data, STR_TERMINATE);
5261 return NT_STATUS_INVALID_PARAMETER;
5264 /* !widelinks forces the target path to be within the share. */
5265 /* This means we can interpret the target as a pathname. */
5266 if (!lp_widelinks(SNUM(conn))) {
5267 char *rel_name = NULL;
5268 char *last_dirp = NULL;
5270 if (*link_target == '/') {
5271 /* No absolute paths allowed. */
5272 return NT_STATUS_ACCESS_DENIED;
5274 rel_name = talloc_strdup(ctx,newname);
5276 return NT_STATUS_NO_MEMORY;
5278 last_dirp = strrchr_m(rel_name, '/');
5280 last_dirp[1] = '\0';
5282 rel_name = talloc_strdup(ctx,"./");
5284 return NT_STATUS_NO_MEMORY;
5287 rel_name = talloc_asprintf_append(rel_name,
5291 return NT_STATUS_NO_MEMORY;
5294 status = check_name(conn, rel_name);
5295 if (!NT_STATUS_IS_OK(status)) {
5300 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5301 newname, link_target ));
5303 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5304 return map_nt_error_from_unix(errno);
5307 return NT_STATUS_OK;
5310 /****************************************************************************
5311 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5312 ****************************************************************************/
5314 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5315 struct smb_request *req,
5316 const char *pdata, int total_data,
5319 char *oldname = NULL;
5320 TALLOC_CTX *ctx = talloc_tos();
5321 NTSTATUS status = NT_STATUS_OK;
5323 /* Set a hard link. */
5324 if (total_data == 0) {
5325 return NT_STATUS_INVALID_PARAMETER;
5328 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5329 total_data, STR_TERMINATE, &status);
5330 if (!NT_STATUS_IS_OK(status)) {
5334 status = resolve_dfspath(ctx, conn,
5335 req->flags2 & FLAGS2_DFS_PATHNAMES,
5338 if (!NT_STATUS_IS_OK(status)) {
5342 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5345 return hardlink_internals(ctx, conn, oldname, fname);
5348 /****************************************************************************
5349 Deal with SMB_FILE_RENAME_INFORMATION.
5350 ****************************************************************************/
5352 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5353 struct smb_request *req,
5362 char *newname = NULL;
5363 char *base_name = NULL;
5364 bool dest_has_wcard = False;
5365 NTSTATUS status = NT_STATUS_OK;
5367 TALLOC_CTX *ctx = talloc_tos();
5369 if (total_data < 13) {
5370 return NT_STATUS_INVALID_PARAMETER;
5373 overwrite = (CVAL(pdata,0) ? True : False);
5374 root_fid = IVAL(pdata,4);
5375 len = IVAL(pdata,8);
5377 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5378 return NT_STATUS_INVALID_PARAMETER;
5381 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5384 if (!NT_STATUS_IS_OK(status)) {
5388 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5391 status = resolve_dfspath_wcard(ctx, conn,
5392 req->flags2 & FLAGS2_DFS_PATHNAMES,
5396 if (!NT_STATUS_IS_OK(status)) {
5400 /* Check the new name has no '/' characters. */
5401 if (strchr_m(newname, '/')) {
5402 return NT_STATUS_NOT_SUPPORTED;
5405 if (fsp && fsp->base_fsp) {
5406 if (newname[0] != ':') {
5407 return NT_STATUS_NOT_SUPPORTED;
5409 base_name = talloc_asprintf(ctx, "%s%s",
5410 fsp->base_fsp->fsp_name,
5413 return NT_STATUS_NO_MEMORY;
5416 if (is_ntfs_stream_name(newname)) {
5417 return NT_STATUS_NOT_SUPPORTED;
5420 /* Create the base directory. */
5421 base_name = talloc_strdup(ctx, fname);
5423 return NT_STATUS_NO_MEMORY;
5425 p = strrchr_m(base_name, '/');
5429 base_name = talloc_strdup(ctx, "./");
5431 return NT_STATUS_NO_MEMORY;
5434 /* Append the new name. */
5435 base_name = talloc_asprintf_append(base_name,
5439 return NT_STATUS_NO_MEMORY;
5444 SMB_STRUCT_STAT sbuf;
5445 char *newname_last_component = NULL;
5449 status = unix_convert(ctx, conn, newname, False,
5451 &newname_last_component,
5454 /* If an error we expect this to be
5455 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
5457 if (!NT_STATUS_IS_OK(status)
5458 && !NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
5463 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
5464 fsp->fnum, fsp->fsp_name, base_name ));
5465 status = rename_internals_fsp(conn, fsp, base_name,
5466 newname_last_component, 0,
5469 DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5470 fname, base_name ));
5471 status = rename_internals(ctx, conn, req, fname, base_name, 0,
5472 overwrite, False, dest_has_wcard,
5473 FILE_WRITE_ATTRIBUTES);
5479 /****************************************************************************
5480 Deal with SMB_SET_POSIX_ACL.
5481 ****************************************************************************/
5483 #if defined(HAVE_POSIX_ACLS)
5484 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5489 SMB_STRUCT_STAT *psbuf)
5491 uint16 posix_acl_version;
5492 uint16 num_file_acls;
5493 uint16 num_def_acls;
5494 bool valid_file_acls = True;
5495 bool valid_def_acls = True;
5497 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5498 return NT_STATUS_INVALID_PARAMETER;
5500 posix_acl_version = SVAL(pdata,0);
5501 num_file_acls = SVAL(pdata,2);
5502 num_def_acls = SVAL(pdata,4);
5504 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5505 valid_file_acls = False;
5509 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5510 valid_def_acls = False;
5514 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5515 return NT_STATUS_INVALID_PARAMETER;
5518 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
5519 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
5520 return NT_STATUS_INVALID_PARAMETER;
5523 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
5524 fname ? fname : fsp->fsp_name,
5525 (unsigned int)num_file_acls,
5526 (unsigned int)num_def_acls));
5528 if (valid_file_acls && !set_unix_posix_acl(conn, fsp, fname, num_file_acls,
5529 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
5530 return map_nt_error_from_unix(errno);
5533 if (valid_def_acls && !set_unix_posix_default_acl(conn, fname, psbuf, num_def_acls,
5534 pdata + SMB_POSIX_ACL_HEADER_SIZE +
5535 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
5536 return map_nt_error_from_unix(errno);
5538 return NT_STATUS_OK;
5542 /****************************************************************************
5543 Deal with SMB_SET_POSIX_LOCK.
5544 ****************************************************************************/
5546 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
5547 struct smb_request *req,
5555 bool blocking_lock = False;
5556 enum brl_type lock_type;
5558 NTSTATUS status = NT_STATUS_OK;
5560 if (fsp == NULL || fsp->fh->fd == -1) {
5561 return NT_STATUS_INVALID_HANDLE;
5564 if (total_data != POSIX_LOCK_DATA_SIZE) {
5565 return NT_STATUS_INVALID_PARAMETER;
5568 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5569 case POSIX_LOCK_TYPE_READ:
5570 lock_type = READ_LOCK;
5572 case POSIX_LOCK_TYPE_WRITE:
5573 /* Return the right POSIX-mappable error code for files opened read-only. */
5574 if (!fsp->can_write) {
5575 return NT_STATUS_INVALID_HANDLE;
5577 lock_type = WRITE_LOCK;
5579 case POSIX_LOCK_TYPE_UNLOCK:
5580 lock_type = UNLOCK_LOCK;
5583 return NT_STATUS_INVALID_PARAMETER;
5586 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
5587 blocking_lock = False;
5588 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
5589 blocking_lock = True;
5591 return NT_STATUS_INVALID_PARAMETER;
5594 if (!lp_blocking_locks(SNUM(conn))) {
5595 blocking_lock = False;
5598 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5599 #if defined(HAVE_LONGLONG)
5600 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5601 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5602 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5603 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5604 #else /* HAVE_LONGLONG */
5605 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5606 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5607 #endif /* HAVE_LONGLONG */
5609 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
5610 "lock_pid = %u, count = %.0f, offset = %.0f\n",
5612 (unsigned int)lock_type,
5613 (unsigned int)lock_pid,
5617 if (lock_type == UNLOCK_LOCK) {
5618 status = do_unlock(smbd_messaging_context(),
5625 uint32 block_smbpid;
5627 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
5638 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
5640 * A blocking lock was requested. Package up
5641 * this smb into a queued request and push it
5642 * onto the blocking lock queue.
5644 if(push_blocking_lock_request(br_lck,
5647 -1, /* infinite timeout. */
5655 TALLOC_FREE(br_lck);
5659 TALLOC_FREE(br_lck);
5665 /****************************************************************************
5666 Deal with SMB_INFO_STANDARD.
5667 ****************************************************************************/
5669 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5674 const SMB_STRUCT_STAT *psbuf)
5676 struct timespec ts[2];
5678 if (total_data < 12) {
5679 return NT_STATUS_INVALID_PARAMETER;
5683 ts[0] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastAccess));
5685 ts[1] = convert_time_t_to_timespec(srv_make_unix_date2(pdata+l1_fdateLastWrite));
5687 DEBUG(10,("smb_set_info_standard: file %s\n",
5688 fname ? fname : fsp->fsp_name ));
5690 return smb_set_file_time(conn,
5698 /****************************************************************************
5699 Deal with SMB_SET_FILE_BASIC_INFO.
5700 ****************************************************************************/
5702 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5707 SMB_STRUCT_STAT *psbuf)
5709 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5710 struct timespec write_time;
5711 struct timespec changed_time;
5713 struct timespec ts[2];
5714 NTSTATUS status = NT_STATUS_OK;
5715 bool setting_write_time = true;
5717 if (total_data < 36) {
5718 return NT_STATUS_INVALID_PARAMETER;
5721 /* Set the attributes */
5722 dosmode = IVAL(pdata,32);
5723 status = smb_set_file_dosmode(conn,
5727 if (!NT_STATUS_IS_OK(status)) {
5731 /* Ignore create time at offset pdata. */
5734 ts[0] = interpret_long_date(pdata+8);
5736 write_time = interpret_long_date(pdata+16);
5737 changed_time = interpret_long_date(pdata+24);
5740 ts[1] = timespec_min(&write_time, &changed_time);
5742 if ((timespec_compare(&write_time, &ts[1]) == 1) && !null_timespec(write_time)) {
5746 /* Prefer a defined time to an undefined one. */
5747 if (null_timespec(ts[1])) {
5748 if (null_timespec(write_time)) {
5749 ts[1] = changed_time;
5750 setting_write_time = false;
5756 DEBUG(10,("smb_set_file_basic_info: file %s\n",
5757 fname ? fname : fsp->fsp_name ));
5759 return smb_set_file_time(conn,
5764 setting_write_time);
5767 /****************************************************************************
5768 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5769 ****************************************************************************/
5771 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5772 struct smb_request *req,
5777 SMB_STRUCT_STAT *psbuf)
5779 uint64_t allocation_size = 0;
5780 NTSTATUS status = NT_STATUS_OK;
5781 files_struct *new_fsp = NULL;
5783 if (!VALID_STAT(*psbuf)) {
5784 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5787 if (total_data < 8) {
5788 return NT_STATUS_INVALID_PARAMETER;
5791 allocation_size = (uint64_t)IVAL(pdata,0);
5792 #ifdef LARGE_SMB_OFF_T
5793 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5794 #else /* LARGE_SMB_OFF_T */
5795 if (IVAL(pdata,4) != 0) {
5796 /* more than 32 bits? */
5797 return NT_STATUS_INVALID_PARAMETER;
5799 #endif /* LARGE_SMB_OFF_T */
5801 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for file %s to %.0f\n",
5802 fname, (double)allocation_size ));
5804 if (allocation_size) {
5805 allocation_size = smb_roundup(conn, allocation_size);
5808 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
5809 fname, (double)allocation_size ));
5811 if (fsp && fsp->fh->fd != -1) {
5812 /* Open file handle. */
5813 /* Only change if needed. */
5814 if (allocation_size != get_file_size(*psbuf)) {
5815 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5816 return map_nt_error_from_unix(errno);
5819 /* But always update the time. */
5821 * This is equivalent to a write. Ensure it's seen immediately
5822 * if there are no pending writes.
5824 trigger_write_time_update_immediate(fsp);
5825 return NT_STATUS_OK;
5828 /* Pathname or stat or directory file. */
5830 status = open_file_ntcreate(conn, req, fname, psbuf,
5832 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
5835 FILE_ATTRIBUTE_NORMAL,
5836 FORCE_OPLOCK_BREAK_TO_NONE,
5839 if (!NT_STATUS_IS_OK(status)) {
5840 /* NB. We check for open_was_deferred in the caller. */
5844 /* Only change if needed. */
5845 if (allocation_size != get_file_size(*psbuf)) {
5846 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5847 status = map_nt_error_from_unix(errno);
5848 close_file(req, new_fsp, NORMAL_CLOSE);
5853 /* Changing the allocation size should set the last mod time. */
5855 * This is equivalent to a write. Ensure it's seen immediately
5856 * if there are no pending writes.
5858 trigger_write_time_update_immediate(new_fsp);
5860 close_file(req, new_fsp, NORMAL_CLOSE);
5861 return NT_STATUS_OK;
5864 /****************************************************************************
5865 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5866 ****************************************************************************/
5868 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5869 struct smb_request *req,
5874 SMB_STRUCT_STAT *psbuf)
5878 if (total_data < 8) {
5879 return NT_STATUS_INVALID_PARAMETER;
5882 size = IVAL(pdata,0);
5883 #ifdef LARGE_SMB_OFF_T
5884 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
5885 #else /* LARGE_SMB_OFF_T */
5886 if (IVAL(pdata,4) != 0) {
5887 /* more than 32 bits? */
5888 return NT_STATUS_INVALID_PARAMETER;
5890 #endif /* LARGE_SMB_OFF_T */
5891 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5892 "file %s to %.0f\n", fname, (double)size ));
5894 return smb_set_file_size(conn, req,
5901 /****************************************************************************
5902 Allow a UNIX info mknod.
5903 ****************************************************************************/
5905 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5909 SMB_STRUCT_STAT *psbuf)
5911 uint32 file_type = IVAL(pdata,56);
5912 #if defined(HAVE_MAKEDEV)
5913 uint32 dev_major = IVAL(pdata,60);
5914 uint32 dev_minor = IVAL(pdata,68);
5916 SMB_DEV_T dev = (SMB_DEV_T)0;
5917 uint32 raw_unixmode = IVAL(pdata,84);
5921 if (total_data < 100) {
5922 return NT_STATUS_INVALID_PARAMETER;
5925 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_FILE, &unixmode);
5926 if (!NT_STATUS_IS_OK(status)) {
5930 #if defined(HAVE_MAKEDEV)
5931 dev = makedev(dev_major, dev_minor);
5934 switch (file_type) {
5935 #if defined(S_IFIFO)
5936 case UNIX_TYPE_FIFO:
5937 unixmode |= S_IFIFO;
5940 #if defined(S_IFSOCK)
5941 case UNIX_TYPE_SOCKET:
5942 unixmode |= S_IFSOCK;
5945 #if defined(S_IFCHR)
5946 case UNIX_TYPE_CHARDEV:
5947 unixmode |= S_IFCHR;
5950 #if defined(S_IFBLK)
5951 case UNIX_TYPE_BLKDEV:
5952 unixmode |= S_IFBLK;
5956 return NT_STATUS_INVALID_PARAMETER;
5959 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev %.0f mode \
5960 0%o for file %s\n", (double)dev, (unsigned int)unixmode, fname ));
5962 /* Ok - do the mknod. */
5963 if (SMB_VFS_MKNOD(conn, fname, unixmode, dev) != 0) {
5964 return map_nt_error_from_unix(errno);
5967 /* If any of the other "set" calls fail we
5968 * don't want to end up with a half-constructed mknod.
5971 if (lp_inherit_perms(SNUM(conn))) {
5972 inherit_access_posix_acl(
5973 conn, parent_dirname(fname),
5977 if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
5978 status = map_nt_error_from_unix(errno);
5979 SMB_VFS_UNLINK(conn,fname);
5982 return NT_STATUS_OK;
5985 /****************************************************************************
5986 Deal with SMB_SET_FILE_UNIX_BASIC.
5987 ****************************************************************************/
5989 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5990 struct smb_request *req,
5995 SMB_STRUCT_STAT *psbuf)
5997 struct timespec ts[2];
5998 uint32 raw_unixmode;
6001 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6002 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6003 NTSTATUS status = NT_STATUS_OK;
6004 bool delete_on_fail = False;
6005 enum perm_type ptype;
6007 if (total_data < 100) {
6008 return NT_STATUS_INVALID_PARAMETER;
6011 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6012 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6013 size=IVAL(pdata,0); /* first 8 Bytes are size */
6014 #ifdef LARGE_SMB_OFF_T
6015 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6016 #else /* LARGE_SMB_OFF_T */
6017 if (IVAL(pdata,4) != 0) {
6018 /* more than 32 bits? */
6019 return NT_STATUS_INVALID_PARAMETER;
6021 #endif /* LARGE_SMB_OFF_T */
6024 ts[0] = interpret_long_date(pdata+24); /* access_time */
6025 ts[1] = interpret_long_date(pdata+32); /* modification_time */
6026 set_owner = (uid_t)IVAL(pdata,40);
6027 set_grp = (gid_t)IVAL(pdata,48);
6028 raw_unixmode = IVAL(pdata,84);
6030 if (VALID_STAT(*psbuf)) {
6031 if (S_ISDIR(psbuf->st_mode)) {
6032 ptype = PERM_EXISTING_DIR;
6034 ptype = PERM_EXISTING_FILE;
6037 ptype = PERM_NEW_FILE;
6040 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, ptype, &unixmode);
6041 if (!NT_STATUS_IS_OK(status)) {
6045 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = %s \
6046 size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6047 fname, (double)size, (unsigned int)set_owner, (unsigned int)set_grp, (int)raw_unixmode));
6049 if (!VALID_STAT(*psbuf)) {
6051 * The only valid use of this is to create character and block
6052 * devices, and named pipes. This is deprecated (IMHO) and
6053 * a new info level should be used for mknod. JRA.
6056 status = smb_unix_mknod(conn,
6061 if (!NT_STATUS_IS_OK(status)) {
6065 /* Ensure we don't try and change anything else. */
6066 raw_unixmode = SMB_MODE_NO_CHANGE;
6067 size = get_file_size(*psbuf);
6068 ts[0] = get_atimespec(psbuf);
6069 ts[1] = get_mtimespec(psbuf);
6071 * We continue here as we might want to change the
6074 delete_on_fail = True;
6078 /* Horrible backwards compatibility hack as an old server bug
6079 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6083 size = get_file_size(*psbuf);
6088 * Deal with the UNIX specific mode set.
6091 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6092 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC setting mode 0%o for file %s\n",
6093 (unsigned int)unixmode, fname ));
6094 if (SMB_VFS_CHMOD(conn, fname, unixmode) != 0) {
6095 return map_nt_error_from_unix(errno);
6100 * Deal with the UNIX specific uid set.
6103 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
6106 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
6107 (unsigned int)set_owner, fname ));
6109 if (S_ISLNK(psbuf->st_mode)) {
6110 ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
6112 ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
6116 status = map_nt_error_from_unix(errno);
6117 if (delete_on_fail) {
6118 SMB_VFS_UNLINK(conn,fname);
6125 * Deal with the UNIX specific gid set.
6128 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) && (psbuf->st_gid != set_grp)) {
6129 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing group %u for file %s\n",
6130 (unsigned int)set_owner, fname ));
6131 if (SMB_VFS_CHOWN(conn, fname, (uid_t)-1, set_grp) != 0) {
6132 status = map_nt_error_from_unix(errno);
6133 if (delete_on_fail) {
6134 SMB_VFS_UNLINK(conn,fname);
6140 /* Deal with any size changes. */
6142 status = smb_set_file_size(conn, req,
6147 if (!NT_STATUS_IS_OK(status)) {
6151 /* Deal with any time changes. */
6153 return smb_set_file_time(conn,
6161 /****************************************************************************
6162 Deal with SMB_SET_FILE_UNIX_INFO2.
6163 ****************************************************************************/
6165 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6166 struct smb_request *req,
6171 SMB_STRUCT_STAT *psbuf)
6177 if (total_data < 116) {
6178 return NT_STATUS_INVALID_PARAMETER;
6181 /* Start by setting all the fields that are common between UNIX_BASIC
6184 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6186 if (!NT_STATUS_IS_OK(status)) {
6190 smb_fflags = IVAL(pdata, 108);
6191 smb_fmask = IVAL(pdata, 112);
6193 /* NB: We should only attempt to alter the file flags if the client
6194 * sends a non-zero mask.
6196 if (smb_fmask != 0) {
6197 int stat_fflags = 0;
6199 if (!map_info2_flags_to_sbuf(psbuf, smb_fflags, smb_fmask,
6201 /* Client asked to alter a flag we don't understand. */
6202 return NT_STATUS_INVALID_PARAMETER;
6205 if (fsp && fsp->fh->fd != -1) {
6206 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6207 return NT_STATUS_NOT_SUPPORTED;
6209 if (SMB_VFS_CHFLAGS(conn, fname, stat_fflags) != 0) {
6210 return map_nt_error_from_unix(errno);
6215 /* XXX: need to add support for changing the create_time here. You
6216 * can do this for paths on Darwin with setattrlist(2). The right way
6217 * to hook this up is probably by extending the VFS utimes interface.
6220 return NT_STATUS_OK;
6223 /****************************************************************************
6224 Create a directory with POSIX semantics.
6225 ****************************************************************************/
6227 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6228 struct smb_request *req,
6232 SMB_STRUCT_STAT *psbuf,
6233 int *pdata_return_size)
6235 NTSTATUS status = NT_STATUS_OK;
6236 uint32 raw_unixmode = 0;
6237 uint32 mod_unixmode = 0;
6238 mode_t unixmode = (mode_t)0;
6239 files_struct *fsp = NULL;
6240 uint16 info_level_return = 0;
6242 char *pdata = *ppdata;
6244 if (total_data < 18) {
6245 return NT_STATUS_INVALID_PARAMETER;
6248 raw_unixmode = IVAL(pdata,8);
6249 /* Next 4 bytes are not yet defined. */
6251 status = unix_perms_from_wire(conn, psbuf, raw_unixmode, PERM_NEW_DIR, &unixmode);
6252 if (!NT_STATUS_IS_OK(status)) {
6256 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6258 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6259 fname, (unsigned int)unixmode ));
6261 status = open_directory(conn, req,
6264 FILE_READ_ATTRIBUTES, /* Just a stat open */
6265 FILE_SHARE_NONE, /* Ignored for stat opens */
6272 if (NT_STATUS_IS_OK(status)) {
6273 close_file(req, fsp, NORMAL_CLOSE);
6276 info_level_return = SVAL(pdata,16);
6278 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6279 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6280 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6281 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6283 *pdata_return_size = 12;
6286 /* Realloc the data size */
6287 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6288 if (*ppdata == NULL) {
6289 *pdata_return_size = 0;
6290 return NT_STATUS_NO_MEMORY;
6294 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6295 SSVAL(pdata,2,0); /* No fnum. */
6296 SIVAL(pdata,4,info); /* Was directory created. */
6298 switch (info_level_return) {
6299 case SMB_QUERY_FILE_UNIX_BASIC:
6300 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6301 SSVAL(pdata,10,0); /* Padding. */
6302 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6304 case SMB_QUERY_FILE_UNIX_INFO2:
6305 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6306 SSVAL(pdata,10,0); /* Padding. */
6307 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6310 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6311 SSVAL(pdata,10,0); /* Padding. */
6318 /****************************************************************************
6319 Open/Create a file with POSIX semantics.
6320 ****************************************************************************/
6322 static NTSTATUS smb_posix_open(connection_struct *conn,
6323 struct smb_request *req,
6327 SMB_STRUCT_STAT *psbuf,
6328 int *pdata_return_size)
6330 bool extended_oplock_granted = False;
6331 char *pdata = *ppdata;
6333 uint32 wire_open_mode = 0;
6334 uint32 raw_unixmode = 0;
6335 uint32 mod_unixmode = 0;
6336 uint32 create_disp = 0;
6337 uint32 access_mask = 0;
6338 uint32 create_options = 0;
6339 NTSTATUS status = NT_STATUS_OK;
6340 mode_t unixmode = (mode_t)0;
6341 files_struct *fsp = NULL;
6342 int oplock_request = 0;
6344 uint16 info_level_return = 0;
6346 if (total_data < 18) {
6347 return NT_STATUS_INVALID_PARAMETER;
6350 flags = IVAL(pdata,0);
6351 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
6352 if (oplock_request) {
6353 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
6356 wire_open_mode = IVAL(pdata,4);
6358 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
6359 return smb_posix_mkdir(conn, req,
6367 switch (wire_open_mode & SMB_ACCMODE) {
6369 access_mask = FILE_READ_DATA;
6372 access_mask = FILE_WRITE_DATA;
6375 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
6378 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
6379 (unsigned int)wire_open_mode ));
6380 return NT_STATUS_INVALID_PARAMETER;
6383 wire_open_mode &= ~SMB_ACCMODE;
6385 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
6386 create_disp = FILE_CREATE;
6387 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
6388 create_disp = FILE_OVERWRITE_IF;
6389 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
6390 create_disp = FILE_OPEN_IF;
6392 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
6393 (unsigned int)wire_open_mode ));
6394 return NT_STATUS_INVALID_PARAMETER;
6397 raw_unixmode = IVAL(pdata,8);
6398 /* Next 4 bytes are not yet defined. */
6400 status = unix_perms_from_wire(conn,
6403 VALID_STAT(*psbuf) ? PERM_EXISTING_FILE : PERM_NEW_FILE,
6406 if (!NT_STATUS_IS_OK(status)) {
6410 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6412 if (wire_open_mode & SMB_O_SYNC) {
6413 create_options |= FILE_WRITE_THROUGH;
6415 if (wire_open_mode & SMB_O_APPEND) {
6416 access_mask |= FILE_APPEND_DATA;
6418 if (wire_open_mode & SMB_O_DIRECT) {
6419 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
6422 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
6424 (unsigned int)wire_open_mode,
6425 (unsigned int)unixmode ));
6427 status = open_file_ntcreate(conn, req,
6431 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6433 0, /* no create options yet. */
6439 if (!NT_STATUS_IS_OK(status)) {
6443 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
6444 extended_oplock_granted = True;
6447 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
6448 extended_oplock_granted = True;
6451 info_level_return = SVAL(pdata,16);
6453 /* Allocate the correct return size. */
6455 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6456 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6457 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6458 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6460 *pdata_return_size = 12;
6463 /* Realloc the data size */
6464 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6465 if (*ppdata == NULL) {
6466 close_file(req, fsp, ERROR_CLOSE);
6467 *pdata_return_size = 0;
6468 return NT_STATUS_NO_MEMORY;
6472 if (extended_oplock_granted) {
6473 if (flags & REQUEST_BATCH_OPLOCK) {
6474 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
6476 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
6478 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
6479 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
6481 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6484 SSVAL(pdata,2,fsp->fnum);
6485 SIVAL(pdata,4,info); /* Was file created etc. */
6487 switch (info_level_return) {
6488 case SMB_QUERY_FILE_UNIX_BASIC:
6489 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6490 SSVAL(pdata,10,0); /* padding. */
6491 store_file_unix_basic(conn, pdata + 12, fsp, psbuf);
6493 case SMB_QUERY_FILE_UNIX_INFO2:
6494 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
6495 SSVAL(pdata,10,0); /* padding. */
6496 store_file_unix_basic_info2(conn, pdata + 12, fsp, psbuf);
6499 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
6500 SSVAL(pdata,10,0); /* padding. */
6503 return NT_STATUS_OK;
6506 /****************************************************************************
6507 Delete a file with POSIX semantics.
6508 ****************************************************************************/
6510 static NTSTATUS smb_posix_unlink(connection_struct *conn,
6511 struct smb_request *req,
6515 SMB_STRUCT_STAT *psbuf)
6517 NTSTATUS status = NT_STATUS_OK;
6518 files_struct *fsp = NULL;
6523 struct share_mode_lock *lck = NULL;
6525 if (total_data < 2) {
6526 return NT_STATUS_INVALID_PARAMETER;
6529 flags = SVAL(pdata,0);
6531 if (!VALID_STAT(*psbuf)) {
6532 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6535 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
6536 !VALID_STAT_OF_DIR(*psbuf)) {
6537 return NT_STATUS_NOT_A_DIRECTORY;
6540 DEBUG(10,("smb_posix_unlink: %s %s\n",
6541 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
6544 if (VALID_STAT_OF_DIR(*psbuf)) {
6545 status = open_directory(conn, req,
6549 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6552 FILE_FLAG_POSIX_SEMANTICS|0777,
6557 status = open_file_ntcreate(conn, req,
6561 FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
6564 FILE_FLAG_POSIX_SEMANTICS|0777,
6565 0, /* No oplock, but break existing ones. */
6570 if (!NT_STATUS_IS_OK(status)) {
6575 * Don't lie to client. If we can't really delete due to
6576 * non-POSIX opens return SHARING_VIOLATION.
6579 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
6582 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
6583 "lock for file %s\n", fsp->fsp_name));
6584 close_file(req, fsp, NORMAL_CLOSE);
6585 return NT_STATUS_INVALID_PARAMETER;
6589 * See if others still have the file open. If this is the case, then
6590 * don't delete. If all opens are POSIX delete we can set the delete
6591 * on close disposition.
6593 for (i=0; i<lck->num_share_modes; i++) {
6594 struct share_mode_entry *e = &lck->share_modes[i];
6595 if (is_valid_share_mode_entry(e)) {
6596 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
6599 /* Fail with sharing violation. */
6600 close_file(req, fsp, NORMAL_CLOSE);
6602 return NT_STATUS_SHARING_VIOLATION;
6607 * Set the delete on close.
6609 status = smb_set_file_disposition_info(conn,
6616 if (!NT_STATUS_IS_OK(status)) {
6617 close_file(req, fsp, NORMAL_CLOSE);
6622 return close_file(req, fsp, NORMAL_CLOSE);
6625 /****************************************************************************
6626 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
6627 ****************************************************************************/
6629 static void call_trans2setfilepathinfo(connection_struct *conn,
6630 struct smb_request *req,
6631 unsigned int tran_call,
6632 char **pparams, int total_params,
6633 char **ppdata, int total_data,
6634 unsigned int max_data_bytes)
6636 char *params = *pparams;
6637 char *pdata = *ppdata;
6639 SMB_STRUCT_STAT sbuf;
6641 files_struct *fsp = NULL;
6642 NTSTATUS status = NT_STATUS_OK;
6643 int data_return_size = 0;
6644 TALLOC_CTX *ctx = talloc_tos();
6647 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6653 if (tran_call == TRANSACT2_SETFILEINFO) {
6654 if (total_params < 4) {
6655 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6659 fsp = file_fsp(req, SVAL(params,0));
6660 /* Basic check for non-null fsp. */
6661 if (!check_fsp_open(conn, req, fsp)) {
6664 info_level = SVAL(params,2);
6666 fname = talloc_strdup(talloc_tos(),fsp->fsp_name);
6668 reply_nterror(req, NT_STATUS_NO_MEMORY);
6672 if(fsp->is_directory || fsp->fh->fd == -1) {
6674 * This is actually a SETFILEINFO on a directory
6675 * handle (returned from an NT SMB). NT5.0 seems
6676 * to do this call. JRA.
6678 if (INFO_LEVEL_IS_UNIX(info_level)) {
6679 /* Always do lstat for UNIX calls. */
6680 if (SMB_VFS_LSTAT(conn,fname,&sbuf)) {
6681 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_LSTAT of %s failed (%s)\n",fname,strerror(errno)));
6682 reply_unixerror(req,ERRDOS,ERRbadpath);
6686 if (SMB_VFS_STAT(conn,fname,&sbuf) != 0) {
6687 DEBUG(3,("call_trans2setfilepathinfo: fileinfo of %s failed (%s)\n",fname,strerror(errno)));
6688 reply_unixerror(req,ERRDOS,ERRbadpath);
6692 } else if (fsp->print_file) {
6694 * Doing a DELETE_ON_CLOSE should cancel a print job.
6696 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
6697 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
6699 DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
6702 send_trans2_replies(conn, req, params, 2,
6707 reply_unixerror(req, ERRDOS, ERRbadpath);
6712 * Original code - this is an open file.
6714 if (!check_fsp(conn, req, fsp)) {
6718 if (SMB_VFS_FSTAT(fsp, &sbuf) != 0) {
6719 DEBUG(3,("call_trans2setfilepathinfo: fstat of fnum %d failed (%s)\n",fsp->fnum, strerror(errno)));
6720 reply_unixerror(req, ERRDOS, ERRbadfid);
6726 if (total_params < 7) {
6727 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6731 info_level = SVAL(params,0);
6732 srvstr_get_path(ctx, params, req->flags2, &fname, ¶ms[6],
6733 total_params - 6, STR_TERMINATE,
6735 if (!NT_STATUS_IS_OK(status)) {
6736 reply_nterror(req, status);
6740 status = resolve_dfspath(ctx, conn,
6741 req->flags2 & FLAGS2_DFS_PATHNAMES,
6744 if (!NT_STATUS_IS_OK(status)) {
6745 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6746 reply_botherror(req,
6747 NT_STATUS_PATH_NOT_COVERED,
6748 ERRSRV, ERRbadpath);
6751 reply_nterror(req, status);
6755 status = unix_convert(ctx, conn, fname, False,
6756 &fname, NULL, &sbuf);
6757 if (!NT_STATUS_IS_OK(status)) {
6758 reply_nterror(req, status);
6762 status = check_name(conn, fname);
6763 if (!NT_STATUS_IS_OK(status)) {
6764 reply_nterror(req, status);
6768 if (INFO_LEVEL_IS_UNIX(info_level)) {
6770 * For CIFS UNIX extensions the target name may not exist.
6773 /* Always do lstat for UNIX calls. */
6774 SMB_VFS_LSTAT(conn,fname,&sbuf);
6776 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,fname,&sbuf)) {
6777 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of %s failed (%s)\n",fname,strerror(errno)));
6778 reply_unixerror(req, ERRDOS, ERRbadpath);
6783 if (!CAN_WRITE(conn)) {
6784 reply_doserror(req, ERRSRV, ERRaccess);
6788 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6789 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6793 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d totdata=%d\n",
6794 tran_call,fname, fsp ? fsp->fnum : -1, info_level,total_data));
6796 /* Realloc the parameter size */
6797 *pparams = (char *)SMB_REALLOC(*pparams,2);
6798 if (*pparams == NULL) {
6799 reply_nterror(req, NT_STATUS_NO_MEMORY);
6806 switch (info_level) {
6808 case SMB_INFO_STANDARD:
6810 status = smb_set_info_standard(conn,
6819 case SMB_INFO_SET_EA:
6821 status = smb_info_set_ea(conn,
6829 case SMB_SET_FILE_BASIC_INFO:
6830 case SMB_FILE_BASIC_INFORMATION:
6832 status = smb_set_file_basic_info(conn,
6841 case SMB_FILE_ALLOCATION_INFORMATION:
6842 case SMB_SET_FILE_ALLOCATION_INFO:
6844 status = smb_set_file_allocation_info(conn, req,
6853 case SMB_FILE_END_OF_FILE_INFORMATION:
6854 case SMB_SET_FILE_END_OF_FILE_INFO:
6856 status = smb_set_file_end_of_file_info(conn, req,
6865 case SMB_FILE_DISPOSITION_INFORMATION:
6866 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6869 /* JRA - We used to just ignore this on a path ?
6870 * Shouldn't this be invalid level on a pathname
6873 if (tran_call != TRANSACT2_SETFILEINFO) {
6874 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6877 status = smb_set_file_disposition_info(conn,
6886 case SMB_FILE_POSITION_INFORMATION:
6888 status = smb_file_position_information(conn,
6895 /* From tridge Samba4 :
6896 * MODE_INFORMATION in setfileinfo (I have no
6897 * idea what "mode information" on a file is - it takes a value of 0,
6898 * 2, 4 or 6. What could it be?).
6901 case SMB_FILE_MODE_INFORMATION:
6903 status = smb_file_mode_information(conn,
6910 * CIFS UNIX extensions.
6913 case SMB_SET_FILE_UNIX_BASIC:
6915 status = smb_set_file_unix_basic(conn, req,
6924 case SMB_SET_FILE_UNIX_INFO2:
6926 status = smb_set_file_unix_info2(conn, req,
6935 case SMB_SET_FILE_UNIX_LINK:
6937 if (tran_call != TRANSACT2_SETPATHINFO) {
6938 /* We must have a pathname for this. */
6939 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6942 status = smb_set_file_unix_link(conn, req, pdata,
6947 case SMB_SET_FILE_UNIX_HLINK:
6949 if (tran_call != TRANSACT2_SETPATHINFO) {
6950 /* We must have a pathname for this. */
6951 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6954 status = smb_set_file_unix_hlink(conn, req,
6960 case SMB_FILE_RENAME_INFORMATION:
6962 status = smb_file_rename_information(conn, req,
6968 #if defined(HAVE_POSIX_ACLS)
6969 case SMB_SET_POSIX_ACL:
6971 status = smb_set_posix_acl(conn,
6981 case SMB_SET_POSIX_LOCK:
6983 if (tran_call != TRANSACT2_SETFILEINFO) {
6984 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6987 status = smb_set_posix_lock(conn, req,
6988 pdata, total_data, fsp);
6992 case SMB_POSIX_PATH_OPEN:
6994 if (tran_call != TRANSACT2_SETPATHINFO) {
6995 /* We must have a pathname for this. */
6996 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7000 status = smb_posix_open(conn, req,
7009 case SMB_POSIX_PATH_UNLINK:
7011 if (tran_call != TRANSACT2_SETPATHINFO) {
7012 /* We must have a pathname for this. */
7013 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7017 status = smb_posix_unlink(conn, req,
7026 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7031 if (!NT_STATUS_IS_OK(status)) {
7032 if (open_was_deferred(req->mid)) {
7033 /* We have re-scheduled this call. */
7036 if (blocking_lock_was_deferred(req->mid)) {
7037 /* We have re-scheduled this call. */
7040 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7041 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7042 ERRSRV, ERRbadpath);
7045 if (info_level == SMB_POSIX_PATH_OPEN) {
7046 reply_openerror(req, status);
7050 reply_nterror(req, status);
7055 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7061 /****************************************************************************
7062 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7063 ****************************************************************************/
7065 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7066 char **pparams, int total_params,
7067 char **ppdata, int total_data,
7068 unsigned int max_data_bytes)
7070 char *params = *pparams;
7071 char *pdata = *ppdata;
7072 char *directory = NULL;
7073 SMB_STRUCT_STAT sbuf;
7074 NTSTATUS status = NT_STATUS_OK;
7075 struct ea_list *ea_list = NULL;
7076 TALLOC_CTX *ctx = talloc_tos();
7078 if (!CAN_WRITE(conn)) {
7079 reply_doserror(req, ERRSRV, ERRaccess);
7083 if (total_params < 5) {
7084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7088 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7089 total_params - 4, STR_TERMINATE,
7091 if (!NT_STATUS_IS_OK(status)) {
7092 reply_nterror(req, status);
7096 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7098 status = unix_convert(ctx, conn, directory, False, &directory, NULL, &sbuf);
7099 if (!NT_STATUS_IS_OK(status)) {
7100 reply_nterror(req, status);
7104 status = check_name(conn, directory);
7105 if (!NT_STATUS_IS_OK(status)) {
7106 DEBUG(5,("call_trans2mkdir error (%s)\n", nt_errstr(status)));
7107 reply_nterror(req, status);
7111 /* Any data in this call is an EA list. */
7112 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7113 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7118 * OS/2 workplace shell seems to send SET_EA requests of "null"
7119 * length (4 bytes containing IVAL 4).
7120 * They seem to have no effect. Bug #3212. JRA.
7123 if (total_data != 4) {
7124 if (total_data < 10) {
7125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7129 if (IVAL(pdata,0) > total_data) {
7130 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7131 IVAL(pdata,0), (unsigned int)total_data));
7132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7136 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7139 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7143 /* If total_data == 4 Windows doesn't care what values
7144 * are placed in that field, it just ignores them.
7145 * The System i QNTC IBM SMB client puts bad values here,
7146 * so ignore them. */
7148 status = create_directory(conn, req, directory);
7150 if (!NT_STATUS_IS_OK(status)) {
7151 reply_nterror(req, status);
7155 /* Try and set any given EA. */
7157 status = set_ea(conn, NULL, directory, ea_list);
7158 if (!NT_STATUS_IS_OK(status)) {
7159 reply_nterror(req, status);
7164 /* Realloc the parameter and data sizes */
7165 *pparams = (char *)SMB_REALLOC(*pparams,2);
7166 if(*pparams == NULL) {
7167 reply_nterror(req, NT_STATUS_NO_MEMORY);
7174 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7179 /****************************************************************************
7180 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7181 We don't actually do this - we just send a null response.
7182 ****************************************************************************/
7184 static void call_trans2findnotifyfirst(connection_struct *conn,
7185 struct smb_request *req,
7186 char **pparams, int total_params,
7187 char **ppdata, int total_data,
7188 unsigned int max_data_bytes)
7190 static uint16 fnf_handle = 257;
7191 char *params = *pparams;
7194 if (total_params < 6) {
7195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7199 info_level = SVAL(params,4);
7200 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7202 switch (info_level) {
7207 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7211 /* Realloc the parameter and data sizes */
7212 *pparams = (char *)SMB_REALLOC(*pparams,6);
7213 if (*pparams == NULL) {
7214 reply_nterror(req, NT_STATUS_NO_MEMORY);
7219 SSVAL(params,0,fnf_handle);
7220 SSVAL(params,2,0); /* No changes */
7221 SSVAL(params,4,0); /* No EA errors */
7228 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7233 /****************************************************************************
7234 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7235 changes). Currently this does nothing.
7236 ****************************************************************************/
7238 static void call_trans2findnotifynext(connection_struct *conn,
7239 struct smb_request *req,
7240 char **pparams, int total_params,
7241 char **ppdata, int total_data,
7242 unsigned int max_data_bytes)
7244 char *params = *pparams;
7246 DEBUG(3,("call_trans2findnotifynext\n"));
7248 /* Realloc the parameter and data sizes */
7249 *pparams = (char *)SMB_REALLOC(*pparams,4);
7250 if (*pparams == NULL) {
7251 reply_nterror(req, NT_STATUS_NO_MEMORY);
7256 SSVAL(params,0,0); /* No changes */
7257 SSVAL(params,2,0); /* No EA errors */
7259 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
7264 /****************************************************************************
7265 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
7266 ****************************************************************************/
7268 static void call_trans2getdfsreferral(connection_struct *conn,
7269 struct smb_request *req,
7270 char **pparams, int total_params,
7271 char **ppdata, int total_data,
7272 unsigned int max_data_bytes)
7274 char *params = *pparams;
7275 char *pathname = NULL;
7277 int max_referral_level;
7278 NTSTATUS status = NT_STATUS_OK;
7279 TALLOC_CTX *ctx = talloc_tos();
7281 DEBUG(10,("call_trans2getdfsreferral\n"));
7283 if (total_params < 3) {
7284 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7288 max_referral_level = SVAL(params,0);
7290 if(!lp_host_msdfs()) {
7291 reply_doserror(req, ERRDOS, ERRbadfunc);
7295 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
7296 total_params - 2, STR_TERMINATE);
7298 reply_nterror(req, NT_STATUS_NOT_FOUND);
7301 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
7302 ppdata,&status)) < 0) {
7303 reply_nterror(req, status);
7307 SSVAL(req->inbuf, smb_flg2,
7308 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
7309 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
7314 #define LMCAT_SPL 0x53
7315 #define LMFUNC_GETJOBID 0x60
7317 /****************************************************************************
7318 Reply to a TRANS2_IOCTL - used for OS/2 printing.
7319 ****************************************************************************/
7321 static void call_trans2ioctl(connection_struct *conn,
7322 struct smb_request *req,
7323 char **pparams, int total_params,
7324 char **ppdata, int total_data,
7325 unsigned int max_data_bytes)
7327 char *pdata = *ppdata;
7328 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
7330 /* check for an invalid fid before proceeding */
7333 reply_doserror(req, ERRDOS, ERRbadfid);
7337 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
7338 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7339 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
7340 if (*ppdata == NULL) {
7341 reply_nterror(req, NT_STATUS_NO_MEMORY);
7346 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
7347 CAN ACCEPT THIS IN UNICODE. JRA. */
7349 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
7350 srvstr_push(pdata, req->flags2, pdata + 2,
7351 global_myname(), 15,
7352 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
7353 srvstr_push(pdata, req->flags2, pdata+18,
7354 lp_servicename(SNUM(conn)), 13,
7355 STR_ASCII|STR_TERMINATE); /* Service name */
7356 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
7361 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
7362 reply_doserror(req, ERRSRV, ERRerror);
7365 /****************************************************************************
7366 Reply to a SMBfindclose (stop trans2 directory search).
7367 ****************************************************************************/
7369 void reply_findclose(struct smb_request *req)
7373 START_PROFILE(SMBfindclose);
7376 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7377 END_PROFILE(SMBfindclose);
7381 dptr_num = SVALS(req->vwv+0, 0);
7383 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
7385 dptr_close(&dptr_num);
7387 reply_outbuf(req, 0, 0);
7389 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
7391 END_PROFILE(SMBfindclose);
7395 /****************************************************************************
7396 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
7397 ****************************************************************************/
7399 void reply_findnclose(struct smb_request *req)
7403 START_PROFILE(SMBfindnclose);
7406 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7407 END_PROFILE(SMBfindnclose);
7411 dptr_num = SVAL(req->vwv+0, 0);
7413 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
7415 /* We never give out valid handles for a
7416 findnotifyfirst - so any dptr_num is ok here.
7419 reply_outbuf(req, 0, 0);
7421 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
7423 END_PROFILE(SMBfindnclose);
7427 static void handle_trans2(connection_struct *conn, struct smb_request *req,
7428 struct trans_state *state)
7430 if (Protocol >= PROTOCOL_NT1) {
7431 req->flags2 |= 0x40; /* IS_LONG_NAME */
7432 SSVAL(req->inbuf,smb_flg2,req->flags2);
7435 if (conn->encrypt_level == Required && !req->encrypted) {
7436 if (state->call != TRANSACT2_QFSINFO &&
7437 state->call != TRANSACT2_SETFSINFO) {
7438 DEBUG(0,("handle_trans2: encryption required "
7440 (unsigned int)state->call));
7441 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
7446 /* Now we must call the relevant TRANS2 function */
7447 switch(state->call) {
7448 case TRANSACT2_OPEN:
7450 START_PROFILE(Trans2_open);
7451 call_trans2open(conn, req,
7452 &state->param, state->total_param,
7453 &state->data, state->total_data,
7454 state->max_data_return);
7455 END_PROFILE(Trans2_open);
7459 case TRANSACT2_FINDFIRST:
7461 START_PROFILE(Trans2_findfirst);
7462 call_trans2findfirst(conn, req,
7463 &state->param, state->total_param,
7464 &state->data, state->total_data,
7465 state->max_data_return);
7466 END_PROFILE(Trans2_findfirst);
7470 case TRANSACT2_FINDNEXT:
7472 START_PROFILE(Trans2_findnext);
7473 call_trans2findnext(conn, req,
7474 &state->param, state->total_param,
7475 &state->data, state->total_data,
7476 state->max_data_return);
7477 END_PROFILE(Trans2_findnext);
7481 case TRANSACT2_QFSINFO:
7483 START_PROFILE(Trans2_qfsinfo);
7484 call_trans2qfsinfo(conn, req,
7485 &state->param, state->total_param,
7486 &state->data, state->total_data,
7487 state->max_data_return);
7488 END_PROFILE(Trans2_qfsinfo);
7492 case TRANSACT2_SETFSINFO:
7494 START_PROFILE(Trans2_setfsinfo);
7495 call_trans2setfsinfo(conn, req,
7496 &state->param, state->total_param,
7497 &state->data, state->total_data,
7498 state->max_data_return);
7499 END_PROFILE(Trans2_setfsinfo);
7503 case TRANSACT2_QPATHINFO:
7504 case TRANSACT2_QFILEINFO:
7506 START_PROFILE(Trans2_qpathinfo);
7507 call_trans2qfilepathinfo(conn, req, state->call,
7508 &state->param, state->total_param,
7509 &state->data, state->total_data,
7510 state->max_data_return);
7511 END_PROFILE(Trans2_qpathinfo);
7515 case TRANSACT2_SETPATHINFO:
7516 case TRANSACT2_SETFILEINFO:
7518 START_PROFILE(Trans2_setpathinfo);
7519 call_trans2setfilepathinfo(conn, req, state->call,
7520 &state->param, state->total_param,
7521 &state->data, state->total_data,
7522 state->max_data_return);
7523 END_PROFILE(Trans2_setpathinfo);
7527 case TRANSACT2_FINDNOTIFYFIRST:
7529 START_PROFILE(Trans2_findnotifyfirst);
7530 call_trans2findnotifyfirst(conn, req,
7531 &state->param, state->total_param,
7532 &state->data, state->total_data,
7533 state->max_data_return);
7534 END_PROFILE(Trans2_findnotifyfirst);
7538 case TRANSACT2_FINDNOTIFYNEXT:
7540 START_PROFILE(Trans2_findnotifynext);
7541 call_trans2findnotifynext(conn, req,
7542 &state->param, state->total_param,
7543 &state->data, state->total_data,
7544 state->max_data_return);
7545 END_PROFILE(Trans2_findnotifynext);
7549 case TRANSACT2_MKDIR:
7551 START_PROFILE(Trans2_mkdir);
7552 call_trans2mkdir(conn, req,
7553 &state->param, state->total_param,
7554 &state->data, state->total_data,
7555 state->max_data_return);
7556 END_PROFILE(Trans2_mkdir);
7560 case TRANSACT2_GET_DFS_REFERRAL:
7562 START_PROFILE(Trans2_get_dfs_referral);
7563 call_trans2getdfsreferral(conn, req,
7564 &state->param, state->total_param,
7565 &state->data, state->total_data,
7566 state->max_data_return);
7567 END_PROFILE(Trans2_get_dfs_referral);
7571 case TRANSACT2_IOCTL:
7573 START_PROFILE(Trans2_ioctl);
7574 call_trans2ioctl(conn, req,
7575 &state->param, state->total_param,
7576 &state->data, state->total_data,
7577 state->max_data_return);
7578 END_PROFILE(Trans2_ioctl);
7583 /* Error in request */
7584 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
7585 reply_doserror(req, ERRSRV,ERRerror);
7589 /****************************************************************************
7590 Reply to a SMBtrans2.
7591 ****************************************************************************/
7593 void reply_trans2(struct smb_request *req)
7595 connection_struct *conn = req->conn;
7600 unsigned int tran_call;
7601 struct trans_state *state;
7604 START_PROFILE(SMBtrans2);
7606 if (req->wct < 14) {
7607 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7608 END_PROFILE(SMBtrans2);
7612 dsoff = SVAL(req->vwv+12, 0);
7613 dscnt = SVAL(req->vwv+11, 0);
7614 psoff = SVAL(req->vwv+10, 0);
7615 pscnt = SVAL(req->vwv+9, 0);
7616 tran_call = SVAL(req->vwv+14, 0);
7618 result = allow_new_trans(conn->pending_trans, req->mid);
7619 if (!NT_STATUS_IS_OK(result)) {
7620 DEBUG(2, ("Got invalid trans2 request: %s\n",
7621 nt_errstr(result)));
7622 reply_nterror(req, result);
7623 END_PROFILE(SMBtrans2);
7628 switch (tran_call) {
7629 /* List the allowed trans2 calls on IPC$ */
7630 case TRANSACT2_OPEN:
7631 case TRANSACT2_GET_DFS_REFERRAL:
7632 case TRANSACT2_QFILEINFO:
7633 case TRANSACT2_QFSINFO:
7634 case TRANSACT2_SETFSINFO:
7637 reply_doserror(req, ERRSRV, ERRaccess);
7638 END_PROFILE(SMBtrans2);
7643 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
7644 DEBUG(0, ("talloc failed\n"));
7645 reply_nterror(req, NT_STATUS_NO_MEMORY);
7646 END_PROFILE(SMBtrans2);
7650 state->cmd = SMBtrans2;
7652 state->mid = req->mid;
7653 state->vuid = req->vuid;
7654 state->setup_count = SVAL(req->vwv+13, 0);
7655 state->setup = NULL;
7656 state->total_param = SVAL(req->vwv+0, 0);
7657 state->param = NULL;
7658 state->total_data = SVAL(req->vwv+1, 0);
7660 state->max_param_return = SVAL(req->vwv+2, 0);
7661 state->max_data_return = SVAL(req->vwv+3, 0);
7662 state->max_setup_return = SVAL(req->vwv+4, 0);
7663 state->close_on_completion = BITSETW(req->vwv+5, 0);
7664 state->one_way = BITSETW(req->vwv+5, 1);
7666 state->call = tran_call;
7668 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
7669 is so as a sanity check */
7670 if (state->setup_count != 1) {
7672 * Need to have rc=0 for ioctl to get job id for OS/2.
7673 * Network printing will fail if function is not successful.
7674 * Similar function in reply.c will be used if protocol
7675 * is LANMAN1.0 instead of LM1.2X002.
7676 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
7677 * outbuf doesn't have to be set(only job id is used).
7679 if ( (state->setup_count == 4)
7680 && (tran_call == TRANSACT2_IOCTL)
7681 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
7682 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
7683 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
7685 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
7686 DEBUG(2,("Transaction is %d\n",tran_call));
7688 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7689 END_PROFILE(SMBtrans2);
7694 if ((dscnt > state->total_data) || (pscnt > state->total_param))
7697 if (state->total_data) {
7699 if (trans_oob(state->total_data, 0, dscnt)
7700 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
7704 /* Can't use talloc here, the core routines do realloc on the
7705 * params and data. */
7706 state->data = (char *)SMB_MALLOC(state->total_data);
7707 if (state->data == NULL) {
7708 DEBUG(0,("reply_trans2: data malloc fail for %u "
7709 "bytes !\n", (unsigned int)state->total_data));
7711 reply_nterror(req, NT_STATUS_NO_MEMORY);
7712 END_PROFILE(SMBtrans2);
7716 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
7719 if (state->total_param) {
7721 if (trans_oob(state->total_param, 0, pscnt)
7722 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
7726 /* Can't use talloc here, the core routines do realloc on the
7727 * params and data. */
7728 state->param = (char *)SMB_MALLOC(state->total_param);
7729 if (state->param == NULL) {
7730 DEBUG(0,("reply_trans: param malloc fail for %u "
7731 "bytes !\n", (unsigned int)state->total_param));
7732 SAFE_FREE(state->data);
7734 reply_nterror(req, NT_STATUS_NO_MEMORY);
7735 END_PROFILE(SMBtrans2);
7739 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
7742 state->received_data = dscnt;
7743 state->received_param = pscnt;
7745 if ((state->received_param == state->total_param) &&
7746 (state->received_data == state->total_data)) {
7748 handle_trans2(conn, req, state);
7750 SAFE_FREE(state->data);
7751 SAFE_FREE(state->param);
7753 END_PROFILE(SMBtrans2);
7757 DLIST_ADD(conn->pending_trans, state);
7759 /* We need to send an interim response then receive the rest
7760 of the parameter/data bytes */
7761 reply_outbuf(req, 0, 0);
7762 show_msg((char *)req->outbuf);
7763 END_PROFILE(SMBtrans2);
7768 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
7769 SAFE_FREE(state->data);
7770 SAFE_FREE(state->param);
7772 END_PROFILE(SMBtrans2);
7773 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7777 /****************************************************************************
7778 Reply to a SMBtranss2
7779 ****************************************************************************/
7781 void reply_transs2(struct smb_request *req)
7783 connection_struct *conn = req->conn;
7784 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
7785 struct trans_state *state;
7787 START_PROFILE(SMBtranss2);
7789 show_msg((char *)req->inbuf);
7792 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7793 END_PROFILE(SMBtranss2);
7797 for (state = conn->pending_trans; state != NULL;
7798 state = state->next) {
7799 if (state->mid == req->mid) {
7804 if ((state == NULL) || (state->cmd != SMBtrans2)) {
7805 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7806 END_PROFILE(SMBtranss2);
7810 /* Revise state->total_param and state->total_data in case they have
7811 changed downwards */
7813 if (SVAL(req->vwv+0, 0) < state->total_param)
7814 state->total_param = SVAL(req->vwv+0, 0);
7815 if (SVAL(req->vwv+1, 0) < state->total_data)
7816 state->total_data = SVAL(req->vwv+1, 0);
7818 pcnt = SVAL(req->vwv+2, 0);
7819 poff = SVAL(req->vwv+3, 0);
7820 pdisp = SVAL(req->vwv+4, 0);
7822 dcnt = SVAL(req->vwv+5, 0);
7823 doff = SVAL(req->vwv+6, 0);
7824 ddisp = SVAL(req->vwv+7, 0);
7826 state->received_param += pcnt;
7827 state->received_data += dcnt;
7829 if ((state->received_data > state->total_data) ||
7830 (state->received_param > state->total_param))
7834 if (trans_oob(state->total_param, pdisp, pcnt)
7835 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
7838 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
7842 if (trans_oob(state->total_data, ddisp, dcnt)
7843 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
7846 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
7849 if ((state->received_param < state->total_param) ||
7850 (state->received_data < state->total_data)) {
7851 END_PROFILE(SMBtranss2);
7855 handle_trans2(conn, req, state);
7857 DLIST_REMOVE(conn->pending_trans, state);
7858 SAFE_FREE(state->data);
7859 SAFE_FREE(state->param);
7862 END_PROFILE(SMBtranss2);
7867 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
7868 DLIST_REMOVE(conn->pending_trans, state);
7869 SAFE_FREE(state->data);
7870 SAFE_FREE(state->param);
7872 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7873 END_PROFILE(SMBtranss2);